cycold / cycold.github.io

Please dot not star...
4 stars 1 forks source link

vue2.0 组件数据封装注意 #133

Closed cycold closed 6 years ago

cycold commented 7 years ago

1.传入组件的数据不可以修改 2.使用组件内部的data对象属性接收的外部传入的属性的数据, 当外部数据变化时,组件内部是不会更新的.

export default {
    props: {
       obj: {
          type: Object,
          default: () => {}
        } 
   },
   data() {
       _obj: this.obj,
      _name: this.obj.name
   }
}

// 以上如果当使用this._obj的local属性来更新view的话, 那么当传入外部的obj的数据变化时, 里面的this._obj是不会变化的. 同时this._name也不会变化.  如果需要响应外部的数据变化,组件也自动更新,
那么在view中直接使用this.obj即可. 

// 当要修改传入进来的数据时,比如直接这里赋值: this.obj = {}, 这是不允许的, 因为不可以直接修改传入的属性值, 避免防止子组件修改父组件的状态. 此时可以在内部使用一个本地变量来接收,就是上面的
this._obj = this.obj, 但是这有一个问题,就是上面提到的, 外部的数据变化时,this._obj并不会自动更新.
所以当外部数据变化时,组件view没有更新, 优先可以考虑这个问题.

发现一个强制组件重新渲染的方法:
比如某组件通过属性依赖此数据 this.treeData = [...]
当更新this.treeData = [...new data] 时, 没有重新更新,
可以使用:

1. 将此依赖设为空: this.treeData = []
2. 在this.$nextTick(() => {
    this.treeData = [new data...]
})

问题: 既然组件不能修改传入的数据, 那么该怎么做呢? 因为很多组件就是修改外部传入的数据的.
可以想象组件就是一个黑盒子, 他有一个数据输入口, 接收外部传入的数据, 经过组件内部处理后,自然就需要将此组件修改过的数据传出去, 这里就只能使用事件了, 
通过组件发射事件给父组件接收, 同时将修改过的数据透过事件传出去, 给父组件. 由父组件再更新数据, 即更新之前传入给子组件的属性,从而子组件自身得到更新. 
所以一般在子组件中直接使用属性作为view渲染数据, 使用本地变量保存,传入的数据的初始值(this._obj). 然后在组件内部修改this._obj, 修改完后,通过事件传给父组件, 
父组件拿到数据后,再更新其传入给子组件的数据, 从而使子组件本身得到更新. 这么做主要是为了父子组件互相解耦.
不是强依赖. 子组件不能修改父组件的数据, 只能有父组件自已更新.