Vue—关于插件(源码级别的插件分析+实践)
Vue插件的原理基于Vue的`use`方法,该方法接收一个函数或者提供`install`方法的源码对象作为参数,如果传入的解析参数是函数,这个函数会被当作`install`方法。源码在Vue 2.6.版本中,解析app源码打包`use`方法内部使用`initUse`函数给Vue添加了一个静态方法`use`。源码以vuex为例,解析它暴露了一个`install`方法,源码通过`Vue.use(vuex)`来安装插件。解析vuex的源码`install`函数会调用`applyMixin`函数,并将Vue传递过去。解析`applyMixin`函数在Vue 2.x版本中会直接使用`Vue.mixin`来扩展功能,源码通过在组件的解析`beforeCreate`钩子中初始化vuex插件。
在Vue中使用混入(mixin)是源码一种设计模式,可以轻松地被子类继承功能,目的是实现函数复用。Vue中也应用了这一设计模式,通过`Vue.mixin`可以用来分发可复用逻辑。混入可以分为全局混入和局部混入,全局混入会影响所有的Vue实例,如果组件中与mixin中具有同名的属性,会进行选项合并,除了生命周期外,其它的所有属性都会被组件自身的属性覆盖。使用混入可以节省代码量,类似于类继承。
要自己实现一个提示框插件,好友买卖游戏源码可以通过`this.$notify()`进行调用,并且可以传入自定义模板。创建一个Vue工程,在`src`目录下新建`plugin`目录,然后创建一个`notify`目录,新建`index.js`和`Notify.vue`。在`index.js`中,引入`Notify.vue`组件,并通过`install`方法中注入的Vue来完成功能。实例挂载之后才可以访问`$el`选项,可以通过`Vue.use`来使用插件,然后在App.vue中验证功能是否正常。要实现传入模板并且显示出来,可以通过`$mount` API手动挂载一个实例,并在调用`$notify`方法时将挂载的元素插入到文档中。通过创建Vue组件,将DOM、JS、Style都创建好,最后调用`$notify`方法将组件插入到页面中。要实现传入模板,可以使用`v-html`指令来插入模板,并在Notify.vue中新增接收参数的方法。在App.vue中传递一段模板,页面上操作的效果为显示提示框,两秒后消失。
都年了,谷歌镜像源码最新你的前端工具集应该有vueuse
摘要:一款基于Vue组合式API的函数工具集。
本文分享自华为云社区《vueuse:我不许身为vuer的前端,你的工具集只有lodash!》,作者:前端要摸鱼。
vueuse 是什么?一款基于Vue组合式API的函数工具集。
以上是官方网站关于它的定义。
首先,它基于Vue Composition Api (组合式API),只有在支持组合式API的环境下,才可以正常使用它;什么是组合式API?
然后,它是一款函数工具集(可类比为lodash.js/ramda.js);
简单来说,这是一个能让你更早下班的工具库。
vueuse 开源吗?现状如何?当然开源!github/vueuse
star数:6.3K
社区活跃度:社区非常活跃,截止年月,一直有mr被合入主线;
被引用情况:截止年月日,npm上可查询到依赖它的库就有个,其中包括著名UI库:Element-Plus
那位常年被调侃“懂个锤子Vue”的著名开源作者Evan You也是此库的金牌赞助商;
安装 vueuse
注: VueUse 借助 vue-demi 的强大功能,可以在一个包中同时适用于 Vue 2 和 3!
Vue 3 Demo: 使用vite: github.com/vueuse/vueus...
使用Webpack: github.com/vueuse/vueus...
Vue 2 Demo: Vue CLI
使用Vue CLI: github.com/vueuse/vueus...
另外,要注意库的版本:
从v6.0版本起,vue3 需要 vue >= v3.2; vue2 需要依赖@vue/composition-api>@vue/composition >= v1.1
vueuse 能做什么?能做的那可太多了,但总体上分为以下几个类别提供工具函数:
这么列了一遍,估计你还是很懵,但因为方法实在太多,也不可能一个个都列出来。
那我就举几个有代表性的例子,带你快速理解这些方法大概是做什么的,有什么特点;
例子1: useMouse
效果:
Wooooow~~~
这可太简单易用了!msm8225源码亲人们,给我买!!(误)
经过源码阅读,我们可以发现,这短短的一个方法,至少做了以下这些事:
如果这些逻辑放到页面里,至少需要6行代码,这些代码后期都会增加维护人员理解页面的成本;
而现在,你只需要一行代码;
除此之外,该方法还有组件式用法,适合更热爱标签的盆友
例子2: useInterval
顾名思义,这个方法是对延时重复调用能力的封装;
看看效果:
是不是很好用?相比手写setInterval更为便捷。
如果徒手实现这样一个套方法,多少行暂且不说,我们需要在业务中写下大量的逻辑代码。
而众所周知:
写的代码越多,出Bug的可能性越大,维护和理解的难度就越高。
从这个角度看,这个库确实是一个合格的函数工具集;
例子3:useVModel
这是一个给经常封装组件的小伙伴的大好利器。
先创建一个组件:Test.vue
接着,在index.vue中使用它
对于有组件封装需求的朋友,这个方法墙裂推荐!
不用再为了单项数据流的组件封装,而写在组件内写冗余的代码了。直接将useVModel返回的越狱抢红包源码数据作为响应式对象用即可。
这可太得劲儿了~~
vuex源码解析
Vuex 是一个专为 Vue.js 应用设计的状态管理库,它采用集中式存储管理应用的所有组件的状态,确保状态以一种可预测的方式变化。Vuex 的状态管理基于 Vue 的响应式原理,因此在 Vue 应用中使用它。
要使用 Vuex,需在 Vue 实例上挂载一个 store。通过 Vue.use(Vuex),Vue 实例可以获得 Vuex 的功能,其内部机制会自动在组件中添加一个指向 store 的 .$store 属性。
安装 Vuex 时,会执行一个名为 install 的方法,该方法在 Vuex 的构造函数中调用。安装阶段,Vuex 会往每一个组件实例上添加一个 beforeCreate 钩子函数,并在其中注入 store。通过 this.$store 访问 store 的属性和方法。
使用 Vuex 时,通过 new Vuex.Store({ }) 创建 store。构造函数中的 this.modules 属性是一个递归收集模块的实例。模块结构遵循树型设计,store 作为根模块,其子模块作为子树。Vuex 通过 register 方法构建模块树。
在 store 的构造函数中,有一个 installModule 方法用于注册模块。此方法处理命名空间概念,将模块的 action、mutation 和 getter 注册到全局或指定命名空间中。注册模块时,会创建一个本地上下文,该上下文根据命名空间调整调用 store.dispatch 和 store.getters 的行为。
对于 getters 的处理,存在命名空间时,通过 store._makeLocalGettersCache 查找或创建缓存,根据命名空间获取或创建 getters。state 的获取则通过 getNestedState 函数,从根状态开始,通过路径递归查找子模块的 state。
在 installModule 方法中,通过 _mutations、_actions 和 _wrappedGetters 存储模块的 mutations、actions 和 getters。mutations 和 actions 以键值对的形式存储,键由命名空间和方法名组成。getters 通过 createLocalGetter 方法创建本地缓存,用于高效访问。
初始化 store._vm 是创建响应式实例的过程,将 state 和 getters 关联到 Vue 实例中,实现状态和计算属性的响应性。
访问 state、mutations、actions 和 getters 时,可以通过 .$store 访问,根据命名空间调整访问行为。获取 state 使用 get 函数处理,访问 mutations 和 actions 使用 commit 和 dispatch 方法,并在执行时检查是否处于调用 mutations 或 actions 的状态。
为了方便组件复用状态逻辑,Vuex 提供了 mapState、mapGetters、mapMutations 和 mapActions 辅助函数,分别用于简化状态、getters、mutations 和 actions 的映射,减少代码冗余。
VueUse onClickOutside 解析
监听指定元素外的单击事件,尤其用于弹窗。
简单实现方式是通过window监听单击事件,但会有问题出现。当子元素被点击时,事件首先在该子元素上触发,然后事件冒泡机制会逐级向上传播,最终可能到达window对象,导致原本用于处理外部点击事件的监听器也被触发。
事件冒泡指的是事件从目标元素开始,逐级向上至祖先元素,直至document对象。
点击内部元素,事件首先在该元素上触发,然后依次向上至外部元素,直至window。
事件委托模式利用了事件冒泡机制,通过将单个事件处理程序放在元素的共同祖先上,优化事件处理。
此代码示例仅需关注container元素,无论动态添加或移除tile元素,点击tile时都会执行打印"click tile"。
缺陷在于点击可能在tile内部元素,event.target指向的是内部元素,而非tile,导致不会打印"click tile"。
解决方法之一是将事件数据放入event对象,通过事件冒泡的父元素事件读取该数据。此方式违背事件委托目的,实际开发中不会使用,但event对象在事件冒泡中传递信息的功能在Vue3源码中被利用。
另一种方法是查找container元素的子孙元素是否包含event.target元素,但查找操作过多。
Node.contains()方法可以优化查找过程,返回一个布尔值,表示一个节点是否是给定节点的后代。
查找event.target的祖先元素是否包含container对象,性能相比查找所有tile元素的子元素更好。
Element.closest()方法获取匹配特定选择器且离当前元素最近的祖先元素,性能优于逐级查找。
Event.composedPath()返回事件路径的对象数组,为更简洁的实现方式。
移除事件使用useEventListener进行绑定,并返回移除事件的函数。
click事件的触发条件是使用鼠标左键在同一元素上触发mousedown和mouseup后执行。
在使用onClickOutside处理modal时,当在modal内按住鼠标左键移出modal区域松开鼠标,事件不会触发modal的单击事件,而是触发window的click事件。解决方法是在window上添加pointerdown事件。
onClickOutside增加配置项ignore指定不触发事件的元素列表,但关于shouldListen = !shouldIgnore(event)中event.detail === 0的代码疑问,可能是为了特定条件下的事件过滤逻辑。
iOS移动端Safari浏览器下单击事件有时不会触发,原因是事件冒泡机制异常。事件允许冒泡的情况包括链接或表单字段、为鼠标事件设置显式事件处理程序、元素或祖先有cursor: pointer CSS声明。
第二种方式实现相对简单,但需要注意在iOS移动端Safari浏览器的事件处理。
在iframe处理方式中,需要关注跨域问题及iframe事件捕获和冒泡的特殊性。
vue-router源码学习 - install与<router-view>
本文深入解析Vue-router的install过程和部分逻辑。首先,探讨Vue-router的注册机制,即Vue.use(VueRouter)时的执行关键代码。利用Vue.mixin功能,混入beforeCreate钩子,确保所有组件在初始化阶段定义好_router和_routerRoot。this.$options展示组件构造时传递的选项信息。根组件执行beforeCreate时,_routerRoot指向根组件,而非根组件的执行则不同。全局混入后,定义$router和$route变量,并注册两个组件。
接下来,聚焦渲染流程的核心。主要负责渲染匹配到的路由组件。上篇中介绍的嵌套路由机制在匹配RouteRecord后,使用Route,其matched字段包含匹配的RouteRecord及其所有祖先RouteRecord。多个层级的页面中,每个router-view需知道自己的层级,通过源码内容实现。每个router-view标记自身,便于确定层级,在找到对应层级组件后进行渲染。
至此,渲染过程简化流程清晰呈现,但Vue-router的复杂性意味着仍有更多细节待探索。后续文章将继续深入,逐步解析更多功能。
2024-11-23 08:07
2024-11-23 07:24
2024-11-23 07:17
2024-11-23 06:59
2024-11-23 06:50