vue功能组件介绍大多数人在开发过程中用的不多,甚至官方文档的位置也比较晦涩难懂,但是当我们对项目进行性能优化时,却是一个好的选择。本文将对功能组件的初始化过程进行系统的讲解。通过本文,您将了解以下内容:什么是功能组件?类型组件是无状态组件,没有data、computed、watch、lifecycle方法,组件中没有this上下文,只有props传递参数。在开发中,有很多只使用props和slot的组件,这些组件可以细化为功能组件。借用官网demo,最简单的功能组件如下:弥补不足Example//提供第二个参数作为contextrender:function(createElement,context){//...}})函数式组件和普通组件的区别组件的实例化过程大致分为四种步骤,状态初始化-->模板编译-->生成VNode-->转换为真实DOM。接下来对比一下普通组件和功能组件的通用配置项,对比一下差异。功能点名称公共组件功能组件描述vmYN组件作用域hooksYN生命周期钩子dataYN数据对象声明computedYN计算属性watchYN监听器propsYY属性childrenYYVNode子节点数组slotsYY返回包含所有槽的对象的函数scopedSlotsYY作用域Slot对象注入YY依赖注入监听器YY事件监听器parentYY对父组件的引用从上表可以看出,普通组件和功能组件最大的区别在于功能组件没有独立的作用域,也没有响应式数据声明。没有独立作用域,会有以下好处:没有组件实例化(newvnode.componentOptions.Ctor(options)),功能组件获取VNode只是普通的函数调用,没有公共属性,没有生命周期钩子用于方法复制,功能组件直接挂载到父组件,缩短第一次渲染和diff更新路径功能组件当父组件生成VNode时,会调用功能组件的render方法,挂载生成的VNode给父组件children,patch阶段可以直接转化为真正的DOM,普通组件在createElm时走组件初始化流程。diff更新时,功能组件调用render直接创建普通VNode,而普通组件创建的VNode包含组件的作用域。diff操作过程中,会额外调用updateChildComponent更新属性、自定义事件等,调用链接会比较长。Vue性能优化点功能组件带来的性能提升主要体现在缩短渲染路径和减少组件嵌套层级。前者与浏览器重绘和回流有相似之处,后者可以降低时间复杂度。不管是哪种性能优化,能从代码层面优化的无疑是成本最低的。虽然有时候效果不是很明显,但是加起来就是了。在vue中,有很多类似上面的点,可以提高代码执行的效率。合理声明data中的数据,保证data中声明的数据是必须的。很多时候有些数据是不需要在数据中声明的,比如需要在组件内部共享但不需要响应式处理的数据。对于data中的数据,对象会优先声明Object.defineProperty,数组也会拦截基本的操作方法。不必要的声明会造成毫无意义的数据劫持。合理使用computed和watchcomputed和watch最大的区别在于computed是懒加载的。懒加载主要体现在两个方面:当依赖状态发生变化时,不会立即触发,只是将当前Watcher实例的dirty属性的值改为true。在对计算出的属性值进行操作时,当且仅当watcher.dirty===为true时,才会触发以上两个特征的计算,可以避免不必要的代码执行。具体代码如下://src\core\instance\state.jsfunctioncreateComputedGetter(key){returnfunctioncomputedGetter(){//获取实例上computed属性的watcher实例constwatcher=this._computedWatchers&&this._computedWatchers[key]if(watcher){//当且仅当计算依赖属性发生变化&&获取计算属性时,才会调用Watcher的更新方法,将dirty设置为trueget方法获取计算值watcher.evaluate()}if(Dep.target){watcher.depend()}returnwatcher。value}}}//src\core\observer\watcher.jsupdate(){//computedwatcherlazy===trueif(this.lazy){//标记lazy执行是否可执行,false不执行computed属性计算this.dirty=true}elseif(this.sync){//同步执行this.run()}else{//将当前观察者放入观察者队列queueWatcher(this)}}v-for绑定键值v-在for循环中定义key值的目的是为了方便准确的找到diff比较节点,避免一些无意义的比较。普通diff:从头尾开始,比较新旧节点的头尾,将光标移近中间。当且仅当遍历一个节点时,diff过程以一个key值结束diff:根据key值维护一个hash表,每次循环准确定位更新目标节点,当且仅当一个节点遍历结束时,diffprocessends在Vue中思考,很多性能优化点都是为了缩短代码执行路径,尤其是在有大量计算逻辑的情况下,性能提升会有肉眼可见的效果。在实际开发中,有很多场景可以使用这种优化方式。举个最简单的例子,关键字高亮匹配。实现该操作需要以下步骤:获取匹配的关键字,格式化关键字(正则表达式中有意义的字符串转义),动态生成匹配的正则表达式,并根据正则表达式进行替换操作。这个时候我们可以省略第一步和第二步,直接执行第三步,因为输入的关键字可能有相同的值,所以我们可以把字符串和正则表达式缓存在Map中,下次匹配的时候,如果有Cache,直接从缓存中取出即可。vue模板编译中用到了这个特性。每次都是以编译后的模板字符串为键值,以render方法为值,进行缓存。如果遇到相同的模板,可以省去编译过程,带来一定的性能提升。.总结养成良好的编码习惯,对个人能力也是一个很好的提升。
