template有以下几种写法:
第一种方式:模板字符串直接书写
<div id="app"></div>
const vm = new Vue({
el: '#app',
template:`<div>姓名:{{ name }}<div>`,
data: {
name: 'ludeng',
}
});
这种方式如果代码量很大,书写非常困难也很不美观。(示例用了ES6模板字符串,有耐心的话也可以用字符串拼接)
第二种方式:使用template元素
这种方式是把template的内容单独提出来放到<template />
元素中
<div id="app"></div>
<template id="tmp">
<div>
姓名: {{ name }}
</div>
</template>
const vm = new Vue({
el: '#app',
template:'#tmp',
data: {
name: 'ludeng',
}
});
template值还可以直接是DOM元素template: document.querySelector('#tmp')
,效果相同。最后都是取template元素的innerHTML作为编译模板
多说一嘴,template元素是H5标准,在此之前是用script标签实现的模板元素功能,写法如下:
<div id="app"></div>
<script type="x-template" id="tmp">
<div>
姓名: {{ name }}
</div>
</script>
效果一样,都是把template的内容提取出来
第三种方式:不写template
直接在el元素里书写模板代码,这种方式是最常用的方式。
<div id="app">
<div>
姓名: {{ name }}
</div>
</div>
const vm = new Vue({
el: '#app',
data: {
name: 'ludeng',
}
});
这种方式把el的outerHTML作为template进行编译
最后,从源码角度理解template几种方式的实现:
template源码分析
源码路径:platforms/web/entry-runtime-with-compiler.js
https://github.com/vuejs/vue/blob/dev/src/platforms/web/entry-runtime-with-compiler.js
Vue.prototype.$mount
函数中找到以下代码:
let template = this.$options.template //取template值
if (template) { //设置了template
if (typeof template === 'string') { //template为模板字符串或者 '#tmp'形式
if (template.charAt(0) === '#') { //template:'#tmp'形式
template = idToTemplate(template) // document.querySelector('#tmp').innerHTML
}
} else if (template.nodeType) { //document.querySelector('#tmp')形式
template = template.innerHTML
} else { // template选项无效
return this
}
} else if (el) { //如果没定义template 则把el的outerHTML作为模板
template = getOuterHTML(el)
}
......
compileToFunctions(template) //将template编译为render function
template:'#tmp'形式,调用idToTemplate
idToTemplate:
根据id返回元素的innerHTML作为template
const idToTemplate = cached(id => {
const el = query(id)
return el && el.innerHTML
})
vue会进行缓存,有缓存则读缓存结果,没有缓存则运行回调函数
下面是cached源码:
(shared/util.js)
export function cached(fn){
const cache = Object.create(null)
return (function cachedFn (str) {
const hit = cache[str]
return hit || (cache[str] = fn(str)) //有缓存读缓存,没缓存则运行回调函数
})
}
如果未设置template,则调用getOuterHTML获得el的outerHTML
getOuterHTML:
function getOuterHTML (el){
if (el.outerHTML) {
return el.outerHTML
} else { // 解决firefox没有outerHTML的问题
const container = document.createElement('div')
container.appendChild(el.cloneNode(true))
return container.innerHTML
}
}
总结:
-
template编译主要有两种情况:
- 如果设置了template,将template编译成render function
- 否则将el的outerHTML作为template进行编译
template四种写法:
- template: `<div>姓名:{{ name }}</div>`
- template:'#tmp',
- template: document.querySelector('#tmp'),
- 不写template