Vue3学习(六)Vue3 + ts几种写法
前言
官网提到组合式api和选项式api
选项式api其实就是vue2的写法,组合式api是vue3的新写法(组合式api可以在script中使用setup()也可以使用<script setup>,<script setup>是setup()的语法糖,语法糖的写法在vue3.2后才支持)
参考
Vue3官网的一些文章
Vue3语法官网教程
官网迁移教程 (Vue2和Vue3差异点)
组合式api setup()用法
单文件组件 <sctipt setup>用法
Vue3使用setup()函数核心API写法
vue3中使用TypeScript
Vue3结合TS项目开发实践总结
Vue3写法总结
Vue3种使用<script setup>语法糖核心API写法
上手后才知道 ,Vue3 的 script setup 语法糖是真的爽
Vue3 中setup()和<script setup></script>
Vue3 <script setup>语法糖+ts+Hook实践探索
Vue3一些API用法
vue3 ref函数用法
Vue3中ref和reactive的区别
Vue3第一篇之ref和reactive详解扩展
实战
Vue3使用setup()函数
<script lang="ts"> import { defineComponent, onMounted, ref, watch, nextTick, computed, onBeforeUnmount } from '@vue/composition-api'; import { useVisibility } from '@live/hooks/src/useVisibility'; import { toWorkVideoPage, getCookie, parseQuery, toLiveRoomByUserId, openProfile, osName, query } from '@live/actions'; import { throttle, isInLiveRoom, isLowDeviceBiz } from '../../utils/init'; import { BOOKSTATUS, ENROLLSTATUS, EVENTSTATUS } from '../../schemas'; import loadingsvg from './img/loading.svg'; import type { PropType } from '@vue/composition-api'; import type { TTabPhotoList, TEventList, TTabs } from '../../schemas'; // import LoadingIcon from '@/components/LoadingIcon/index.vue'; import { showToast } from '@/utils/init'; import { sendShow, sendClick } from '@/logs/index'; import TabSwiper from '@/components/TabSwiper/index.vue'; // import LottieIcon from '@/components/LottieIcon/index.vue';export default defineComponent({components: {Swiper,Sticky,// LottieIcon,TabSwiper,// LoadingIcon,LottieIcon: () => import(/* webpackChunkName:"lottie-icon" */ '@/components/LottieIcon/index.vue'),},props: {tabPhotoList: {type: Array as PropType<TTabPhotoList[]>,default: () => [],},currentTabIndex: {type: Number,default: 0,},bookStatusLoading: {type: Boolean,default: false,},},emits: ['updateCurrentTabIndex', 'handleEnroll', 'handleBook',],setup(props, { emit }) {const swiperPanelRef = ref();const currentSwiperPanelIndex = ref(0);const setTimeoutId = ref();// 当前页面是否可见,settimeout中需要判断是否播放视频const isVisibility = ref(true);// 当前video是否可见,只有video可见 && 页面可见才播放视频const isVisibilityVideo = ref(true);const swiperPannelItemRef = ref();const laterRender = ref(false);setTimeout(() => {laterRender.value = true;});watch([() => props.currentTabIndex],() => {if (currentSwiperPanelIndex.value === 0) {sendShow(getPanelShowLog(0));}},{immediate: false,},);// 自动播放第一个视频onMounted(() => {sendShow(getPanelShowLog(0));handleVideoPlay();// 离开可视区不播放视频const io = new IntersectionObserver(res => {if (res[0].intersectionRatio > 0) {isVisibilityVideo.value = true;handleVideoPlay();} else {isVisibilityVideo.value = false;isVisibility.value = true;videoStop();}});io.observe(document.querySelector('.swiper-panel-main')!);});onBeforeUnmount(() => {videoStop();});useVisibility({visibleHandler: () => {console.log('----visibleHandler-00-0---');isVisibility.value = true;// 此处安卓端未生效,代码执行到,但是视频没有重新播放// if (osName !== 'android') { // fix 安卓偶先播放状态下漏出封面图// pc,ios,androidhandleVideoPlay(1000, false);// }},hiddenHandler: () => {isVisibility.value = false;console.log('----hiddenHandler-00-0---');// 此处安卓端未生效,代码执行到,但是视频没有因此暂停// if (osName !== 'android') {videoStop(false);// }},});// const videoVisibilityCallBack =const eventListByIndex = computed<TEventList[]>(() => {return (props.tabPhotoList[props.currentTabIndex] as TTabPhotoList).eventList || [];});const tabsByTabPhotoList = computed<TTabs[]>(() => {return props?.tabPhotoList?.map((item: TTabPhotoList) => {return {tabTitle: item?.tabTitle,tabCode: item?.tabCode,selectedTitle: item?.selectedTitle,};});});const onSwiperTabsChange = (index: number) => {// currentSwiperTabsIndex.value = index;emit('updateCurrentTabIndex', index);currentSwiperPanelIndex.value = 0;swiperPanelRef?.value?.to(0);handleVideoPlay();};const getPanelShowLog = (index: number) => {const event: any = (props as any).tabPhotoList[props.currentTabIndex].eventList[index];return {action: 'BLIND_DATE_VENUE_VIDEO_CARD',params: {author_id: event.authorInfo.userInfo.user_id,id: event.eventId,status: event.eventStatus,tab_name: props.tabPhotoList[props.currentTabIndex].tabTitle,video_id: event.photo.photoId,},};};const onSwiperPanelChange = (index, lastIndex) => {sendShow(getPanelShowLog(index));currentSwiperPanelIndex.value = index;handleVideoPlay();};const videoStop = (isInitPoster = true) => {try {if (isInLiveRoom()) {return;}// 暂停隐藏封面if (isInitPoster) {initPoster();}const dom = document.querySelectorAll('.swiper-panel-item video');dom.forEach((item: HTMLVideoElement) => {item?.pause();// item?.load();console.log('stop', item.className);});} catch (e) {console.log('error', 'videostop', e);}};/*** 播放视频处理:ref不太满足播放控制,采用document.querySelectorAll直接获取dom* 1.涉及到过渡动画,影响getBoundingClientRect计算,所以await nextTick();* 2.因为支持轮播,可能存在两个activitydom都处于选中状态,因此需要用for循环找到一个距离屏幕中心最近的item* inShowPoster: 安卓端点击视频跳转再次回到h5时候,封面会闪一下(不会暂停1s后播放),次case不隐藏封面*/const handleVideoPlay = (timeOut = 1000, isInitPoster = true) => {if (isInLiveRoom()) {return;}// fix 快速切换导致业务卡顿clearTimeout(setTimeoutId.value);videoStop(isInitPoster);setTimeoutId.value = setTimeout(() => {try {videoStop(isInitPoster);// console.error(' settimeout transform------', document.querySelector('.spu-swiper-inner').style.transform);if (isVisibility.value && isVisibilityVideo.value ) {const targetDom = getCurrentVideo();// play调用失败或者多次调用触发异常(The operation was aborted)targetDom?.play()?.catch(e => {console.log(e);});}} catch (e) {console.log('error', e);}}, timeOut);};const getCurrentVideo = () => {const activeDom = document.querySelectorAll('.swiper-panel-item.is-active video');const target = window.innerWidth / 2;let targetDom = activeDom?.[0] as HTMLVideoElement;let distance = Number.MAX_VALUE;for (const item of activeDom) {const left = item.getBoundingClientRect().left;if (Math.abs(left - target) < distance) {distance = Math.abs(left - target);targetDom = item as HTMLVideoElement;}}return targetDom;};const initPoster = () => {//const domPoster = document.querySelectorAll<HTMLElement>('.item-video-living.videoPoster');domPoster.forEach(item => {item && (item.style.opacity = '1');});};const toWorkVideoPageFn = (eventId: number, photoId: string, userId: string, eventStatus: number) => {if (isInLiveRoom()) {return;}sendClick({action: 'BLIND_DATE_VENUE_VIDEO_CARD',params: {author_id: userId,id: eventId,status: eventStatus,tab_name: props.tabPhotoList[props.currentTabIndex].tabTitle,video_id: photoId,},});// videoStop();toWorkVideoPage(photoId, '');};const handleBook = throttle((isCancel:boolean, eventId: number, userId: number, photoId: string) => {console.log('handleBook', isCancel, eventId, userId, photoId);if (!props.bookStatusLoading) { // 网络请求阶段bookStatusLoading为trueemit('handleBook', isCancel, eventId, userId, photoId);}}, 1000);const handleEnroll = throttle((isCancel:boolean, eventId: number, userId: number, photoId: string) => {console.log('handleEnroll', isCancel, eventId, userId, photoId);emit('handleEnroll', isCancel, eventId, userId, photoId);}, 1000);const handleOnline = (userId: number) => {// videoStop();const { authorId } = query;if ( String(authorId) === String(userId)) {showToast('已经在当前直播间');return;}if (userId) {toLiveRoomByUserId(String(userId), {liveSource: 'BLIND_DATE_CNY_PAGE_BUTTON',sourceType: 269,});}};const openProfileFn = (userId: number) => {// videoStop();openProfile(String(userId));};const onVideoWaiting = (id: string) => {// loadingconst domLoading = document.querySelectorAll<HTMLElement>(`.${id}`);domLoading.forEach(item => {item && (item.style.opacity = '1');});console.log('onVideoWaiting', id);};// 性能考虑,不采用display,用opacityconst onVideoPlaying = (id: string) => {try {// 关闭loadingconst domLoading = document.querySelectorAll<HTMLElement>(`.${id}`);domLoading.forEach(item => {item && (item.style.opacity = '0');});// 关闭posterconst domPoster = document.querySelectorAll<HTMLElement>(`.${id}_poster`);domPoster.forEach(item => {item && (item.style.opacity = '0');});const video = getCurrentVideo();video && (video.muted = false);} catch (e) {console.log('onVideoPlaying', e);}};const onVideoOtherEvent = throttle((name: string, id: string) => {if (name === 'timeupdate') {const dom = getCurrentVideo();if (dom?.readyState < 4 ) {onVideoWaiting(id);} else {onVideoPlaying(id);}}}, 1000);// 不是低端机 && 不在直播间const isShowVideo = () => {return !isLowDeviceBiz() && !isInLiveRoom();};const oneventvideo = (name, id) => {// const dom = getCurrentVideo();// console.log('name', name, id, dom.readyState);if (name === 'canplaythrough') {try {// 关闭loadingconst domLoading = document.querySelectorAll<HTMLElement>(`.${id}`);domLoading.forEach(item => {item && (item.style.opacity = '0');});} catch (e) {console.log('onVideoPlaying', e);}}};// 当前dom节点改变:loop模式下,边界场景下视觉上未切换,实际已切换,此时会出现有声音,无画面情况,此case需要重新播放视频const onDomChangePanel = (index, lastIndex) => {handleVideoPlay();};const getTextInfo = (title: string) => {return title.indexOf('「') === 0;};return {swiperPanelRef,currentSwiperPanelIndex,onSwiperTabsChange,onSwiperPanelChange,toWorkVideoPageFn,eventListByIndex,tabsByTabPhotoList,handleBook,handleEnroll,handleOnline,openProfileFn,isInLiveRoom,BOOKSTATUS,ENROLLSTATUS,EVENTSTATUS,onVideoWaiting,onVideoPlaying,loadingsvg,isShowVideo,swiperPannelItemRef,oneventvideo,onVideoOtherEvent,onDomChangePanel,getTextInfo,laterRender,};}, }); </script>
相关文章:

