- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章升级 Vue3 大幅提升开发运行效率由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
。
原计划 2019 年发布的 Vue3,又经过一年的再次打磨,终于于去年 9 月正式发布。随后,不少 UI 组件库都积极参与适配,去年 12 月,Element-plus(Element-ui 官方升级版)也发布了 beta 版.
由于项目中用到了 Element-ui 组件,组件库未适配的情况下,不敢贸然升级 Vue3。Element-plus 发布后,又经过 1 个月的观察、测试和调研,发现 Element-plus 相对成熟(还有少量 bug,后续会讲),便开始尝试升级 Vue3.
。
有两种方案可以快速升级 Vue3:
之所以会有方案一,主要还是担心 Element-plus 不够稳定,如果有天坑,又无法绕过去,除了向饿了么团队提交 PR,微前端兜个底也是不错的应急措施.
就这样微前端方案又运行了 1 个月,部分页面已完成升级,运行良好,实践证明 Element-plus 比想象中稳定,这增加了我对于方案二的信心。考虑到还有少量业务复杂的页面,在微前端模式下,子项目的各种数据多经过一层 qiankun 的 proxy 代理,性能有损耗,影响了页面更新,于是一次性将剩余的页面全部迁移到 Vue3 项目中.
实践证明,除非比较复杂的项目,或者依赖组件库没升级等原因不适合升级外,常规情况下,升级 Vue3 都是一个不错的选择.
。
为什么要升级 Vue3,这是一个几乎不需要回答的问题。升级 Vue3 后,代码结构更加清晰内聚,响应式数据流更加可控,节省了很多心智成本,从而使得开发效率大幅提升。Vue3 还带来了很多新特性,框架层面运行性能更高(性能提升了 1.3 至 2 倍,SSR 性能提升了 2 至 3 倍),Composition API 使得代码拆分,函数封装更容易,复杂项目也随之更容易管理.
Vue2 中,相关的逻辑经常分散在 option 的 data、watch、computed、created、mounted 等钩子中,阅读一段代码,经常需要上下反复横跳,带来了部分阅读障碍。钩子又依赖 Vue 实例,代码封装基于天生携带钩子的 Mixin 去做,更加容易和相对方便.
但正因为如此,Mixin 的钩子容易不自觉的越界,插手到页面或组件的内部变量和方法管理过程中;甚至,多个不同的 Mixin,相互之间就很容易冲突,项目开发者,在引入 Mixin 和避免冲突之间需要保持微妙的平衡,不但增加心智负担,还带来了副产品:本身扑朔迷离的 this 变得更加不确定。因此,大型项目 Mixin 几乎都是一种反模式.
现在这些框架问题,都由 Vue3 的 Composition API 解决了.
。
我们先看一些立马能感受到变化的特性.
Proxy 代理 。
这是一个一上手 Vue3 就能感知的变化。即使你在 Vue3 中编写 Vue2 风格的基于 option 的代码,Proxy 也是默默提供着数据响应式.
如上所示,Vue2 的数据响应式是通过 Object.defineProperty 实现,这是一个深度遍历的过程,无论 data 中包含多少层数据,都需要全部遍历一遍。深度遍历,给对象的每个自身属性添加 defineProperty,需要不小的性能开销,同时后面新增到 this 中的属性不提供响应式监听,因此我们需要使用诸如this.$set这种方式去添加新属性.
Proxy 就没有这个问题,如下所示.
Proxy 不但使得 data 获得了新属性的响应性,整个响应式处理过程的效率还提升了数倍,由此带来了 Vue3 的大部分性能提升.
Composition API 。
为了保持对 Vue2 的向下兼容,Vue3 中仍然支持纯 Option 配置的书写方式,这为升级提供了便利,平移 Vue2 的代码,只需少量改动,便可正常运行.
同时考虑到上手难度,Vue3 的顶层代码风格与 Vue2 保持一致,依然是 export 一个对象,对象包含了一系列的配置,其中便有 setup 入口函数。我们先来看一段代码,然后逐个解读.
setup 作为入口函数,包含两个参数,分别是响应式的 props 外部参数,以及 context 对象,context 包含 attrs、emit、expose、props、slots 五个参数,如下所示:
在 Vue3 的设计里,setup,以及从 vue 对象中解构出来的各种生命周期函数,执行优先级高于 Vue2 中的各种生命周期钩子,因此 。
这段代码的输出依次是 setup、beforeCreate、created.
ref、reactive 。
setup 中,第一句const selectRef = ref(null);,这里定义的是一个响应式的数据,可传递给 template 或 render,用于下拉框组件或下拉框 dom 绑定引用。为什么使用 ref,不使用 reactive 呢?ref 和 reactive 都可以给数据添加响应性,ref 一般用于给 js 基本数据类型添加响应性(当然也支持非基本类型的 object),reactive 只能用于代理非基本数据类型。null 是基本数据类型,只能使用 ref,那既然如此,为什么不在所有情况都使用 ref 呢?我们来看一段代码:
我们注意到,使用 ref api 时,数据变成了对象,值就是 value 属性的值,如果数据本身就是对象,依然会多一层 value 结构,而 reactive 没有这些副作用。同时,还有一个有意思的现象是,所有的源数据,都需要经过响应式 api 包裹,然后才能使用,这跟前面提到的 Proxy 原理有关,Proxy 代理数据时,需要基于返回的代理进行数据更新.
toRefs 。
除了 ref、reactive 外,还有一个常用的响应式 api——toRefs。为什么需要它,这是因为响应式对象,经过解构出来的属性不再具有响应性,toRefs 就是为了快速获得响应性的属性,因此这段代码const { init } = toRefs(props);,就是为了获得响应式属性 init,想要保留 props 参数的响应性,建议这么做.
watch、watchEffect 。
如上,watch api,它需要接受一个具有返回值的 getter 函数或者 ref(如() => state.num,ref).
如果需要监听多个值,如下所示:
可见多个数据的每次更新都会触发 watch。想要监听一个嵌套的对象,跟 Vue2 一样,依旧需要使用 deep 选项,如下所示:
看到差别了吗?监听响应式对象时,返回的是对象的引用,因此 currState,prevState 指向是同一个最新的 state,如果需要获取变化前的值,建议返回监听的属性,如watch(() => state.attr.id),刚好 state.attr.id 是一个基本类型的值,那么 deep 也不需要.
watchEffect 是 Vue3 新增的 api,watchEffect 会自动运行一次,用于自动收集依赖,但不支持获取变化前的值,除此之外,与 watch 用法一致。那么 watchEffect 适用什么场景呢?这也是我刚上手 Vue3 的困惑之一。我们来看一段代码:
以上代码中,watch 中的逻辑只能在 userInfo 变化后执行,因此 state.rights 不会提供初始值,相反,watchEffect 中 state.rights 由于自动依赖收集,获得了一次赋值的机会.
这样做的好处是什么呢?在实际项目中,userInfo.role 可能是一个全局 store 中的数据,用户登录进来后,就会通过接口获取初始值,我们并不能确认,用户进到其中一个页面时,userInfo.role 的值是否已经被接口更新,且 userInfo 变化前的值我们也不关心,watchEffect 就非常适合这种场景,它会自动进行一次初始化,并且在变化后,及时更新值.
watch 和 watchEffect 的监听会在组件销毁时自动取消,除此之外,可以通过它们返回的函数手动取消监听,如下所示:
watchEffect 更多的用法,请参考官方文档.
computed 。
computed 的使用如下:
num2 是一个不可变的 ref 对象,不能直接对它的 value 属性赋值.
computed 还可以接收一个带有 get 和 set 函数的对象,来创建一个可读写的 ref 对象,如下所示:
自定义 Hooks 。
Vue3 的 Composition 之所以这样实现,主要原因就是为了便于代码拆分,降低耦合,我们不妨来实现一个自定义的 hooks.
useCount.js 就是一个自定义的 hooks,得益于 Vue3 的全局 API,我们可以轻松做到代码拆分。Vue3 的 setup 聚合了所有的逻辑,容易产生面条代码,合理使用自定义 hooks,可以有效的减少面条代码,提升代码可维护性。并且 Vue3 的 hooks 比 react 更加简单高效,不会多次执行,不受调用顺序影响,不存在闭包陷阱等等,几乎可以没有任何心智负担的使用.
。
看到这里,相信你对 Vue3 的生命周期已经有一些了解了,我们不妨来做个梳理.
Vue3 几乎内置了所有的 Vue2 生命周期钩子,也就是说,刚开始升级项目至 Vue3 时,可以直接使用 Vue2 的钩子,方便平滑升级,如上图左下角所示,有两个钩子发生了替换,beforeDestory 被替换成了 beforeUnmount,destoryed 被替换成了 unmounted。完整的钩子对比如下:
除了 setup 外,Vue3 的其他生命周期钩子都添加了 on 前缀,更加规范统一。新的钩子需要在 setup 中使用,如下所示:
Tree-Shaking 。
Vue3 一共开放了 113 个 API,我们可以通过如下方式引用:
通过 ES6 modules 的引入方式,能够被 AST 静态语法分析感知,从而可以只提取用到的代码片段,最终达到 Tree-Shaking 的效果,这样就使得 Vue3 最终打包出来的包更小,加载更快。据尤大去年 4 月在 B 站的直播:基本的 hello world 项目大小为 13.5kb,Composition API 仅有 11.75kb,包含所有的运行态仅 22.5kb.
Fragment 。
Vue3 中,Fragment 的引入,解决了组件需要被一个唯一根节点包裹的难题,带来的是 dom 层级的减少,以及渲染性能的提升,某些时候,如下所示:
在 Vue2 中,这意味着我们没办法在 child.vue 的 template 中加入多个 td 节点,多个 td 可以被 tr 包裹,如果 child.vue 根节点替换为 tr,那么就会跟 parent.vue 的 tr 冲突.
同样的代码,在 Vue3 中就能正确编译通过,这是因为 Vue3 中,组件的 template 被一层不可见的 Fragment 包裹,组件天生支持多个根节点的布局.
Teleport 。
Teleport 是 Vue3 新增的组件,即传送门,Teleport 能够在不改变组件内部元素父子关系的情况下,将子元素”传送“到其他节点下加载,如下所示:
dialog 直接挂载在 container 下,超出部分将不可见。加一层 Teleport,我们可以轻松将 dialog 展示出来.
dialog 依然处于 container 内部,仅仅只是被挂载到 body 上,逻辑关系不变,展示也不会遮挡.
Suspense 。
Vue2 中,我们经常写这样的 loading 效果,如下所示:
Vue3 中,我们可以通过 Suspense 的两个插槽实现以上功能,如下所示:
。
Vue3 还包括了一些其他常用更新,限于篇幅,这里先列出来,下篇再讲.
实际上,Vue3 带来的更新,远不止这些,为此我梳理了一个 Vue3 的知识图谱,尽可能囊括一些本文未提到的特性.
如上图,Vue 不但重写了 diff 算法,还在编译阶段做了很多优化,编译时优化可以通过这个网站看出来:https://vue-next-template-explorer.netlify.app/.
。
根据 Monterail 2 月份发布的第三版 Vue 生态报告,Vue 的流行度逐年上升,很多非 web 的可视化领域也可以基于 Vue 开发,特别是 Vue3 的渲染 API 的开放,使得基于 Vue 构建 Canvas、WebGL、小程序等应用更加方便,如下图所示,60 行代码实现一个简单的 Canvas 柱状图:
运行结果如下图所示:
原文地址:https://zhuanlan.51cto.com/art/202104/659798.htm 。
最后此篇关于升级 Vue3 大幅提升开发运行效率的文章就讲到这里了,如果你想了解更多关于升级 Vue3 大幅提升开发运行效率的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我在将过滤器从 vue 1 迁移到 vue 2 时遇到问题,我在这里完全创建了我需要的东西(突出显示与输入文本匹配的文本): Vue.component('demo-grid', { templa
我有一个在 vue 组件外部运行的函数。我想要将它返回的数据传递给vue组件中的数据。 function example(){ var item = 'item'
我正在尝试安装一个 Vue 插件,以便我可以使用选项管理一些 API 调用。我有一个 stocks.js 文件,我想从中进行 API 调用。 当我执行以下操作时,出现'Vue is defined b
如何从指令访问 Vue 实例? 我有这个 HTML 和这个脚本 var app = new Vue({ el: '#vueApp', data: { myData:
如何在 .vue 文件中使用 Vue.set() 和 Vue.use()?我正在使用 vue-cli 搭建我的项目,我需要使用 Vue.use(VeeValidate) 进行验证。我也想使用类似下面的
从 vue-property-decorator 和 vue 导入 Vue 之间有什么区别和用例?据我所知,在使用 @Component 装饰器定义自定义组件时,我始终需要从 vue-property
有没有办法使用 yarn serve(可能使用 webpack/vuetify-loader)在本地 Vuetify 应用程序的本地 npm 依赖项上发生热重载? 商业案例 我们有一些通用的 Vuet
我有一个在某些未知情况下不可靠的插槽的奇怪错误。 成分 有3个层次组件。 孙子 (headlessTable),它提供一个名为 arrayValue 的插槽. 子项 (collapsableCard)
我是 Vue 本地新手,我也遇到了一个问题,can I use the Vue component inside a Vue native component such as Vue-chart an
Vue.delete 的替代方案是什么?在 Vue 3 的新 Reactivity API 中? 最佳答案 Vue.delete和 Vue.set在 Vue 3 中不需要。通过使用代理的新 react
我是 Vue 的新手,正在尝试学习如何使用它。 我想我在尝试安装一个新的 Vue 应用程序时被绊倒了。 这是我可以开始工作的内容: const vm = new Vue({}) 从那里我可以安装
我使用boots-vue。我从文档https://bootstrap-vue.js.org/docs/components/table/#table-body-transition-support中举
我真的只是想为我的图书馆建立一个 jest+vue 的框架,并迅速得到这个错误。 我知道这个结构不是通常的笑话结构,我在这里尝试用一个辅助控件来描述一个测试。 这是我的test的内容文件夹:array
我正在尝试使用基于 examples 的 vue-router , 如 let routes = [ { path: '/', component: MainComponent }, ];
我有一个想要通过简单的 v-model 功能发布到 NPM 的组件。 因此,如果它能够在 vuejs 2/3 上互换运行那就更理想了。 我可以通过将组件设置为发出 input 和 update:mod
我正在尝试在 bootstrap-vue 表中创建一个插槽,以使用自定义组件呈现任何 bool 值。 所以我有一个简单的表格 现在,如果我想以特定方式渲染单个列,我必须使用插槽 它有
Vue Router 在主 Vue 实例之前加载,但要加载该 Router,我应该准备一些信息,然后将它们作为属性传递给此 Route。在此示例中,它是从主 Vue 实例传递到主屏幕的 current
我有一个想要通过简单的 v-model 功能发布到 NPM 的组件。 因此,如果它能够在 vuejs 2/3 上互换运行那就更理想了。 我可以通过将组件设置为发出 input 和 update:mod
我找到了一个关于如何使用 Vue 路由器的很好的例子。这是 app.js 文件: // Telling Vue to use the router Vue.use(VueRouter) // Init
我没有完整的 vue 应用程序,所以我使用 custom elements替换一些应该用 vue 处理的元素。 我只想使用 vue multiselect plugin在 html 文件中。 所以我尝
我是一名优秀的程序员,十分优秀!