评论列表数据父子组件之间的共享:
父子通信的props
如果是一个 数组,我们只要不重新赋值这个props
里面的数组,就都不算修改props
,而可以实现父子之间共享数据,实时变化。(其本质是父子用了一个引用数据类型的数据)
实现:子组件comment-list
将 data
里面的变量list
修改成 props
里面的属性list
用于去接收外面的空数组commentList
data () {
return {
// 其他变量...
// list: [], // <===注释掉
}
}
props: {
// 其他属性...
// 定义自定义属性list,去接收外面的commentList 变量
list: {
type: Array,
default: () => [] //复杂数据类型,要用函数的方式
}
}
父组件:
data(){
return{
// 其他变量...
commentList: [] // 评论列表
}
}
<!-- 文章评论列表 -->
<comment-list
:source="article.art_id"
:list="commentList"
@onload-success="totalCommentCount = $event.total_count"
/>
methods: {
onSuccessPost(comment) {
console.log(comment);
this.isReplyShow = false;
//将发布的内容展示在页面顶部
this.commentList.unshift(comment.new_obj); // <=== 精华之句!!!
},
},
父组件的空数组不是为了传递给子组件,是让子组件把数据列表共享给父组件,因为父子通信关联的是引用数据类型,任何人一方改变了,另外一方都会变化。
核心:组件之间如果共享的是一个引用数据类型,任何一个组件修改(不赋值),其他都会变化。
列表数据重复的问题:
原因: van-list
组件有个特点,就是只有在可视范围内才会自动调用load
事件,所以我们之前文章内容过长,就不会触发请求文章评论列表,故而 我们手动在created
里面调用了onLoad
方法,但是现在我们这里的回复列表一开始就在可是范围内,故而会触发2次请求,1次是可视范围内自动触发,1次是我们主动调用触发。所以我们要关闭 自动检测可视范围自动调用。
实现:
- 给
van-list
组件设置immediate-check
属性,关闭可视范围自动调用检测
<!--
只有 List 在可视范围内才会检查滚动位置触发 onLoad
-->
<van-list
v-model="loading"
:finished="finished"
finished-text="已显示全部评论"
:error="error"
error-text="加载失败,请点击重试"
:immediate-check="false"
@load="onLoad"
>
created () {
// 当手动初始 onLoad 的话,它不会自动开始初始的 loading
// 所以我们要手动的开启初始 loading
this.loading = true
this.onLoad()
}
回复列表内容不更新的问题:
弹层组件(van-popup):
- 如果初始的条件是 false,则弹层的内容不会渲染
- 程序运行期间,当条件变为 true 的时候,弹层才渲染了内容
- 之后切换弹层的展示,弹层只是通过 CSS 控制隐藏和显示
原因: 弹层渲染出来以后就只是简单的切换显示和隐藏,里面的内容也不再重新渲染了,所以会导致我们的评论的回复列表不会动态更新了。解决办法就是在每次弹层显示的时候重新渲染组件。
<!-- 评论回复 -->
<!--
弹出层是懒渲染的:只有在第一次展示的时候才会渲染里面的内容,之后它的关闭和显示都是在切换内容的显示和隐藏
-->
<van-popup v-model="isReplyShow"position="bottom" style="height: 100%;">
<!--
v-if 条件渲染
true:渲染元素节点
false:不渲染
-->
<comment-reply
v-if="isReplyShow"
:comment="currentComment"
@close="isReplyShow = false"
/>
</van-popup>
<!-- /评论回复 -->
vue依赖注入:官网
可以在组件之间传递数据:
provide: function () {
return {
articleId: this.articleId,
};
},
inject: {
articleId:{
type: [String, Number],
default: null,
}
},