Vue3学习(六)Vue3 + ts几种写法
前言 官网提到组合式api和选项式api 选项式api其实就是vue2的写法,组合式api是vue3的新写法(组合式api可以在script中使用setup()也可以使用<script setup>,<script setup>是setup(ÿ…...

【前端】ES6:Proxy代理和Reflect对象
文章目录 1 Proxy代理1.1 get方法1.2 set方法1.3 has方法1.4 this问题 2 Reflect对象2.1 代替Object的某些方法2.2 修改某些Object方法返回结果2.3 命令式变为函数行为2.4 配合Proxy 1 Proxy代理 Proxy如其名,它的作用是在对象和和对象的属性值之间设置一个代理&am…...

基于微信开发助手企鹅音乐微信小程序的设计与实现(源码+文档+讲解)
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...

学习Spring Boot,应该从哪里开始学起
文章目录 前言1. Java基础2. Spring框架基础3. Spring Boot入门4. 搭建Spring Boot项目5. 编写RESTful API6. 数据库操作7. 安全性和测试8. 部署和运维9. 实践和项目总结前言 学习Spring Boot,应该从哪里开始学起 学习Spring Boot,你可以从以下几个步骤开始学起: 1. Java基…...

【JavaEE初阶】深入解析死锁的产生和避免以及内存不可见问题
前言: 🌈上期博客:【后端开发】JavaEE初阶—线程安全问题与加锁原理(超详解)-CSDN博客 🔥感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 ⭐️小编会在后端开发的学习中不断更新~~~ &#…...

企微群管理软件:构建高效社群运营的新引擎
在数字化营销日益盛行的今天,企业微信(简称“企微”)群作为企业与用户直接互动的重要平台,其管理与运营效率直接关系到企业的品牌形象、用户满意度及市场影响力。企微群管理软件,作为专为企微社群设计的高效管理工具&a…...

CORE 中间件、wwwroot
ASP.NET Core中间件组件是被组装到应用程序管道中以处理HTTP请求和响应的软件组件(从技术上来说,组件只是C#类)。 ASP.NET Core应用程序中的每个中间件组件都执行以下任务。 选择是否将 HTTP 请求传递给管道中的下一个组件。这可…...

SpringBoot 与 Maven 快速上手指南
SpringBoot 与 Maven 快速上手指南 在Java开发领域,Spring Boot和Maven是两个极其重要的工具,它们极大地简化了企业级应用的开发和构建过程。Spring Boot通过自动配置和起步依赖等特性,让开发者能够快速搭建起一个Spring应用;而M…...

大觅网之自动化部署(Automated Deployment of Da Mi Network)
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…...

【C++】入门基础知识-1
🍬个人主页:Yanni.— 🌈数据结构:Data Structure. 🎂C语言笔记:C Language Notes 🏀OJ题分享: Topic Sharing 目录 前言: C关键字 命名空间 命名空间介…...

Redis一些简单通用命令认识常用数据类型和编码方式认识Redis单线程模型
通用命令 get() / set() 这是Redis中两个最为核心的命令。 set插入 这里的key 和 value都是字符串,我们可以加双引号 或者单引号,或者不加。 get查找 如果查询的key值不存在,那么会返回一个 nil ,也就是代表空 在Redis中命令…...

使用电子模拟器 Wokwi 运行 ESP32 示例(Arduino IDE、VSCode、ESP32C3)
文章目录 Wokwi 简介安装客户端(Mac/Linux)创建 Token Arduino IDEVSCode 配置安装 wokwi 插件打开编译后目录 ESP32C3 示例Arduino IDE创建模拟器运行模拟器 Wokwi 简介 Wokwi 是一款在线电子模拟器。您可以使用它来模拟 Arduino、ESP32、STM32 以及许…...

C嘎嘎入门篇:类和对象(1)
前言: 小编在之前讲述了C的部分入门基础,读者朋友一定要掌握好那些,因为C的学习和C有点不同,C的知识都是比较连贯的,所以我们学好了前面才可以学习后面的内容,本篇文章小编将会讲述C真正的入门篇࿱…...

tomcat服务搭建部署ujcms网站
tomcat服务搭建部署ujcms网站 关闭selinux和防火墙 setenforce 0 && systemctl stop firewalld安装java环境 #卸载原有java8环境 yum remove java*#上传java软件包,并解压缩 tar -xf openjdk-11.0.1_linux-x64_bin.tar.gz && mv jdk-11.0.1 jdk11…...

unity_Occlusion_Culling遮挡剔除学习
unity_Occlusion_Culling遮挡剔除学习 文档: https://docs.unity.cn/cn/2019.4/Manual/occlusion-culling-getting-started.html没彻底搞明白,但是会用,虽然也不熟练 设置遮挡剔除 打开遮挡剔除面板 设置场景物体。设置为静态 设置场景 烘…...

vue初学随笔
Vue基础 Vue基本概念 Vue是什么 Vue是一个渐进式的JavaScript框架,它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。 渐进式:各个特性可以根据项目需要逐渐引入和…...

IDEA Dependency Analyzer 分析 maven 项目包的依赖
一、场景分析 javax.validation 是我们 SpringMVC 常用的数据校验框架。但是 javax.validation 是一个规范(Java Bean Validation,简称 JSR 380),它并没有具体的实现,它的常用实现,是hibernate-validator。…...

微信小程序 - 最新详细安装使用 Vant weapp UI 框架环境搭建详细教程
前言 自从 2024 年开始,小程序做了很多改变和升级, 导致网上很多搭建教程文章的教程失效了,本文来做最新的教程。 第一步 为了更贴合新手,我这里创建了一个纯净无任何业务代码的小程序项目。...

【C语言】手把手带你拿捏指针(完)(指针笔试、面试题解析)
文章目录 一、sizeof和strlen的对⽐1.sizeof2.strlen3.sizeof与strlen对比 二、数组和指针笔试解析1.一维数组2.字符、字符串数组和字符指针代码1代码2代码3代码4代码5代码6 3.二维数组4.总结 三、指针运算笔试题解析代码1代码2代码3代码4代码5代码6 一、sizeof和strlen的对⽐ …...

Vue中input框自动聚焦
在Vue中input自动聚焦的思路: 给需要聚焦的input设置ref <el-inputv-model"loginForm.username"ref"userNameInput"name"username"type"text"auto-complete"on"placeholder"username"keyup.enter.…...

基于Node.js+Express+MySQL+VUE实现的计算机毕业设计旅游推荐网站
猜你喜欢评论 登录注册搜索 推荐定制景点/springboot/javaWEB/J2EE/MYSQL数据库/vue前后分离小程序 功能图如下所示: 一、设计目标 本次计算机毕业设计项目的主要目标是设计和开发一款功能完善、用户友好的旅游推荐网站。该网站旨在为广大旅游爱好者提供一个便捷、…...

已存在的Python项目使用依赖管理工具UV
1. 文档 uv文档 2. 如何转换 初始化 uv initrequirements.txt转换成pyproject.toml uv add $(cat requirements.txt)删除requirements.txt 如果更新pyproject.toml之后,使用命令 uv sync替换项目环境 如果有库没有加入依赖,自己手动加一下&am…...

JavaWeb美食推荐管理系统
目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 spring-mybatis.xml3.5 spring-mvc.xml3.5 login.jsp 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优…...

如何像专家一样修复任何 iPhone 上的“iPhone 已禁用”错误
“我忘记了密码,并且我的 iPhone 在多次输入错误密码后就被禁用了,如何再次访问我的手机?” 作为最安全的数字设备之一,iPhone 必须使用正确的密码解锁。即使您可以使用 Face ID 或 Touch ID 访问您的设备,在充电或重…...

django drf to_representation
使用场景 1.需要对结果的中的某个字段进行进一步的处理; 2.模型类中没有的字段,添加到结果中进行响应; 例子 from django.db import modelsclass TestModel(models.Model):name models.CharField(_("名称"), max_length50, nul…...

2024最新国内镜像源设置(npm、yarn、pnpm)
淘宝镜像源https://registry.npmmirror.com/ 腾讯云镜像源https://mirrors.cloud.tencent.com/npm/ cnpm是一个基于npm的中国镜像源https://r.cnpmjs.org/ # 查询当前使用的镜像源 npm get registry# 设置为淘宝镜像源 npm config set registry https://registry.npmmirror.co…...

Java线程池和原子性
文章目录 前言1 线程池1.1 线程池概述1.1.1 线程池存在的意义1.1.2 Executors默认线程池 1.2 线程状态介绍1.2.1 线程状态源码1.2.2 线程状态含义1.2.3 线程状态转换图 2 原子性2.1 volatile关键字2.2 synchronized解决2.3 原子性2.4 AtomicInteger类2.5 悲观锁和乐观锁 前言 …...

【数据评估与清洗】对数据结构和内容进行清洗
评估数据 结构方面 需要清理:乱数据不需要清理:整洁数据 每列是一个变量每行是一个观察值每个单元格是一个值 内容方面 需要清理:脏数据 丢失数据重复数据不一致数据无效或错误数据 不需要清理:干净数据 # 获取整体信息 df.in…...

机器学习和深度学习的区别
1. 基本概念 1.1 机器学习定义 机器学习是人工智能的一个核心分支,它赋予计算机系统无需明确编程即可学习和改进的能力。通过分析大量数据,机器学习算法能够识别数据中的模式和趋势,从而做出预测或决策。这种方法通常涉及统计模型和优化技术…...

UE虚幻引擎云渲染汽车动画的优势!
在汽车广告和动画制作领域,虚幻引擎(UE)结合云渲染技术正掀起一场技术革命。这项技术以其高性能、成本效益和灵活性,为创作者提供了强大的工具,以实现更加逼真和高效的汽车动画制作。 一、为什么选择UE虚幻引擎制作汽车…...