一,el,template,render屬性優先性
當Vue選項對象中有render渲染函數時,Vue構造函數將直接使用渲染函數渲染DOM樹,當選項對象中沒有render渲染函數時,Vue構造函數首先通過將template模板編譯生成渲染函數,然后再渲染DOM樹,而當Vue選項對象中既沒有render渲染函數,也沒有template模板時,會通過el屬性獲取掛載元素的outerHTML來作為模板,並編譯生成渲染函數。
換言之,在進行DOM樹的渲染時,render渲染函數的優先級最高,template次之且需編譯成渲染函數,而掛載點el屬性對應的元素若存在,則在前兩者均不存在時,其outerHTML才會用於編譯與渲染。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js"></script>
</head>
<body>
<div class="vapp-1">{{ info }}</div>
<div class="vapp-2">{{ info }}</div>
<div class="vapp-3">{{ info }}</div>
<script>
new Vue({
el: '.vapp-1',
data: {
info: '這是通過el屬性獲取掛載元素的outerHTML方式渲染。'
},
template: '<div>這是template屬性模板渲染。</div>',
render: function (h) {
return h('div', {}, '這是render屬性方式渲染。')
}
})
new Vue({
el: '.vapp-2',
data: {
info: '這是通過el屬性獲取掛載元素的outerHTML方式渲染。'
},
template: '<div>這是template屬性模板渲染。</div>'
})
new Vue({
el: '.vapp-3',
data: {
info: '這是通過el屬性獲取掛載元素的outerHTML方式渲染。'
}
})
</script>
</body>
</html>
渲染結果:

二,template的三種寫法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js"></script>
</head>
<body>
<div id="app1"></div>
<div id="app2"></div>
<div id="app3"></div>
<script type="text/x-template" id="tem">
<div>
<h1>{{message}}</h1>
</div>
</script>
<template id="tem_t">
<div>
<h1>{{message}}</h1>
</div>
</template>
<script>
//第一種(使用模板字符串)
new Vue({
el: "#app1",
template: '<div>\
<h1>{{message}}</h1>\
</div>',
data: {
message: '字符串拼接'
}
})
//第二種(使用script元素)
new Vue({
el: "#app2",
template: '#tem',
data: {
message: '使用script元素'
}
})
//第三種(使用template元素)
new Vue({
el: "#app3",
template: '#tem_t',
data: {
message: '使用template元素'
}
})
</script>
</body>
</html>
渲染結果:

三,render渲染函數
vue一般使用template來創建HTML,然后在有的時候,我們需要使用javascript來創建html,這時候我們需要使用render函數
例如:我現在要寫一個根據不同level顯示不同級別的標題
<div id="container">
<tb-heading :level="1">
<a href="#">Hello world!</a>
</tb-heading>
</div>
用render函數實現:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js"></script>
</head>
<body>
<div id="container">
<tb-heading :level="level">
<a href="#">Hello world!</a>
</tb-heading>
</div>
<script>
//寫組件
Vue.component('tb-heading', {
render: function (createElement) {
return createElement(
'h' + this.level, // tag name 標簽名稱
this.$slots.default // 組件的子元素
)
},
props: {
level: {
type: Number,
required: true
}
}
});
new Vue({
el: "#container",
data:{
level:2,
}
})
</script>
</body>
</html>
渲染結果:

四,render函數中的creatElement參數
createElement 接受的參數:
// @returns {VNode}
createElement(
// {String | Object | Function}
// 一個 HTML 標簽名、組件選項對象,或者
// resolve 了上述任何一種的一個 async 函數。必填項。
'div',
// {Object}
// 一個與模板中 attribute 對應的數據對象。可選。
{
// (詳情見下一節)
},
// {String | Array}
// 子級虛擬節點 (VNodes),由 `createElement()` 構建而成,
// 也可以使用字符串來生成“文本虛擬節點”。可選。
[
'先寫一些文字',
createElement('h1', '一則頭條'),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
createElement的第二個參數的參數:深入數據對象
{
// 與 `v-bind:class` 的 API 相同,
// 接受一個字符串、對象或字符串和對象組成的數組
'class': {
foo: true,
bar: false
},
// 與 `v-bind:style` 的 API 相同,
// 接受一個字符串、對象,或對象組成的數組
style: {
color: 'red',
fontSize: '14px'
},
// 普通的 HTML attribute
attrs: {
id: 'foo'
},
// 組件 prop
props: {
myProp: 'bar'
},
// DOM property
domProps: {
innerHTML: 'baz'
},
// 事件監聽器在 `on` 內,
// 但不再支持如 `v-on:keyup.enter` 這樣的修飾器。
// 需要在處理函數中手動檢查 keyCode。
on: {
click: this.clickHandler
},
// 僅用於組件,用於監聽原生事件,而不是組件內部使用
// `vm.$emit` 觸發的事件。
nativeOn: {
click: this.nativeClickHandler
},
// 自定義指令。注意,你無法對 `binding` 中的 `oldValue`
// 賦值,因為 Vue 已經自動為你進行了同步。
directives: [
{
name: 'my-custom-directive',
value: '2',
expression: '1 + 1',
arg: 'foo',
modifiers: {
bar: true
}
}
],
// 作用域插槽的格式為
// { name: props => VNode | Array<VNode> }
scopedSlots: {
default: props => createElement('span', props.text)
},
// 如果組件是其它組件的子組件,需為插槽指定名稱
slot: 'name-of-slot',
// 其它特殊頂層 property
key: 'myKey',
ref: 'myRef',
// 如果你在渲染函數中給多個元素都應用了相同的 ref 名,
// 那么 `$refs.myRef` 會變成一個數組。
refInFor: true
}
實現如下例子:
<ul v-if="items.length">
<li v-for="item in items">{{ item.name }}</li>
</ul>
<p v-else>No items found.</p>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js"></script>
</head>
<body>
<div id="container">
<cm-ul :items="items"></cm-ul>
</div>
<script>
//寫組件
Vue.component('cm-ul', {
render: function (createElement) {
//if-else判斷
if (this.items.length) {
return createElement('ul', this.items.map(function (item) {
return createElement('li', item.name)
}))
} else {
return createElement('p', 'No items found.')
}
},
props: {
items: {
items:Array
}
}
});
new Vue({
el: "#container",
data: {
items: [{name:'華為'},{name:'小米'},{name:'華為'}],
}
})
</script>
</body>
</html>
渲染結果:

