遇到这样一种需求场景:点赞为子组件,页面为父组件
vue子组件变化父组件未监测到,点赞时父组件的点赞人数未自动更新。
vue父组件变化子组件未监测到,发表动态后列表数据变化,子组件还保持原来的顺序。
发表前:
发表后:
父组件page.vue:
<!--父组件-->
<div v-for="(item, index) in dataList" :key="index">
<my-cmp-like :isLike="item.isGood==='1'?true:false" :likeId="item.id" :index="index"></my-cmp-like>
</div>
子组件MyLike.vue(点赞):
<!--子组件-->
props: {
isLike: {
type: Boolean,
default: false
},
likeId: {
type: String,
default: ''
},
index: {
type: Number,
default: 0
}
}
vue为单向数据流,数据从父级组件传递给子组件,只能单向绑定,子组件内部不能直接修改从父级传递过来的数据。
- 方法一:在子组件中利用
$parent
直接修改父组件数据。(不推荐该方式,原因见下文末)
MyLike.js:
<!--子组件-->
this.$parent.dataList[this.index].praiseNameList = res.data.data.praiseNameList;
- 方法二:通过
$emit
向父组件传递方法
<!--父组件-->
<template>
<my-cmp-like @praiseChange="updatePraise" :isLike="item.isGood==='1'?true:false" :likeId="item.id" :index="index"></my-cmp-like>
</template>
<script>
import myCmpLike from './ChildCount';
export default{
components: {
myCmpLike,
},
methods: {
updatePraise(index, data) {
this.dataList[index].praiseNameList = data;
},
},
};
</script>
<!--子组件-->
this.$emit('praiseChange', this.index, res.data.data);
父组件中:key="index"
未发生变化,故监测不到,改为:key="item.id"
<!--父组件-->
<div v-for="(item, index) in dataList" :key="item.id">
<my-cmp-like :isLike="item.isGood==='1'?true:false" :likeId="item.id" :index="index"></my-cmp-like>
</div>
vue父子组件通信总结:
父组件向子组件通信
- 通过
props
传递数据
<template>
<div>
<h2>父组件</h2>
<child-count :msg="message"></child-count>
</div>
</template>
<script>
import childCount from './ChildCount';
export default{
components: {
childCount,
},
data: {
message: '信息'
},
};
</script>
<!--子组件-->
<template>
<div>
<h3>我是子组件</h3>
<span>{{parentMessage}}</span>
</div>
</template>
<script>
export default{
props: {
msg: {
type: String,
default: ''
},
isLike: {
type: Boolean,
default: false
},
index: {
type: Number,
default: 0
},
// 其他入参
type: {
type: String,
default: ''
},
// 回调
func: Function
},
};
</script>
- 通过
ref
属性名称获取到子组件的实例
<!--父组件-->
<template>
<div v-for="(item, index) in dataList" :key="index">
<h2>父组件</h2>
<div @click="someFun(index)">调用子组件方法</div>
<my-cmp-like ref="myLike"></my-cmp-like>
</div>
</template>
<script>
import myCmpLike from '@/components/MyLike'
export default{
components: {
myCmpLike,
},
data() {
return {
dataList: []
}
},
methods(){
someFun(i) {
this.$refs.myLike[i].showMsg()
},
},
};
</script>
<!--子组件-->
<template>
<div>
<h3>我是子组件</h3>
<span>{{msg}}</span>
</div>
</template>
<script>
export default{
props: {...},
data() {
return {
msg: '子组件'
}
},
methods: {
showMsg() {
alert(this.msg)
},
}
};
</script>
子组件向父组件通信
- 通过
$emit
向父组件传递方法
<!--子组件-->
<template>
<div>
<h3>我是子组件一</h3>
</div>
</template>
<script>
export default{
data() {
return {
item: {
name: 'Tony'
},
};
},
mounted() {
this.$emit('childEvent', this.item);
},
};
</script>
<!--父组件-->
<template>
<div>
<h2>父组件</h2>
<Child-one @childEvent="parentMethod"></Child-one>
</div>
</template>
<script>
import ChildOne from './ChildOne';
export default{
components: {
ChildOne,
},
data() {
return {
parentMessage: '我是来自父组件的消息',
};
},
methods: {
parentMethod(item) {
console.log(item)
alert(this.parentMessage)
},
},
};
</script>
- 通过props回调参数调用父组件方法
<!--父组件-->
<template>
<div>
<h2>父组件</h2>
<Child-one :func="showMsg"></Child-one>
</div>
</template>
<script>
import ChildOne from './ChildOne';
export default{
components: {
ChildOne,
},
data() {
return {
parentMessage: '我是来自父组件的消息',
};
},
methods: {
showMsg(item) {
console.log(item)
alert(this.parentMessage)
},
},
};
</script>
<!--子组件-->
<template>
<div>
<h3>我是子组件</h3>
<span>{{parentMessage}}</span>
</div>
</template>
<script>
export default{
data() {
return {
msg: '子组件的信息'
}
},
props: {
// 回调
func: Function
},
mounted() {
this.func && this.func(this.msg)
},
};
</script>
- 通过
$parent
获取父组件中的数据(不推荐该方式,因为vue提倡单向数据流,只有父组件交给子组件的数据子组件才有使用的权限,不允许子组件私自获取父组件的数据进行使用。)
<!--子组件-->
this.$parent.dataList[this.index].praiseNameList = res.data.data.praiseNameList;
vue兄弟组件、页面之间通信
- 复杂情况用vuex
- 简单情况用事件总线
新建eventBus.js
// 事件总线
import Vue from 'Vue'
export default new Vue()
a页面
import eventBus from '@/utils/eventBus'
beforeDestroy() {
eventBus.$emit('eventPerson', { a: 111 })
}
b页面
import eventBus from '@/utils/eventBus'
created() {
// 处理事件
eventBus.$on('eventPerson', data => {
console.log('事件总线数据呀', data)
})
},
beforeDestroy() {
// 组件销毁前清除事件监听
eventBus.$off('eventPerson')
// eventBus.$off('eventPerson', this.handleEventPerson)
}