1. 组件基础
组件也是一个vue实例,也具有methods,computed,data,计算属性等
<div id="app">
<todo-item :msg="message"></todo-item>
</div>
<script>
//注册全局组件,任何vue实例/组件都能使用
Vue.component('todo-item',{
data: function(){
return {};
},
props:['msg'],
computed: {
},
template: '<div>{{msg}}<div>'
});
var vm = new Vue({
el: '#app',
data: {
message: 'hello Vue!'
},
});
</script>
Vue.component注册的是全局组件,在所有vue实例/组件中都能使用
2. 为什么vue的data是一个函数而不是一个对象?
使用函数能保证每个组件的data的内存是独立的而不是共用。 因为组件是可以复用的,多个组件共用数据会相互影响。
3. 父子组件通信
子组件通过props获取父组件传递的属性值,子组件通过$emit执行父组件的回调函数与父组件进行通信
3.1 子组件通过props获取父组件传递的msg
<div id="app">
<todo-item :msg="message"></todo-item>
</div>
<script>
Vue.component('todo-item',{
props:['msg'],
template: '<div>{{msg}}<div>'
});
var vm = new Vue({
el: '#app',
data: {
message: 'hello Vue!'
},
});
</script>
3.2 子组件通过$emit执行父组件的回调
<div id="app">
<todo-item :msg="message" v-on:todo-click="onClick"></todo-item>
</div>
<script>
Vue.component('todo-item',{
props:['msg'],
template: '<button @click="handleClick">按钮</button>',
data: function(){
return { name: 'ian'};
},
methods: {
handleClick: function(){
//执行父组件的回调函数
this.$emit('todo-click', this.name);
},
},
});
var vm = new Vue({
el: '#app',
data: {
message: 'hello Vue!'
},
methods: {
onClick: function(a){
console.log('获取子组件传递的参数', a);
},
},
});
</script>
$emit(callbackname,param1,param2…) 需要注意的是回调函数的名字不能是驼峰
4. 使用插槽
和 HTML 元素一样,我们经常需要向一个组件传递内容,像这样:
<alert-box>
Something bad happened.
</alert-box>
vue提供了slot插槽用来占位
<div id="app">
<todo-item>foo is not a function</todo-item>
</div>
<script>
Vue.component('todo-item',{
template: `<span>typeError:<span><slot></slot>`
});
var vm = new Vue({
el:'#app',
});
</script>
5. 局部组件和全局组件
像上面使用Vue.component组件的是全局组件,可以通过添加components属性注册局部组件
<div id="app">
<todo-item></todo-item>
<component-a></component-a>
</div>
<script>
//全局组件
Vue.component('todo-item', {
template: '<div>todolist</div>'
});
//局部组件
const ComponentA = {
data: function () {
return { name: 'ian' };
},
template: '<div>{{name}}</div>'
};
var vm = new Vue({
el: '#app',
data: {
message: 'hello vue'
},
components: {
'component-a': ComponentA
}
});
</script>
在单页应用中全局组件的打包产物会一直存在,直到根节点上的vue实例销毁,也就是说即使我当前这个页面没有用到的全局组件也会加载。通常的做法是将一些基础的、频繁使用的组件注册到全局,其余的全部注册局部组件。
6. 组件的命名规则
我们知道vue的属性(包含计算属性)和方法是不能使用驼峰命名的,而组件是支持驼峰命名的
Vue.component('todo-item', ...);
//使用驼峰命名
Vue.component('TodoItem', ...);
7. 动态组件
vue提供了一个特殊的is属性用来渲染动态组件。动态组件的意思是:当多个组件需要依赖某个变量进行切换显示的时候,只有当前被展示的组件是存活的,其它的组件都是被销毁的状态。
var ArticleA = {
template: `<ul>
<li>《笑傲江湖》</li>
<li>《雪山飞狐》</li>
<li>《倚天屠龙记》</li>
<ul>`
};
var ArticleB = {
template: `<ul>
<li>《你不知道的JavaScript》</li>
<li>《前端微服务》</li>
<li>《html编程指南》</li>
<ul>`
};
var vm = new Vue({
el: '#app',
data: {
active: 'ArticleA',
},
components: {
ArticleA,
ArticleB,
},
methods: {
toogleView: function () {
this.active = this.active === 'ArticleA' ? 'ArticleB' : 'ArticleA';
},
},
});
默认显示组件ArticleA,点击切换按钮的时候ArticleA组件被销毁,ArticleB组件渲染.。
8. keep-alive 缓存
前面我们提到在使用动态组件的时候,会有一个旧组件销毁新组件渲染的过程。而使用keep-alive能使旧组件不被销毁,组件被缓存起来,仍然是存活状态。
var ComA = {
data: function () {
return { count: 0 };
},
template: '<div>count: {{count}} <button @click="count++">加一</button></div>'
};
var ComB = {
template: `<ul>
<li>《你不知道的JavaScript》</li>
<li>《前端微服务》</li>
<li>《html编程指南》</li>
<ul>`
};
var vm = new Vue({
el: '#app',
data: {
active: 'ComA',
},
components: {
ComA,
ComB,
},
methods: {
toogleView: function () {
this.active = this.active === 'ComA' ? 'ComB' : 'ComA';
},
},
});
在组件A显示的时候点击按钮将A组件的count更新为3,切到B组件再切回来,A组件的状态还在,count还是3。需要注意的是添加keep-alive的组件不会走mounted和destroy这两个生命周期,而是会走keep-alive专属的周期函数。在使用缓存渲染视图的时候走active,在退出缓存的时候走deactive。
总结:
- 组件也是一个实例,有自己的独立的属性和状态
- 组件的data是一个函数,这样能保证每个组件的data彼此独立而不是共用
- 子组件通过props接收父组件传递的属性值,子组件通过$emit执行父组件的回调函数
- 使用slot占位解析html
- 组件分为局部组件和全局组件,通常将最基础的、频繁使用的注册为全局组件
- 组件的命名支持驼峰和以’-'分隔
- 使用is渲染动态组件,在切换的过程中旧组件被销毁新组件渲染
|