前言
前面系列文章:
Vue的有有两大特性
- 渐进式
- 组件
渐进式是Vue底层的设计,我们不先关心,第三章着重介绍组件(component )的使用。和指令,过滤器一样,组件可以分为局部组件和全局组件,定义方式也都大同小异。
基础实例
在真正介绍component
之前,先介绍 Vue.extend({Object} options) 。Vue.extend()
使用基础 Vue 构造器,创建一个“子类”,参数是一个包含组件选项的对象。data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数。 后面会介绍到这里的data为什么不是对象而是一个函数。
<body>
<div id="app"></div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#app')
</script>
</body>
<!--
渲染结果:
Walter White aka Heisenberg
-->
在上面建立了一个Vue.extend()
并把它通过$mount
挂载到DOM上,但是通过这种方式好像只能使用一次,如果使用组件就不会有这种问题,因为组件是可以复用的。
<body>
<div id="app">
<my-component></my-component>
<my-component></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
// new Profile().$mount('#app')
Vue.component("my-component",Profile)
// 创建Vue实例
var app = new Vue({
el: '#app'
})
</script>
</body>
<!--
Walter White aka Heisenberg
Walter White aka Heisenberg
-->
以上就是一个使用Vue.component
创建最基本的组件,也就是说它们在注册之后可以用在任何新创建的 Vue 根实例new Vue()
的模板中。首先,第一个参数就是我们所需要的定义的组件名,这个可以使用短横线命名(如实例中的),也可以使用“驼峰命名”,如果使用“驼峰命名”,那么在使用的过程中就必须改成成短横线的形式,当然如果是在字符串模板(反引号``选中的,如上面的template)中是没有这个限制的,如下:
<body>
<div id="app">
<p>+++++++++++</p>
<myComponent></myComponent>
<p>+++++++++++</p>
<my-component></my-component>
<p>+++++++++++</p>
<test></test>
<p>+++++++++++</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
Vue.component("myComponent",Profile)
// 简写
Vue.component("test",{
template: '<myComponent></myComponent>',
})
new Vue({
el: '#app',
})
</script>
</body>
<!--
渲染结果:
+++++++++++
+++++++++++
Walter White aka Heisenberg
+++++++++++
Walter White aka Heisenberg
+++++++++++
-->
在div中声明了三个组件,第一个是“驼峰命名”,第二个短横线命名,第三个是在字符串模板中使用“驼峰命名”。根据结果我们可以看到,第一个没有显示,其他都能正常显示。在新定义的test组件中,没有再声明Vue.extand()
而是用对象代替,其实后者是前者的简写,熟悉以后大家就可以这样声明一个全局组件:
Vue.component('my-component-name', { /* ... */ })
局部注册
<body>
<div id="app">
<profile></profile>
<my-com></my-com>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
components:{
profile:{
template:`<h1>profile</h1>`
},
"my-com":{
template:`<h1>myComponent</h1>`
}
}
})
</script>
</body>
在Vue实例中,定义了一个components
属性对象,和Vue,extand()
一样,我们只需要以对象的形式在里面实现组件就好。需要注意的是短横线命名需要用引号包裹。
其他知识
可能大家也看出来了,使用字符串模板编写html实在有些一言难尽吗,Vue中也给我们提供了一个新的标签<template></template>
,我们只需要指明template标签的id,直接引用就好:
<!--html-->
<template id="html">
<div>
<p>大风起兮云飞扬</p>
<p>维加海内西归故乡</p>
</div>
</template>
<!--javascript-->
Vue.component("my-template",{
template: "#html"
})
值得注意的是,如果template里面需要有多个标签的话,需要用一个标签进行包裹,然后在里面书写,如上面的<div></div>
。
如果想要控制两个组件的切换(显示|消失)的话,怎么办那?肯定下意识就会想到用if和show这两条指令,这样当然可以,不过Vue还为组件提供了一个is属性,来实现这个效果。当然光有is属性还不够,需要和<component></component>
标签搭配使用:
<body>
<div id="app">
<button @click="myButton">切换</button>
<keep-alive>
<component :is="componentName"></component>
</keep-alive>
</div>
<template id="template">
<div class="temp">
<h1>雕栏玉砌应犹在</h1>
<h2>雕栏玉砌应犹在</h2>
<h3>雕栏玉砌应犹在</h3>
</div>
</template>
<template id="footer">
<div>
<h1>只是朱颜改</h1>
<h2>只是朱颜改</h2>
<h3>只是朱颜改</h3>
<input type="checkbox">
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component("my-component",{
template:"#template"
})
var app = new Vue({
el: '#app',
data: {
componentName:"my-component"
},
methods: {
myButton(){
this.componentName = this.componentName == "my-component" ? "my-footer" : "my-component"
}
},
components:{
"my-footer":{
template:"#footer"
}
}
})
</script>
</body>
上面的案例可以帮助我们实现组件之间的切换,也就是说is指向的是想要显示的组件名称。
<keep-alive>
<component :is="componentName"></component>
</keep-alive>
不过上面可以看出,在<component></component>
标签之外还有一层标签<keep-alive></keep-alive>
,它的作用就是保存状态。在footer组件中定义了一个checkbox,选中这个单选框,在切换的组件时候,如果没有keep-alive标签的话,单选框就不会是选中状态。想要保持选中就需要在外层加个<keep-alive></keep-alive>
标签。
总结
组件其实就是一个Vue()
实例,不过这个实例是一个大组件。实例既然是组件,那么实例中的属性对象在组件中也是可以使用的,比如之前的methods,computed,watch……,data除外,data在组件中是一个函数,而非一个对象。因为组件的可复用性,如果声明的多个组件都对data中的同一条数据进行操作的话,那么数据就会混乱。而使用函数的话,那么声明的多个组件就只会对自己的数据进行操作。比如有一个苹果(data中的数据),有多个人(多个组件),之前是多个人抢这一个苹果,后来改成函数了,就相当于一个人给了一个苹果,而且为了防止眼红,还把一个人专门放到一个屋子中了,这样这个苹果到底怎么处理只有自己知道。