Vue组件系统提供了一种抽象,让我们可以使用独立可复用的组件来构建大型应用,任意类型的应用程序界面都可以抽象为一个组件树。组件化可以提高开发效率,方便重复使用,简化调试步骤,提升项目可维护性,便于多人协同开发。
组件通信
props
父给子传值
1 2 3 4 5
| props:{ msg: String}
<HelloWorld msg="hello world">
|
自定义事件
子给父传值
1 2 3 4
| this.$emit('add', good)
<Cart @add="cartAdd($event)"></Cart>
|
事件总线
任意两个组件之间传值常用事件总线或vuex的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Bus{ constructor(){ this.callbacks={} } $on(name,fn){ this.callbacks[name]=this.callbacks[name]||[] this.callbacks[name].push(fn) } $emit(name,args){ if(this.callbacks[name]){ this.callbacks[name].forEach(cb => cb(args)) } } }
Vue.prototype.$bus = new Bus()
this.$bus.$on('foo',msg => {})
this.$bus.$emit('foo',msg)
|
实践中通常用Vue代替Bus,因为Vue已经实现了相应的接口
vuex
创建唯一的全局数据管理者store,通过他管理数据并通知组件状态变更
详细见Vue统一状态管理——Vuex
$parent/$root
兄弟组件之间通信可以通过共同的祖辈搭桥,$parent或$root,与Bus总线类似
1 2 3 4 5
| this.$parent.$on('foo',msg => {})
this.$parent.$emit('foo',msg)
|
$children
父组件可以通过$children访问子组件,实现父子通信
1 2
| this.$children[0].xx = 'xxx'
|
注意:$children不能保证子元素顺序 (异步组件)
$attr/$listener
包含了父作用域中不作为prop被识别(且获取)的特性绑定(class和style除外)。当一个组件没有声明任何prop时,这里会包含所有父作用域的绑定(class和style除外),并且可以通过 vbind=”$attrs”传入内部组件——在创建高级别的组件时非常有用。
1 2 3 4 5
| <p>{{$attrs.foo}}</p>
//parent <Helloworld foo = 'foo'>
|
refs
获取子节点引用
1 2 3 4 5 6
| <Helloworld ref='hw'>
mounted(){ this.$refs.hw.xx = '' }
|
provide/inject
能够实现祖先和后代之间传值(依赖注入)
1 2 3 4 5 6 7 8 9 10 11
| provide(){ return { foo:'foooooo' } }
<p>{{foo}}</p>
inject:['foo']
|
也可以使用别名
1 2 3 4
| <p>{{bar}}</p>
inject:{bar:{from:'foo'}}
|
provide和inject主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。
插槽
插槽语法是Vue实现的内容分发API,用于复合组件开发。该技术在通用组件库开发中有大量应用。
匿名插槽
1 2 3 4 5 6 7 8 9
| <div> <solt></solt> </div>
<Comp1> <template>content...</template> </Comp1>
|
具名插槽
将内容分发到子组件指定位置
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div> <solt></solt> <solt name="content"></solt> </div>
<Comp2> <template v-solt:default>具名插槽</template> <template v-solt:content>内容。。</template> <Comp2>
|
作用域插槽
分发内容要用到子组件中的数据
1 2 3 4 5 6 7 8 9 10 11 12
| <div> <solt :foo="foo"></solt> </div>
<Comp3> <template v-solt:default="soltProps"> 来自子组件数据:{{soltProps.foo}} </template> </Comp3>
|
范例
1 2 3 4 5 6 7 8 9 10 11 12
|
<Layout>
<template v-slot:footer="{fc}">{{fc}}</template> </Layout>
<div class="footer"> <slot name="footer" :fc="footerContent"></slot> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import Layout from '@/components/slots/Layout.vue' export default { components: { Layout }, }
data() { return { remark: [ '好好学习,天天向上', '学习永远不晚', '学习知识要善于思考,思考,再思考', '学习的敌人是自己的满足,要认真学习一点东西,必须从不自满开始', '构成我们学习最大障碍的是已知的东西,而不是未知的东西', '在今天和明天之间,有一段很长的时间;趁你还有精神的时候,学习迅速办事', '三人行必有我师焉;择其善者而从之,其不善者而改之' ] } }, computed: { footerContent() { return this.remark[new Date().getDay() - 1] } },
|