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.…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
