1、组件间的通讯vue
组件实例的做用域是孤立的;这意味着不能而且不该该在子组件的模板内直接引用父组件的数据。可是父子组件之间须要通讯:父组件要给子组件传递数据,子组件须要将它内部发生的事情告知给父组件。数组
在 Vue.js 中,父子组件的关系能够总结为 props down, events up 。父组件经过 props 向下传递数据给子组件,子组件经过 events 给父组件发送消息。以下图所示:this
2、 Prop — 父组件传递数据给子组件spa
prop 是父组件用来传递数据的一个自定义属性。子组件须要显式地用 props 选项声明 “prop”:3d
Vue.component('child', {component
// 声明 props对象
props: ['message'],索引
// 就像 data 同样,prop 能够用在模板内接口
// 一样也能够在 vm 实例中像 “this.message” 这样使用事件
template: '<span>{{ message }}</span>'
})
2.1 简单的传值
注意:HTML 特性不区分大小写。当使用非字符串模版时,prop的名字形式会从 camelCase 转为 kebab-case(短横线隔开)。
2.2 父组件传值给子组件,动态绑定
运行结果:
父组件传递数据给子组件图解:
2.3 prop默认是单向绑定
当父组件的属性变化时,将传导给子组件,可是反过来不会。这是为了防止子组件无心修改了父组件的状态。
案例验证:
运行结果:
结论:在vuejs2.0中,任何试图在组件内修改经过props传入的父组件数据都被认为是anti-pattern的。
3、自定义事件
咱们知道,父组件是使用 props 传递数据给子组件,但若是子组件要把数据传递回去,应该怎样作?那就是自定义事件!
每一个 Vue 实例都实现了事件接口(Events interface),即:
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
另外,父组件能够在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
一个简单的官方案例帮助咱们来理解:
运行结果:子组件已经和它外部彻底解耦了。它所作的只是触发一个父组件关心的内部事件。
4、Slot插槽 — 实现内容分发
父组件模板的内容在父组件做用域内编译;子组件模板的内容在子组件做用域内编译
上面话的意思在于:在子组件中定义的数据,只能用在子组件的模板;在父组件中定义的数据,只能用在父组件的模板。若是父组件的数据要在子组件中使用,则须要子组件定义props。
4.1 什么是slot?
slot的意思是插槽,其目的在于让组件的可扩展性更强。打个比方说:假如父组件须要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪一个地方显示、如何显示,就是slot分发负责的。
(1) 匿名solt
下面这个示例是一个匿名slot,它只能表示一个插槽:
结合上述案例,咱们再进一步来了解:好比咱们定制了一个button组件,在根组件里注册为vButton,从而复用。那么各个button上的文字确定是不一样的,可是这些文字大部分状况下也是不须要动态更新的,那么就没必要用props之类的方法从根组件向子组件传递文字,直接用slot便可。
(2) 实名solt
假设你的电脑主板上的各类插槽,有插CPU的,有插显卡的,有插内存的,有插硬盘的,因此假设有个组件是computer,其模板是:
<template id="computer">
<div>
<slot name="CPU">这儿插你的CPU</slot>
<slot name="GPU">这儿插你的显卡</slot>
<slot name="Memory">这儿插你的内存</slot>
<slot name="Hard-drive">这儿插你的硬盘</slot>
</div>
</template>
那么,你想要配置一台电脑,就能够这么写:
<computer>
<div slot="CPU">Intel Core i7</div>
<div slot="GPU">GTX980Ti</div>
<div slot="Memory">Kingston 32G</div>
<div slot="Hard-drive">Samsung SSD 1T</divt>
</computer>
具体代码以下:
5、父子组件之间相互访问
在开发中,组件之间须要相互访问。好比:父组件访问子组件,子组件访问父组件,或者是子组件访问根组件。
针对这种状况,Vue.js提供了如下API:
父组件访问子组件:使用$children或$refs (一个对象,其中包含了全部拥有 ref 注册的子组件)
子组件访问父组件:使用$parent
子组件访问根组件:使用$root
5.1 $children
运行结果:
在父组件中,经过this.$children能够访问子组件;this.$children是一个数组,它包含全部子组件的实例。
5.2 $refs
在子组件上使用v-ref指令,能够给子组件指定一个索引ID;经过这个ID咱们能够拿到这个组件。
<template id="parent-component">
<div>
<first-component ref="fc1"></first-component>
<second-component ref="fc2"></second-component>
<button @click="printAllChildComponent">输出子组件</button>
</div>
</template>
在父组件中,则经过```$refs.索引ID```访问子组件的实例。
5.3 $parent
<template id="first-component">
<div>
<h2>{{ content }}</h2>
<button @click="printParentComponent">获取父组件</button>
</div>
</template>
'first-component': {
template: '#first-component',
data:function () {
return {
content: '我是子组件1'
}
},
methods: {
printParentComponent: function () {
console.log(this.$parent.$el);
}
}
}
运行结果:
注意事项:
尽管子组件能够访问父链上任意的实例,不过子组件应当避免直接依赖父组件的数据,尽可能显式地使用 props 传递数据。
另外,在子组件中修改父组件的状态是很是不提倡的作法,由于:这让父组件与子组件紧密地耦合;只看父组件,很难理解父组件的状态。由于它可能被任意子组件修改!理想状况下,只有组件本身能修改它的状态。