作者简介:
李中凯
八年多工作经验 前端负责人,
擅长JavaScript/Vue。
掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/posts
公众号:1024译站
定义 Vue.js 组件模板有多种方式,据我所知,至少有7种不同的方法。
本文将逐一介绍每种方法的示例,并讨论其优缺点,以便你了解在特定情况下使用哪种方法最好。
普通字符串
定义 Vue 组件模板最快也是最容易的方式就是给组件定义加上一个 template 属性,它的值就是包含 HTML 标签的普通字符串。
但是,这种方法实际上只在代码示例或快速原型中使用,因为模板过于简单,不太实用。
app.js
Vue.component('my-checkbox', {
template: '<div class="checkbox-wrapper" @click="check"><div :class="{ checkbox: true, checked: checked }"></div><div class="title">{{ title }}</div></div>',
data() {
return { checked: false, title: 'Check me' }
},
methods: {
check() { this.checked = !this.checked; }
}
});
模板字符串
从 ES2015 开始,可以用反引号定义一种特殊的字符串,叫做模板字面量。跟普通字符串不用,它可以内嵌表达式,并支持多行。
支持多行的特性让它在定义组件模板时比普通字符串方便多了,因为可以让多行标签可读性更好。
app.js
Vue.component('my-checkbox', {
template: <div class="checkbox-wrapper" @click="check"> <div :class="{ checkbox: true, checked: checked }"></div> <div class="title">{{ title }}</div> </div>
,
data() {
return { checked: false, title: 'Check me' }
},
methods: {
check() { this.checked = !this.checked; }
}
});
较老的浏览器可能不支持 ES2015 特性,因此需要用 Babel 转换代码。
x-template
这种方式是将模板定义在 HTML 文件里的 script 标签里。script 标签需要指定type="text/x-template ",并通过 id 属性在组件里引用。
好处是可以在 HTML 文件里写模板标记,非常直观。坏处就是模板和组件的其他部分分离了,查找起来不太方便。
app.js
Vue.component('my-checkbox', {
template: '#checkbox-template',
data() {
return { checked: false, title: 'Check me' }
},
methods: {
check() { this.checked = !this.checked; }
}
});
index.html
<div id="app">...</div>
<script type="text/x-template" id="checkbox-template">
<div class="checkbox-wrapper" @click="check">
<div :class="{ checkbox: true, checked: checked }"></div>
<div class="title">{{ title }}</div>
</div>
</script>
inline template
用这个方法可以在父模板中定义组件的模板。需要给标签加上inline-template 属性,以便让 Vue 知道在哪找到它。
这个方法跟 x-template 的优缺点差不多,不过有一点区别,由于模板是定义在文档 body 里的,因此它的内容可以被爬虫识别,有利于 SEO。
app.js
Vue.component('my-checkbox', {
data() {
return { checked: false, title: 'Check me' }
},
methods: {
check() { this.checked = !this.checked; }
}
});
index.html
<div id="app">
...
<my-checkbox inline-template>
<div class="checkbox-wrapper" @click="check">
<div :class="{ checkbox: true, checked: checked }"></div>
<div class="title">{{ title }}</div>
</div>
</my-checkbox>
</div>
inline templates 和 x-template 可以与后端框架(例如Laravel Blade)中的模板引擎结合使用。
render 函数
render 函数要求你用纯 JavaScript 定义模板。具体语法可以参考 Vue 文档 ,大体就是通过调用 createElement(tag, options, childElements)创建模板节点。
这样做的好处是,它不需要编译,并且你可以完全利用 JavaScript 的能力,而不是局限于指令提供的功能。例如,模板里的循环只能通过v-for,但在 JavaScript 里你可以用任何数组方法。
但是,与其他模板选项相比,render 函数更加冗长和抽象,我估计没人愿意用这种方法写完整个应用。
app.js
Vue.component('my-checkbox', {
data() {
return { checked: false, title: 'Check me' }
},
methods: {
check() { this.checked = !this.checked; }
},
render(createElement) {
return createElement(
'div', {
attrs: {
'class': 'checkbox-wrapper'
},
on: {
click: this.check
}
},
[
createElement(
'div', {
'class': {
checkbox: true,
checked: this.checked
}
}
),
createElement(
'div', {
attrs: {
'class': 'title'
}
},
[this.title]
)
]
);
}
});
JSX
JSX 是 JavaScript 的一个扩展,它可以在 JavaScript 代码里使用特殊的模板语法。
JSX 本来是 React 的一个特性,在 Vue 的模板中使用它一直备受争议,因为一些开发人员认为它丑陋、不直观,跟 Vue 的气质不符。
但是,用 JSX 写 Vue render 函数,可读性高得多,也没那么抽象。不过它需要编译,因为浏览器可不认识 JSX。
app.jsx
Vue.component('my-checkbox', {
data() {
return { checked: false, title: 'Check me' }
},
methods: {
check() { this.checked = !this.checked; }
},
render() {
return <div class="checkbox-wrapper" onClick={ this.check }>
<div class={{ checkbox: true, checked: this.checked }}></div>
<div class="title">{ this.title }</div>
</div>
}
});
单文件组件
Vue.js 最受欢迎的特性之一就是 单文件组件(SFC)。它可以将模板和组件定义全部放在一个文件里。里面的模板会被 vue-loader 编译成 render 函数,因此也可以获得最佳的运行时性能。
单文件组件是一个.vue文件,比如Checkbox.vue,在 template 标签中定义模板, script 标签中定义组件属性和逻辑。然后就可以在应用中导入使用了。
只要你习惯使用 Vue CLI 或者其他构建工具,单文件组件是个不错的选择。
Checkbox.vue
<template>
<div class="checkbox-wrapper" @click="check">
<div :class="{ checkbox: true, checked: checked }"></div>
<div class="title">{{ title }}</div>
</div>
</template>
<script>
export default {
data() {
return { checked: false, title: 'Check me' }
},
methods: {
check() { this.checked = !this.checked; }
}
};
</script>
谁是王者
吧啦这么多,到底哪种方法最好?本文的答案是:单文件组件,因为它是几乎所有场景中最通用、最强大的选择。
实际上,以上每一种方法在特定的场景中都有优势,应该根据你的实际情况进行判断。熟悉每一种用法,说不定哪天就用上了呢!
作者简介:
李中凯
八年多工作经验 前端负责人,
擅长JavaScript/Vue。
掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/posts
公众号:1024译站
本文已经获得李中凯老师授权转发,其他人若有兴趣转载,请直接联系作者授权。