1.vue-router源码学习 - install与<router-view>
2.都2022年了,源码你的源码前端工具集应该有vueuse
3.Vue—关于插件(源码级别的插件分析+实践)
4.VueUse onClickOutside 解析
5.为什么 uni-app (vue3) 和 @vueuse/core v10 一起用会报错?
6.Vue3 源码中创建应用实例(createApp)流程
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标记自身,便于确定层级,在找到对应层级组件后进行渲染。
至此,渲染过程简化流程清晰呈现,opencenter源码项目但Vue-router的复杂性意味着仍有更多细节待探索。后续文章将继续深入,逐步解析更多功能。
都年了,你的前端工具集应该有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 能做什么?能做的那可太多了,但总体上分为以下几个类别提供工具函数:
这么列了一遍,估计你还是很懵,但因为方法实在太多,也不可能一个个都列出来。zlmediakit源码解析
那我就举几个有代表性的例子,带你快速理解这些方法大概是做什么的,有什么特点;
例子1: useMouse
效果:
Wooooow~~~
这可太简单易用了!亲人们,给我买!!(误)
经过源码阅读,我们可以发现,这短短的一个方法,至少做了以下这些事:
如果这些逻辑放到页面里,至少需要6行代码,这些代码后期都会增加维护人员理解页面的成本;
而现在,你只需要一行代码;
除此之外,该方法还有组件式用法,适合更热爱标签的盆友
例子2: useInterval
顾名思义,这个方法是对延时重复调用能力的封装;
看看效果:
是不是很好用?相比手写setInterval更为便捷。
如果徒手实现这样一个套方法,多少行暂且不说,我们需要在业务中写下大量的逻辑代码。
而众所周知:
写的代码越多,出Bug的可能性越大,维护和理解的难度就越高。
从这个角度看,这个库确实是一个合格的函数工具集;
例子3:useVModel
这是一个给经常封装组件的小伙伴的大好利器。
先创建一个组件:Test.vue
接着,在index.vue中使用它
对于有组件封装需求的朋友,这个方法墙裂推荐!
不用再为了单项数据流的mfc课程源码组件封装,而写在组件内写冗余的代码了。直接将useVModel返回的数据作为响应式对象用即可。
这可太得劲儿了~~
Vue—关于插件(源码级别的插件分析+实践)
Vue插件的原理基于Vue的`use`方法,该方法接收一个函数或者提供`install`方法的对象作为参数,如果传入的参数是函数,这个函数会被当作`install`方法。在Vue 2.6.版本中,`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 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事件捕获和冒泡的特殊性。
为什么 uni-app (vue3) 和 @vueuse/core v 一起用会报错?
在 @vueuse/core v 发布后,尝试在 uni-app (vue3) 上使用时遇到报错。为解决此问题,首先复现了配置情况,包括拉取 uni-app 官方的 vue3 模板、安装依赖和引入 @vueuse/core。运行到微信小程序时报错,错误信息指出"TransitionGroup"未在 "node_modules/@vueuse/core/node_modules/vue-demi/lib/index.mjs"中导出,而是由 "@vueuse/core/index.mjs"导入。深入探究发现,vue-demi理论上导出了TransitionGroup,但实际情况并未导出。怀疑可能是 uni-app 修改了 vue 库用于微信小程序,而修改后的库中缺少了 TransitionGroup 导出。通过在 vite 配置文件中添加插件验证,确认了问题根源在于此。再次运行到微信小程序并验证,确认使用了 @dcloudio/uni-mp-vue 文件内的 vue 库。进入文件内搜索,发现 TransitionGroup 并未存在,由此确定问题出在 uni-app 修改的 vue 库未导出 TransitionGroup。
为解决此问题,选择降级到 @vueuse/core v9,因为此版本未使用到 TransitionGroup。但若希望使用 v,需找到问题所在并进行修复。翻看 vue-demi 源码得知,其模拟并导出了 TransitionGroup,但此导出并未实际作用。通过为修改后的 vue 库补充 TransitionGroup 的模拟,可以解决报错问题。再次运行到微信小程序,问题得到解决。若团队伙伴也遇到此问题,可创建一个 patch。使用支持 patch 命令的包管理器或 patch-package,进行修复操作。最终,最好的解决方案是 uni-app 官方在修改的 vue 库内增加 TransitionGroup 的导出。
@vueuse/core v 未在官方支持的小程序平台,导致部分特性无法直接使用。推荐尝试 @uni-helper/uni-use,以获得更好的 uni-app 开发体验。
Vue3 源码中创建应用实例(createApp)流程
Vue3的核心应用实例创建过程主要由createAppAPI驱动,这个过程涉及到了关键函数如beforeCreateRender和createApp。createApp位于/vue-core/vue-next/packages/runtime-dom/src/index.ts中,它是项目构建的起点,功能包括组件实例的构建和页面挂载。
首先,createApp通过ensureRenderer函数来构建组件实例,这个过程涉及虚拟节点的操作,如更新和挂载。ensureRenderer会返回createRenderer,进一步生成baseCreateRenderer,最终返回createAppAPI。这个函数的主要任务是为虚拟节点添加如mixin、use、mount、props和emits等功能。
在beforeCreateRender中,主要负责创建render和hydrate渲染器,这些渲染器负责DOM操作,如节点的更新和挂载。虽然这部分内容详细,但略过了具体的实现细节,有兴趣的话,可以参考vue-core/vue-next/packages/runtime-core/src/renderer.ts文件。
createAppAPI函数的核心是返回createApp,这个函数接收根组件和其props作为输入,用于生成Vue应用程序实例。至此,组件实例app已经创建完成,但挂载到页面的过程将在后续内容中深入讨论。