Vue函数式组件浅析

364 阅读3分钟

众所周知,Vue有两种版本,完整版(vue.js) 和 运行时版(vue.runtime.js)。

完整版:

    1. 完整版包含 编译器(compiler)和 运行时(vue.runtime.js),功能强大,可以直接将html或者template中占位符进行替换,而运行时版本不行,只能通过 render(h){} 将想要显示的数据渲染到页面。
    1. 编译器的功能是将模板字符串编译为Javascript渲染函数(render(h))的代码
    1. 运行时的功能包括创建Vue实例、渲染并处理虚拟DOM等除了编译器的其它所有功能

运行版:

  • 只包含 vue.runtime.js

同时,这两个版本又都有开发环境和生产环境,开发环境的代码都是未经过压缩的,里面是正常的代码和注释,而生产环境中的代码就是将所有代码中间没有必要的空格、换行、注释都去掉,将所有代码压缩为一行。

对于用户(coders)其实更多关心的是,哪个能更快的加载出我想要的页面,这个时候运行时版本优点就出来了:

  • 体积小,用户体验好,但只支持h函数
  • 对于coders们来说,只能写h函数,面对一些复杂的需求时,需要写出复杂的标签组合,开发体验不好, 因为没有compilercoders们就不能写出更直观更语义化的HTML标签和template,所以我们需要一个compiler
  • vue-loader就可以引入compiler,把Vue文件里的HTML标签和template会在构建时预编译成 h 函数

templaterender 用法对比:

//需要编译器
new Vue({
    template: '<div>{{ hi }}</div>'
})
//不需要编译器
new Vue({
    render(h) {
        return h(div'', this.hi)
    }
})

说了这么多,终于到了,今天的主题vue的函数式组件,顾名思义,.vue文件也可以只起到一个函数的作用。

组件的定义:

Vue提供了一种可以让组件变为无状态、无实例的函数化组件,从原理上说,一般子组件都会经过实例化的过程,而单纯的函数组件并没有这个过程,它可以简单理解为一个中间层,只处理数据,不创建实例,也是由于这个行为,它的渲染开销会低很多。实际的应用场景是,当我们需要在多个组件中选择一个来代为渲染,或者在将children,props,data等数据传递给子组件前进行数据处理时,我们都可以用函数式组件来完成,它本质上也是对组件的一个外部包装。

该组件没有管理任何状态,也没有监听任何传递给他的状态,也没有生命周期访问,(理解为 没有常规组件的 data() 也没有 this,因此优点是 渲染开销低很多 轻量 灵活

组件标志:

functional: true

没有this的影响:

  • 没有template标签,写上也不会编译
  • 所有属性通过render(h, context)context 传递,即 context.props

组件的使用场景:

  • 定义两个组件对象 demo1 demo2
let demo1 = {
    props: ['msg'],
    render: function(createElement, context) {
        return createElement('h1', this.msg)
    }
}

let demo2 = {
    props: ['msg'],
    render: function(createElement, context) {
        return createElement('h2', this.msg)
    }
}
  • 定义一个函数组件,它会根据计算结果选中其中一个组件进行选项:
Vue.component('demo3', {
    //函数式组件的标志,functional设置为true
    funcitonal: true,
    props: ['msg'],
    render: function(createElement, context) {
        var get = function() {
            return demo1
        }
        return createElement(get(), context)
    }
})
  • 函数式组件的使用:
<demo3 :msg="msg" id="demo3"> </demo3>
new Vue({
    el: '#app',
    data: {
        msg: 'demo'
    }
})

最终渲染结果为:

<h2>demo</h2>