(三)vue父子组件通信(二)

父子组件通信注意事项:

一、单向传递问题:子组件一般不修改props中的数据

 1、先看报错:

如果直接在子组件中修改props中的属性值,f12会有报错:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "result" (found in component )

2、改进:即子组件中最好不要修改props中的属性的值(如val),如果需要修改,可以单独在data中定义一个本地属性copyVal,在子组件初始化时候把val赋值给copyVal,之后只操作copyVal。

例1:现有项目列表,可新增、修改项目,新增、修改都是弹框,弹框页中有一项用了子组件
(三)vue父子组件通信(二)_第1张图片


                
              
 
 
 
changeServiceContext(serviceContext) {
      this.project.serviceContext = serviceContext;
    },

子:这里用context作为中间媒介传值,(不过我也奇怪为什么这里直接操作fileList,f12没有看到报错。。。)


 

 

二、子组件数据更新问题:子组件初始化后,生命周期随父组件的销毁而销毁。

1、父组件调用子组件传值时,父组件中数据改变会及时传给子组件,但是子组件的页面如果已经渲染好了,可能不会二次渲染,这时需要在子组件中加上watch监控该值的变化;如果子组件加了watch还是不触发二次渲染,可以使用强制刷新的方法,强制刷新一般有两种方法,1是在父组件中销毁子组件并重新初始化;2是在子组件中销毁调用方法并重新触发。

2、父组件强制刷新子组件:如在一个父组件中多次调用某一个子组件,可能出现子组件值不更新的问题,如分页列表中点击编辑均调用同一个子组件。这点注意和父组件循环调用子组件区分开,父组件循环调用,是初始化了多个子组件,并非一个。

如上例,如果在子组件中直接操作props中的serviceContext,除了f12报错,功能是正常的。改进后用context做中间值,发现打开第一个项目的编辑框编辑这一项后,再打开其他项目的编辑框,context的内容都是一样的了,没有清除。在created中打console日志发现这个子组件只初始化一次,后面没有销毁,所以值没有清除()。强制刷新子组件的方法如下(以下内容都是写在父组件中的.):


 
data(){
  return {
    sonRefresh: true
  }
}
 
// 下面这段内容写在父组件需要更新子组件的地方
this.sonRefresh= false;
this.$nextTick(() => {
    this.sonRefresh= true;
});

另引申问题:还是上面的例子,父组件接收子组件的值后更新project的serviceContext属性值,但是watch里面监听不到这个属性值的变化:

  'channelProject.serviceContext': {
      handler(newObj, oldObj) {
        alert(newObj);
      },
      immediate: true,
      deep: true
    }

例2:如现有父子组件,父组件是查询条件,子组件是根据查询条件查询的数据。

父:


子:


由于这个页面子组件是和父组件一块初始化的,所以页面初始化时:

后来父组件改变时,由于子组件的initMsg方法不会再调用了:

如果想时间改变时再调用initMsg,在父组件中控制子组件的初始化是可以实现的:修改parent.vue如下


这时候的页面初始化:

父组件改变:

3、子组件自己刷新:在main.js中引入bus

import VueBus from 'vue-bus';
Vue.use(VueBus);

父组件通过this.$bus.$emit调用子组件的方法,子组件在this.$bus.$on之前加上$off销毁,以防止父组件需要重新调用。

如例2做以下修改:

父:


子:


页面初始化:

父组件改变:

  

例3:再如父组件是tab标签,

父:


child-one:


child-two:


(三)vue父子组件通信(二)_第2张图片

(三)vue父子组件通信(二)_第3张图片

(三)vue父子组件通信(二)_第4张图片

注:这里父组件去掉了时间组件的change方法改为加搜索按钮,因为发现这种情况下在change方法中调用子组件initMsg方法,month有延迟。

你可能感兴趣的:(VUE,js)