front-end-navigator
front-end-navigator copied to clipboard
Vue2.0 中 render 和 template 疑惑点
从 Vue 升级到2.0之后,多了采用jsx方式渲染生成HTML模版,还有一种就是一直沿用的 template 字符串拼接方式生成模版,但其实隐含的还有 直接去挂载手动写入模版,Vue 的功能很强大多种方式有时也让我们感到到很😅
Vue2.0 生成 HTML 方式:
- 1.使用 render 函数jsx方式渲染生成HTML模版
- 2.使用 template 字符串拼接方式生成模版
- 3.采用自定义标签,内嵌到 Vue 根实例挂载点(自定义标签影响html语义化,不推荐,但其实这个算是vue 1.0 采用 es5 写法遗留问题未借用babel)
注意: 对于挂载实例 不是采用 render 方式拼接模版,webpack 打包 vue 会报错,主要是由于webpack选择 vue 版本问题,详见 https://github.com/vuejs-templates/webpack/issues/215,2.0 Changes #2873
警告错误 [Vue warn]: You are using the runtime-only build of Vue where the template option is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
在解释这些之前,我们先搞清楚明白,组件 component 与 根实例 new Vue() 的关系:
创建 Vue 的根实例
const vm = new Vue({
// 选项对象
data: {},
template: '<my-component></<my-component>',
//render: (myComponent) => {
return createElement(myComponent)
},
components: {
"my-component": MyComponent
},
created () => {
},
mounted () => {
},
methods () => {
}
})
一个 Vue 实例其实正是一个 MVVM 模式中所描述的 ViewModel - 因此在文档中经常会使用 vm 这个变量名。
在实例化 Vue 时,需要传入一个选项对象,它可以包含数据、模板、挂载元素、方法、生命周期钩子等选项。
创建 component 组件
可以扩展 Vue 构造器,从而用预定义选项创建可复用的组件构造器(这个是官方说法,比较绕口),其实说白了,组件可以理解为继承于 Vue 构造器,与跟实例 vm 存在细微的差别对数据指针data更改。
//继承Vue 构造器,创建组件,区别修改data指针,跟实例 data: {},组件 data () {return {}}
const MyComponent = Vue.extend({
// 扩展选项对象
})
// 所有的 `MyComponent` 实例都将以预定义的扩展选项被创建,实例组件可以直接 data: {}, 没有指针问题,不会影响其他组件
const myComponentInstance = new MyComponent({
data: {}
})
注册 component 组件
组件全局注册
// 要使用这个组件构造器做的组件,需要用 Vue.component(tag, consturctor) 注册--全局注册,注册在根实例上的,全局可以直接使用
// Vue.component('my-component', MyComponent)
注意:对于统一性、共用性组件,建议采用组件全局注册方式,如 <ant-img src = "" v-on:error="_errorReport()" v-on:load="_loadReport"></ant-img>替代image标签进行统一上报处理。
组件局部注册
// vue 创建组件默认,使用构造器,然后实例生成组件
const MyComponent = Vue.extend({
})
const myComponentInstance = new MyComponent({
data: {},
components: {
"my-component": MyComponent //组件局部注册,注册在子组件上的
}
})
有了以上知识之后,基本对vue的实例,组件思路有了整理的了解,那接下来理解 Vue2.0 生成 HTML 方式。
render 函数jsx方式渲染生成HTML模版
字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。render 函数接收一个 createElement 方法作为第一个参数用来创建 VNode。
//根实例挂载
const vm = new Vue({
//virtul Dom 方案渲染模版
render: h => h(APP)
//render: (createElement) => {
// return createElement(APP)
//}
}).$mount('#app')
createElement 函数中生成模板:
createElement(
// {String | Object | Function}
// 一个 HTML 标签,组件选项,或一个函数
// 必须 Return 上述其中一个
'div',
// {String | Array}
// Children VNodes, built using `createElement()`,
// or simply using strings to get 'text VNodes'. Optional.
[
'Some text comes first.',
createElement('h1', 'A headline'),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
template 字符串拼接方式生成模版
// Vue.extend()组件构造器
const MyComponent = Vue.extend({
template: '<div>大家好,{{msg}}我来了</div>',
data: function () {
return {
msg: 'Hello!' //组件构造器生成的组件data数据需要return 返回,而实例new Vue()不需要(主要是处理指针问题)
}
},
created: function(){
console.log("组件开始创建")
}
})
const vm = new Vue({
//template是字符串模版拼接方案渲染模版
template: '<my-component></my-component>',
components: {
"my-component": MyComponent //实例局部注册组件
},
created(){
console.log("开始创建")
}
})
采用自定义标签,内嵌到 Vue 根实例挂载点获取模版
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<meta name="author" content="@pfan"/>
</head>
<!-- S 左侧导航内容 -->
<div vm-mod = "sideLeftNav">
<my-component></my-component>
</div>
<!-- E 左侧导航内容 -->
<!-- 这里填写路径是输出的路径 相对于dist输出路径 -->
<!-- <script src="./app.js"></script> -->
</body>
</html>
app.js
import Vue from 'vue'
var MyComponent = Vue.extend({
template: '<div>大家好,{{msg}}我来了</div>',
data: function () {
return {
msg: 'Hello!'
}
},
created: function(){
console.log("组件开始创建")
}
})
//全局注册,不需要在组件做局部注册
Vue.component('my-component', MyComponent)
const vm = new Vue({
el: '[vm-mod="sideLeftNav"]',
//由于组件是全局注册,所以不需要局部注册,可直接使用
components: {
// "my-component": MyComponent //实例局部注册组件
}
})
ps: 注意,自定义标签的这种模版方式不推荐使用,影响html语义化。
总结,通过以上的例子,我们理清了,组件与 Vue 根实例的关系, 以及挂载点,生成 html 的方式,最后更好的扩展优化可以深入做vue组件直出方案 prerender-spa-plugin 做简单直出。
参考资料:
// 所有的 MyComponent 实例都将以预定义的扩展选项被创建
const myComponentInstance = new MyComponent({})
请问,这句是什么意思?vue内部哪个阶段执行的?
@bi-kai const myComponentInstance = new MyComponent({}) 这里是实例化组件,并不是那个生命周期执行,挂载在 vue 根实例,complier之后才会有生命周期