vue中 render 函数功能与原理分析
作者:webchang
1. 前言
在使用 vue-cli2 脚手架构建项目时,如果选择了Runtime-only模式,那么在main.js文件中会有下面一段代码:
有关Runtime + Compiler的介绍可以看这篇文章:Vue中 Runtime + Compiler 和 Runtime-only 两种模式含义和区别
import Vue from 'vue' import App from './App' Vue.config.productionTip = false new Vue({ el: '#app', render: h => h(App) })
2. 分析render函数
2.1 render 函数的作用
Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,真的需要 JavaScript 的完全编程的能力。这时可以用渲染函数,它比模板更接近编译器。
render
函数和 template
一样都是创建 html 模板的,但是有些场景中用 template 实现起来代码冗长繁琐而且有大量重复,这时候就可以用 render 函数。
2.2 render 函数讲解
render
函数即渲染函数,它是个函数,它的参数 createElement
也是个函数。
上边的代码中 render: h => h(App)
,这是 ES6的箭头函数的写法,可以把 h
当作 createElement
的别名。所以这段代码其实相当于:
render: function (createElement) { return createElement(App) }
2.3 createElement 函数讲解
这个函数的作用就是生成一个 VNode节点,render 函数得到这个 VNode 节点之后,返回给 Vue.js 的 mount 函数,渲染成真实 DOM 节点,并挂载到根节点上。
createElement 函数的返回值是 VNode(即:虚拟节点)
有关对 VNode 的介绍可以看这篇博客:VNode简介
createElement 函数的3个参数
- 一个 HTML 标签字符串,组件选项对象,或者解析上述任何一种的一个 async 异步函数。类型:String | Object | Function。必需。
- 一个包含模板相关属性的数据对象,你可以在 template 中使用这些特性。类型:Object。可选。
- 子虚拟节点 (VNodes),由 createElement() 构建而成,也可以使用字符串来生成“文本虚拟节点”。类型:String | Array。可选。
实现createElement函数
1、普通用法
// main.js文件 new Vue({ el: '#app', render:function (createElement) { //1.普通用法 // createElement(标签,{属性},[内容]) return createElement("h2",{class:"box"},['hello',createElement("button",["按钮"])]) } })
运行效果如图所示:
2、我们也可以自定义一个组件,传递给render函数
// ... let Cpn = { template:`<h2>{{message}}</h2>`, data(){ return { message:"我是组件" } } } new Vue({ el: '#app', render:function (createElement) { //2.使用组件 return createElement(Cpn) } })
运行效果如图所示:
3、既然我们能够使用组件,那么App组件也是可以的
import Vue from 'vue' import App from './App' Vue.config.productionTip = false new Vue({ el: '#app', render:function (createElement) { return createElement(App) } })
效果如图所示:
3. 参考资料
补充
关于Vue中 render: h => h(App) 的具体含义的理解
一、问题:
https://github.com/vuejs-templates/webpack-simple/blob/master/template/src/main.js
import Vue from 'vue' import App from './App.vue' new Vue({ el: '#app', render: h => h(App) })
vue的代码中有这么一段,令人第一眼对这个 h 函数十分困惑??
二、原因:
经过查找相关资料后发现:
render: h => h(App) 是下面内容的缩写:
render: function (createElement) { return createElement(App); }
进一步缩写为(ES6 语法):
render (createElement) { return createElement(App); }
再进一步缩写为:
render (h){ return h(App); }
按照 ES6 箭头函数的写法,就得到了:
render: h => h(App);
其中 根据 Vue.js 作者 Even You 在 Vue 的 issue 中的回复,h 的含义如下:
It comes from the term "hyperscript", which is commonly used in many virtual-dom implementations. "Hyperscript" itself stands for "script that generates HTML structures" because HTML is the acronym for "hyper-text markup language".
它来自单词 hyperscript,这个单词通常用在 virtual-dom 的实现中。Hyperscript 本身是指
生成HTML 结构的 script 脚本,因为 HTML 是 hyper-text markup language 的缩写(超文本标记语言)
三、总结:
h 函数的本质是createElement 函数,这个函数的作用就是生成一个 VNode节点,render 函数得到这个 VNode 节点之后,返回给 Vue.js 的 mount 函数,渲染成真实 DOM 节点,并挂载到根节点上
而之所以要 叫 h,根据作者解释是,来源于 hyper script,
........
个人觉得可读性差了很多,就算是外国人不经解释也很难理解这个 h 函数
不如直接 createElement