Vue组件
Vue组件
组件需要注册后才可以使用,注册分为全局注册和局部注册。
全局注册
全局注册后任何Vue实例都可以使用,子组件必须在父实例创建前注册。
Vue.component('component-name', {
template: '<div>{{ message }}</div>',
data: function () {
return {message: '组件内容'}
}
});
component-name是组件的自定义标签名称,推荐使用小写字母加减号分割的形式命名。
Vue.component方法的第二个参数是一个对象字面量,可以包含template、data、computed、methods等选项。其中data定义组件数据,必须是函数;template选项的值必须被一个html元素包裹
局部注册
app = new Vue({
el: '#app',
components: {
'component-name': {
template: ''
}
}
});
在Vue实例中使用components选项局部注册组件,注册后的组件只在该实例作用域下有效。
组件通信
所谓通信即组件之间传递数据,组件关系可分为父子组件通信、兄弟组件通信、跨级组件通信。
父组件向子组件传递数据
组件的props选项声明从父级接受的数据,props选项既可以是字符串数组也可以是对象。
父级向子组件传递数据,可分为3步:
- 父组件使用子组件时,在子组件标签添加数据属性
- 子组件
props选项声明从父级接受的数据 - 在子组件中应用从父级接受的数据
<div id="app">
<my-component message="来自父组件的数据"></my-component>
</div>
<script>
Vue.component('my-component', {
template: '<div>{{ message }}</div>',
props: ['message']
});
var app = new Vue({
el: '#app'
});
</script>
props选项传入一个对象类型,对从父级接受的数据进行校验。
子组件向父组件传递数据
Vue通过自定义事件,实现子组件向父组件传递数据:
- 子组件通过
$emit(eventName, eventArgument)方法触发自定义事件 - 父组件使用子组件时,在子组件标签使用
v-on指令监听自定义事件
<div id="app">
<my-component @shownumber="handleShownumber"></my-component>
<p>数值:{{ total }}</p>
</div>
<script>
Vue.component('my-component', {
template: '<div @click="handleAdd"></div>',
data : function () {
return {counter : 0};
},
methods : {
handleAdd: function () {
this.counter++;
this.$emit('shomnumber', this.counter);
}
}
});
var app = new Vue({
el: '#app',
data: {
total: 0
},
methods: {
handleShownumber: function (total) {
this.total = total;
}
}
});
</script>
可以通过v-model替代步骤2中的v-on的事件监听
<div id="app">
<my-component v-model="total"></my-component>
<p>数值:{{ total }}</p>
</div>
<script>
Vue.component('my-component', {
template: '<div @click="handleAdd"></div>',
data : function () {
return {counter : 0};
},
methods : {
handleAdd: function () {
this.counter++;
this.$emit('shomnumber', this.counter);
}
}
});
var app = new Vue({
el: '#app',
data: {
total: 0
}
});
</script>
中央事件总线
- 创建空的Vue实例,作为中央事件总线
- 子组件触发事件时,指定事件发起者为中央事件总线($emit方法的调用方是中央事件总线实例)
- 父组件在
mounted钩子函数里监听来自中央事件总线的事件
<div id="app">
<my-component></my-component>
<p>数值:{{ total }}</p>
</div>
<script>
var bus = new Vue();
Vue.component('my-component', {
template: '<div @click="handleAdd"></div>',
data : function () {
return {counter : 0};
},
methods : {
handleAdd: function () {
this.counter++;
bus.$emit('shomnumber', this.counter);
}
}
});
var app = new Vue({
el: '#app',
data: {
total: 0
},
mounted: function () {
var _this = this;
bus.$on('shownumber', function (total) {
_this.total = total;
})
}
});
</script>
内容分发:slot
具名插槽
子组件模板中的<slot>标签添加name属性指定插槽名字
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
父组件分发的内容包裹在<template>中,使用 v-slot 指令 指定分发的插槽名字
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
<template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容 .
v-slot 只能添加在 <template>元素上
作用域插槽
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的
为了让父级中的插槽内容能访问子组件数据,引入作用域插槽:
- 子组件
<slot>元素绑定子组件数据
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
绑定在 <slot> 元素上的 attribute 被称为插槽 prop
- 父组件使用
v-slot访问子组件绑定的插槽prop
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
所有插槽prop会绑定到slotProps变量上

浙公网安备 33010602011771号