父子组件通信: props、 $parent / $children、 provide / inject 、 ref 、 $attrs / $listeners
兄弟组件通信:EventBus 、 Vuex
跨级组件通信: EventBus 、 Vuex 、 provide / inject 、 $attrs / $listeners
父传子 子组件用 props 接收,父组件用 v-bind:prop 发送
父组件
<template>
<div class="section">
<com-article :articles="articleList"></com-article>
</div>
</template>
<script>
import comArticle from "./comArticle";
export default {
data() {
return {
articleList: ["红楼梦", "西游记", "三国演义", "水浒传"]
}
},
components: { comArticle },
}
</script>
子组件
<template>
<ul>
<li v-for="(item, index) in articles" :key="index">{{item}}</li>
</ul>
</template>
<script>
export default {
props: ["articles"]
}
</script>
子传父 子组件用 v-on:click="" this.$emit('name', this.msg)(【有的版本名称只能小写】)发送,父组件自定义事件 v-on:name="getChildValue" 然后在 getChildValue(data){} 方法中接收
父组件
<template>
<div class="section">
<com-article @onEmitIndex="onEmitIndex"></com-article> 【不能加括号】
<ul>
<li v-for="(item, index) in articles" :key="index">{{item}}</li>
</ul>
</div>
</template>
<script>
import comArticle from "./com2";
export default {
data() {
return {
articles:[]
};
},
components: { comArticle },
methods: {
onEmitIndex(data) {
this.articles = data;
}
}
}
</script>
子组件
<template>
<div>
<button @click="emitIndex()">点击把articleList传给父组件</button> 【可以传参】
</div>
</template>
<script>
export default {
data() {
return {
articleList: ["红楼梦", "西游记", "三国演义", "水浒传"]
};
},
methods: {
emitIndex() {
this.$emit("onEmitIndex", this.articleList); //
}
}
}
</script>
父子传参还可以用 $parent(对象)和 $children(数组)
provide / reject (上传下)
父辈组件中通过 provide 来提供变量,子孙组件中通过 reject 来注入变量。
父组件
<template>
<div>
com1 是父组件
<com2></com2>
</div>
</template>
<script>
import com2 from './com2.vue'
export default {
provide: {
msg: "这是父辈组件 com1 传出去的数据"
},
components:{
com2
}
}
</script>
子组件
<template>
<div>
com2 是 com1 的子组件
{{demo}}
<com3></com3>
</div>
</template>
<script>
import com3 from './com3.vue'
export default {
inject: ['msg'],
data() {
return {
demo: this.msg
}
},
components: {
com3
}
}
</script>
孙组件
<template>
<div>
com3 是 com1 的孙组件
{{msg}}
</div>
</template>
<script>
export default {
inject: ['msg']
}
</script>
ref
如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据 ref="xx" this.$refs.xx
eventBus(事件总线,项目较大难以维护,组件都可以传) $emit(name, data)发送 $on(name, data=>{})接收 【名称小写】
event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()
com1.vue 发送事件
<button @click="additionHandle">加法器</button>
import {EventBus} from './event-bus.js'
data(){
return {num: 1}
},
additionHandle(){
EventBus.$emit('addition', {num: this.num++}
)
com2.vue 接收事件
<div>计算和: {{count}}</div>
data() {
return {count: 0}
},
mounted() {
EventBus.$on('addition', param => {
this.count = this.count + param.num;
})
}
localStorage / sessionStorage
因为 window.loacalStorage.setItem(key, value)、window.loacalStorage.getItem(key) 储存的是字符串,需要用 JSON.parse() / stringify() 转换
可结合 vuex,实现数据持久保存和解决数据及状态混乱问题
$attrs $listeners(仅仅是传递数据,而不做中间处理,使用 vuex 处理,未免有点大材小用)
test.vue
<template>
<div>
test.vue
<child-com1 :name="name" :age="age" :gender="gender" :height="height" title="test.vue 传出的值"></child-com1>
</div>
</template>
<script>
const childCom1 = () => import("./com1.vue");
export default {
components: { childCom1 },
data() {
return {
name: "zhangsan",
age: "18",
gender: "女",
height: "158"
};
}
};
</script>
<style scoped>
div{
background-color: #ddd;
}
</style>
com1.vue
<template>
<div class="com1">
com1
<p>name: {{name}}</p>
<p>childCom1的$attrs: {{$attrs}}</p>
<child-com2 v-bind="$attrs"></child-com2>
</div>
</template>
<script>
const childCom2 = () => import("./com2.vue");
export default {
components: {
childCom2
},
inheritAttrs: false, // 关闭自动挂载到组件根元素上的没有在 props 声明的属性
props: {
name: String
},
created() {
console.log(this.$attrs);
// {age: "18", gender: "女", height: "158", title: "test.vue 传 com1.vue"}
}
};
</script>
<style scoped>
.com1{
margin: 20px;
background-color: #f00;
}
</style>
com2.vue
<template>
<div>com2
<p>age: {{age}}</p>
<p>childCom2: {{ $attrs }}</p>
</div>
</template>
<script>
export default {
inheritAttrs: false,
props: {
age: String
},
created() {
console.log('com2', this.$attrs);
// { "name": "zhang", "gender": "女", "height": "158", "title": "程序员成长指北" }
}
};
</script>
<style scoped>
div{
background: #0f0;
margin: 20px
}
</style>