父子组件通信问题
- 只有父元素和子元素
父元素通过 props 给子元素传递数据,子元素通过$emit 方法通过事件的方法向父元素传递数据
// 父元素
<Tab :currentTab="currentTab" :tablist="tablist" @change-tab="tabChange"></Tab>
<script>
import Tab from '../../../components/Tab1'
export default {
components: { Tab },
methods: {
tabChange(index) {
this.currentTab = index
}
}
}
</script>
// 子元素
<template>
<div class="head">
<div class="tab" :currentTab="currentTab" v-for="(item, index) in tablist" :key="index" :class="[currentTab === index ? 'active' : '']" @click="tabChange(index)">
<span>{{item.name}}</span>
<span :class="item.theme" v-if="item.count && item.showCount"></span>
</div>
</div>
</template>
<script>
export default {
props: {
tablist: {
type: Array
},
currentTab: Number
},
methods: {
tabChange(index) {
this.$emit('change-tab', index)
}
}
}
</script>
- 多级组件嵌套
通过特性绑定 a t t r s 和 attrs和 attrs和listeners,父组件 A 下面有子组件 B,子组件 B 下面有子组件 C
父组件 A
<attrOne :one="one" :two="two" :three="three" :four="four" title="父组件" v-on="$listeners" @sendMsg="sendMsg"></attrOne>
<script>
import attrOne from '../../components/attrOne'
import Vue from 'vue'
export default {
data() {
return {
one: 'html',
two: 'css',
three: 'javaScript',
four: 'vue',
color: 'blue'
}
},
components: { attrOne },
provide() {
return {
theme: this
}
},
methods: {
test(color) {
console.log('123')
if (color) {
this.color = this.color
}
this.color = this.color === 'blue' ? 'red' : 'blue'
},
sendMsg(val) {
console.log('子传第二层父元素', val)
}
}
}
</script>
子组件 B
<template>
<div>
<p>我是第一个子组件 {{ one }}</p>
<p>第一个子组件的$attr {{ $attrs }} </p>
<attrThree v-bind="$attrs" v-on="$listeners" @sendMsg="sendMsg"></attrThree>
</div>
</template>
<script>
import attrTwo from '../components/attrTwo'
import attrThree from '../components/attrThree'
export default {
props: {
one: {
type: String
}
},
components: { attrTwo, attrThree },
inheritAttrs: false,
created() {
console.log('第一个', this.$attrs)
console.log('第一个', this.$listeners)
// console.log('inject', this.name)
},
mounted() {
},
methods: {
sendMsg(val) {
console.log('子传第一个父元素', val)
}
}
}
</script>
子组件 C
<template>
<div>
<p>我是第二个子组件 {{ three }}</p>
<p @click="send">第二个子组件的$attr {{ $attrs }} </p>
</div>
</template>
<script>
export default {
props: {
three: {
type: String
},
four: {
type: String
}
},
created() {
console.log('第二个', this.$attrs)
console.log('第二个', this.$listeners)
},
methods: {
send() {
this.$emit('sendMsg', '我是子组件信息')
}
}
}
</script>
- 中央事件总线 Events Bus
新建一个 Vue 事件 bus 对象,然后通过 bus. e m i t 触 发 事 件 , b u s . emit触发事件,bus. emit触发事件,bus.on 监听触发的事件。
// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()
//子组件
<template>
<button @click="decrease()">-</button>
</template>
<script>
import { EventBus } from '../event-bus.js'
export default {
name: 'DecreaseCount',
data() {
return {
num: 1,
deg: 180
}
},
methods: {
decrease() {
EventBus.$emit('decreased', {
num: this.num,
deg: this.deg
})
}
}
}
</script>
// 父组件
<!-- App.vue -->
<template>
<div id="app">
<div class="container">
<div class="front">
<div class="increment">
<IncrementCount />
</div>
<div class="show-front">{{ fontCount }}</div>
<div class="decrement">
<DecreaseCount />
</div>
</div>
</div>
</div>
</template>
<script>
import IncrementCount from '../../components/incrementCount'
import DecreaseCount from '../../components/decreaseCount'
import { EventBus } from '../../event-bus'
export default {
name: 'App',
components: {
IncrementCount,
DecreaseCount
},
data() {
return {
degValue: 0,
fontCount: 0,
backCount: 0
}
},
mounted() {
EventBus.$on('incremented', ({ num, deg }) => {
// 修改数据
this.fontCount += num
// DOM还没更新
// $nextTick,将回调延迟到下次 DOM 更新循环之后执行。
this.$nextTick(() => {
// DOM已经更新
this.backCount += num
this.degValue += deg
})
})
EventBus.$on('decreased', ({ num, deg }) => {
this.fontCount -= num
this.$nextTick(() => {
this.backCount -= num
this.degValue -= deg
})
})
}
}
</script>
- provide / inject
允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。
inject 可以是:一个字符串数组或者一个对象,对象的 key 是本地的绑定名。
<attrOne
:one="one"
:two="two"
:three="three"
:four="four"
title="父组件"
v-on="$listeners"
@sendMsg="sendMsg"
@changeParent="changeParent"
></attrOne>
// 父组件
provide() {
// 让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象,返回的对象可以直接用于渲染函数和计算属性内,并且会在发生改变时触发相应的更新。也可以作为最小化的跨组件状态存储器.
this.theme = Vue.observable({
color: 'blue'
})
return {
theme: this.theme
}
},
test(color) {
this.color = this.color === 'blue' ? 'red' : 'blue'
// 子组件响应式更新
this.theme.color = this.theme.color === 'blue' ? 'red' : 'blue'
},
// 子组件 两种方法
inject: ['theme'],
inject: {
theme: {
//函数式组件取值不一样
default: () => ({})
}
},
- $parent / $children 只单纯适用于父子组件,兄弟间的组件不适用,
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例 - vuex 这是链接