关于vue.js:从函数式组件引发的性能思考
简介vue函数式组件大部分人在开发过程中用到的不多,就连官网文档地位搁置的也比拟费解,然而在咱们对我的项目做性能优化时,却是一个不错的抉择。本文将对函数式组件初始化过程做一个系统性的论述,通过本文,你将理解到以下内容: 什么是函数式组件函数式组件与一般组件间的差别vue类似性能优化点什么是函数式组件函数式组件即无状态组件,没有data、computed、watch,也没有生命周期办法,组件中也没有this上下文,只有props传参。在开发中,有很多组件仅仅只用到了props和插槽,这部分组件就能够提炼为函数式组件。借用官网demo,最简略的函数式组件如下: Vue.component('my-component', { functional: true, // Props 是可选的 props: { // ... }, // 为了补救短少的实例 // 提供第二个参数作为上下文 render: function (createElement, context) { // ... }})函数式组件与一般组件间的差别组件实例化过程大抵分为四步,状态初始化 --> 模板编译 --> 生成VNode --> 转换为实在DOM。接下来比照一般组件与函数式组件罕用配置项,比拟下差别。 性能点名称一般组件函数式组件形容vmYN组件作用域hooksYN生命周期钩子dataYN数据对象申明computedYN计算属性watchYN侦听器propsYY属性childrenYYVNode 子节点的数组slotsYY一个函数,返回了蕴含所有插槽的对象scopedSlotsYY作用域插槽的对象injectionsYY依赖注入listenersYY事件监听parentYY对父组件的援用从上表中能够看出,一般组件与函数式组件最大的差异在于函数式组件没有独立作用域,没有响应式数据申明。没有独立作用域,会有以下长处: 没有组件实例化(new vnode.componentOptions.Ctor(options)),函数式组件获取VNode仅仅是一般函数调用 无公共属性、办法拷贝无生命周期钩子调用函数式组件间接挂载到父组件中,缩短首次渲染、diff更新门路 函数式组件在父组件生成VNode时,函数式组件render办法会被调用,生成VNode挂载到父组件children中,patch阶段可间接转换成真是DOM,一般组件则在createElm时,走组件初始化流程。diff更新时,函数式组件调用render,间接创立一般VNode,而一般组件创立的VNode的是蕴含组件作用域的,diff操作时,还有额定调用updateChildComponent更新属性、自定义事件等,调用链路会比拟长。vue性能优化点函数式组件带来的性能晋升次要体现在缩短渲染门路与缩小组件嵌套层级,前者与浏览器重绘回流有殊途同归之处,后者能够升高工夫复杂度。 无论何种性能优化,能从代码层面做优化的,无疑是代价最小的,尽管有时成果不是很显著,然而千里之行;始于足下。在vue中,有不少与上述类似的点,能够晋升代码执行效率。 正当申明data中数据,确保data中申明数据都是必须的很多时候有一些数据没必要申明在data中,比方须要组件内共享,但不须要响应式解决的数据。data中的数据,对象都会对其深度优先用Object.defineProperty申明,数组也会拦挡基本操作办法。不必要的申明会造成无意义的数据劫持。 正当应用computed与watchcomputed与watch最大的区别在于computed是惰性加载的。惰性加载次要体现在两个方面: 依赖状态产生扭转时,不会立刻触发,只是扭转以后Watcher实例的dirty属性值为true当对计算属性值取操作时,当且仅当watcher.dirty === true时,才会触发计算以上两点个性,可能防止一些不必要的代码执行,具体代码如下所示: // src\core\instance\state.jsfunction createComputedGetter (key) { return function computedGetter () { // 获取实例上的computed属性的watcher实例 const watcher = this._computedWatchers && this._computedWatchers[key] if (watcher) { // 当且仅当computed依赖属性发生变化 && 对计算属性进行取操作,才会调用Watcher的update办法,将dirty置为true if (watcher.dirty) { // 调用get办法,获取到computed的值 watcher.evaluate() } if (Dep.target) { watcher.depend() } return watcher.value } }}// src\core\observer\watcher.jsupdate () { // computed watcher lazy === true if (this.lazy) { // 标记懒执行是否可执行状态,false不执行计算属性计算 this.dirty = true } else if (this.sync) { // 同步执行 this.run() } else { // 将以后watcher放入到watcher队列 queueWatcher(this) }}v-for绑定key值v-for循环定义key值目标是便于精准找到diff比对节点,防止一些无意义的比对。 ...