??Vue"非常规"技巧, ??99%的人是第一次看
2020/3/5 11:02:39
本文主要是介绍??Vue"非常规"技巧, ??99%的人是第一次看,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
让"原生Event"与"v-on"玩出花
一句话理解"Event": 类似vue中$emit
, 使用new Event
可以创建浏览器的原生事件,通过使用addEventListener
监听事件.
简单使用:
// 监听 el.addEventListener('abc', onAbc); // 创建事件 const event = new Event(type); // 派发事件对象 el.dispatchEvent(event); 复制代码
这和Vue有什么关系?
看, 这样给组件绑定事件很常见:
<my-scroll @scroll-reach-bottom="onScrollReachBottom"/> 复制代码
但是如果不是组件是一个html元素呢?
<div @scroll-reach-bottom="onScrollReachBottom"/> 复制代码
要实现上例就需要用到自定义事件(Event).
为什么不用"组件"?
以"拖拽组件"为例, 众所周知组件至少有一个元素(根), 那么如果我们使用"拖拽组件":
<my-drag> <span>待拖拽</span> </my-drag> <!--实际dom结构--> <div> <span>待拖拽</span> </div> 复制代码
可以看到组件破坏了dom结构, 使用时可能会直接影响样式, 所以很多vue插件都使用了"vue指令"解决这个问题.
更好的"vue指令"
这个是饿了么ui的InfiniteScroll(无限滚动)指令:
<ul v-infinite-scroll="load" infinite-scroll-distance="10" infinite-scroll-delay="10"> <li v-for="i in count">{{ i }}</li> </ul> 复制代码
export default{ directives:{ infiniteScroll } } 复制代码
对比下如果用Event实现后:
<ul @infinite-scroll="load"> <li v-for="i in count">{{ i }}</li> </ul> 复制代码
export default{ mounted(){ const is = new InfiniteScroll(this.$el,{ distance:10, delay:10 }); this.$on('hook:destroy', is.destroy); } } 复制代码
说实话没对使用者差别不太大, 无非就是"@"语义看起来稍微好点, 但是销毁需要自己手动触发.
但是如果你编写过"vue指令", 你应该还记得vue对指令的"钩子函数"的设计并不是特别友好, 需要自己实现钩子间的数据管理, 不优雅.
但是用了Event
方式, 你可以把自己的组件做成构造函数, 上面的"状态管理"问题就好解决了, 而且你这样写出的代码就不局限于是vue插件了, 他就是一个普通的js插件, 可以用在任何框架下.
当然指令的"修饰符"等概念还是很吸引人的, 如果需要可以结合Event
和"vue指令"一起用, 如虎添翼.
如何使用Event?
定义事件'abc', 并给事件对象赋值:
// 注册监听 el.addEventListener('abc', event=>{ 'abc' === event.type // true 1 === event.a // true }); // 创建事件 const event = new Event(type, { // 事件是否可以冒泡, 默认false bubbles: false, // 事件是否可以取消(使用preventDefault时), 默认false cancelable: false, // 事件是否会在影子DOM根节点之外触发侦听器, 默认false, // 此属性涉及原生web component, 欲深入了解web component请查阅mdn composed: false }); // 修改事件对象的值 Object.assign(event, {a:1,b:2}); // 派发事件对象 el.dispatchEvent(event); 复制代码
cancelable实例
el.addEventListener('abc', event=>{ // 受到cancelable控制 // cancelable === false时, // preventDefault()无效 event.preventDefault(); }); 复制代码
bubbles实例
parent.appendChild(el); el.addEventListener('abc', event=>{ // event.stopPropagation(); }); parent.addEventListener('abc', event=>{ // 受到bubble控制 // bubble === false时, // 子元素绑定的事件回调中, // 有没有event.stopPropagation()都不触发 }); 复制代码
兼容
Event
对低版本不兼容, 但是mdn上已经明确写出, 未来的浏览器都会以Event
作为标准, 所以我们还要结合老语法做下兼容.
createEvent
const event = document.createEvent('HTMLEvents'); // 参数意义和new Event一样 event.initEvent(type, bubbles, cancelable); 复制代码"灰色"代表"未知", 但是可以放心使用, 因为vue2.6的源码中关于"v-model"部分多处使用了
createEvent
说明应该可以兼容到ie9.
兼容代码
function dispatchDOMEvent(el, payload, eventInit){ let event; if (void 0 !== Event) { event = new Event(type, eventInit); } else { event = document.createEvent('HTMLEvents'); event.initEvent(type, eventInit?.bubbles, eventInit?.cancelable); } return el.dispatchEvent(event); } 复制代码
我的应用
其实这种方式和vue配合也是偶然发现, 不是什么复杂的东西, 只是一般不会往这上面想.
我做了一个✋手势库用这种方式实现在vue下和"v-on"配合:
✋手势库: github.com/any86/any-t…🔥typescript系列课程
如果你对ts感兴趣了, 欢迎看看我的ts基础教程.
特别篇, 在vue3🔥源码中学会typescript🦕 - "is"
第六课, 什么是声明文件(declare)? 🦕 - 全局声明篇
新手前端学🔥typescript - 实战篇, 实现浏览器全屏(59行)
微信群
感谢大家的阅读, 如有疑问可以加我微信, 我拉你进入微信群(由于腾讯对微信群的100人限制, 超过100人后必须由群成员拉入)
这篇关于??Vue"非常规"技巧, ??99%的人是第一次看的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04package.json 文件位置在哪?-icode9专业技术文章分享
- 2024-10-01Craco.js学习:从入门到实践指南
- 2024-10-01Create-React-App学习:入门与实践指南
- 2024-10-01CSS-in-JS学习:从入门到实践指南
- 2024-09-30JSX语法学习:从入门到初步掌握
- 2024-09-30Mock.js学习:入门教程与实战演练
- 2024-09-30React Hooks学习:从入门到实践
- 2024-09-30受控组件学习:React中的基础入门教程
- 2024-09-29JS定时器教程:初学者必看指南
- 2024-09-29JS对象教程:初学者的全面指南