当前位置: 首页 > news >正文

Vue 组件二次封装透传slots、refs、attrs、listeners

最近写了一个开源项目,有些地方需要二次封装,需要透传一些数据,需要注意的是ref,我这里使用俩种方式间接传递ref,具体如下:

使用:

import VideoPlayer from './index.js'Vue.use(VideoPlayer)

index.js因为是Vue 2.7 老项目,所以这里用Vue.extend构造函数构造组件这里和 Vue3 不太一样,Vue3 要用 defineComponent创建组件支持hook式和选项式,废弃了Vue.extend(),这里属性继承用$attrs, 事件用 $listeners(Vue3 不需要,在attrs里面),插槽这里固定指定了一个ocr作用域插槽,refs后面说

import Player from "video-player"
import OcrResult from "@/components/ocrResult"
import Vue from "vue"let P = Vue.extend({data() { return { isEnableOcr: true, // 是否启用ocrisEnableWaterMarker: true, // 是否启动水印waterMarkerContent: '水印' // 水印内容} }template: `<Player ref="player"v-bind="$attrs"v-on="$listeners":isEnableOcr="isEnableOcr":isEnableWaterMarker="isEnableWaterMarker":waterMarkerContent="waterMarkerContent"><template v-if="isEnableOcr" #ocr="{ show_ocr, curPlayTime, cancel }"><ocrResultv-model="show_ocr":curPlayTime="curPlayTime * 1000"@cancel="cancel"/></template></Player >`,
})export default {install(Vue) {Vue.component('VideoPlayer', VideoPlayer)}
}

这里如果涉及到多个slot插槽,利用#[name]动态插槽,scope返回作用域插槽数据:

 <template v-for="(_, name) in $slots" #[name]="scope"><slot :name="name" v-bind="scope"></slot></template>

这里涉及到 refs,因为 refs``Vue没有做处理,不想 reactforwardRef,我的处理方式,提前已知组件暴露出什么数据,遍历获取,反之全部遍历获取:

// 透传ref属性,这里劫持下,不然会报错
let attributes = ['_register_emits', 'current', 'duration']attributes.forEach(key => {Object.defineProperty(this, key, {get() {return Reflect.get(this.$refs.player, key, this)},set(v) {throw new Error('Not Allow!')}})
})// for (let key in this.$refs.player) {
//   this[key] = this.$refs.player[key]
// }

还有一种方式,利用render函数渲染 vnode,这样做少去了编译过程,Vue拿到节点compireAST,进而打标记最后生成render函数,render函数渲染时当前利用Vue.extend()生成的组件实例会自动绑定this,而template不会这么做

render(h) {let scopedSlots = {}if (this.isEnableOcr) {scopedSlots.ocr = ({ show_ocr, curPlayTime, cancel }) => {return h(ocrResult, {props: {value: show_ocr,curPlayTime: curPlayTime * 1000},on: {input: (val) => { show_ocr = val; },cancel}});};}return h(Player, {attrs: this.$attrs,on: this.$listeners, // 添加 $listenersprops: {isEnableOcr: this.isEnableOcr,isEnableWaterMarker: this.isEnableWaterMarker,waterMarkerContent: this.waterMarkerContent},scopedSlots})}
http://www.dtcms.com/a/333588.html

相关文章:

  • 【Spring框架】SpringAOP
  • Ubuntu 22.04 安装PCL(Point Cloud Library)和Eigen库
  • 基于 Ubuntu22.04 安装 SSH 服务,记录
  • 如何实现免密码 SSH 登录
  • 零基础-动手学深度学习-10.4. Bahdanau 注意力
  • week1-[一维数组]传送
  • python-pycharm切换python各种版本的环境与安装python各种版本的环境(pypi轮子下载)
  • Linux下的软件编程——多任务(线程)
  • QT开发中如何加载第三方dll文件
  • C语言指针(五):回调函数与 qsort 的深层关联
  • 前端性能优化
  • JCTools 无锁并发计数器:ConcurrentAutoTable
  • obsidian ai/copilot 插件配置
  • epoll边缘模式收数据学习
  • 【100页PPT】数字化转型某著名企业集团信息化顶层规划方案(附下载方式)
  • 基于之前的Python附魔插件做出的一些改进
  • 3s岗位合集
  • 并行Builder-输出型流程编排的新思路
  • AI提高投放效率的核心策略
  • 【生产实践】内网YUM源中rpm包的替换与仓库升级实战
  • 应用侧华为云LoTDA设备接入平台
  • 2025二建成绩公布!各地合格标准汇总!
  • 通俗易懂:Vue3的ref()运行机理
  • Windows Server存储智能数据校验
  • AMQP协议介绍
  • 【进阶】Java技术栈八股文学习资料整理
  • 优化网络ROI:专线复用,上云出网一“线”牵!
  • 力扣top100(day04-04)--栈
  • 从“写代码”到“定义需求”:AI编程工具如何重构软件开发的核心流程?
  • 深度学习-卷积神经网络-ResNet 残差网络