VueStudyNote icon indicating copy to clipboard operation
VueStudyNote copied to clipboard

17 实现子组件data方法

Open xwjie opened this issue 6 years ago • 0 comments

原因

如果子组件的data不是方法的话,每个组件返回相同的一份数据,那么多个子组件的数据就会冲突。所以子组件的data方法必须是一个function,每个子组件返回独立的数据。

测试代码

<h1>子组件data方法测试</h1>
<div id="counter-event-example">
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>
<script>

Xiao.component('button-counter', {
  template: '<button @click="incrementCounter">{{ counter }}</button>',
  data:   function () {
    return {
      counter: 0
    }
  },
  methods: {
    incrementCounter: function () {
      console.log('incrementCounter')
      this.counter += 1
    }
  },
})

new Xiao({
  el: '#counter-event-example',
})
</script>

实现

判断data是不是方法,如果是方法,把调用后的值赋值为data即可。调用的时候会绑定this为当前实例。

/**
 * 监听data
 * @param {*} vm
 */
function initData(vm: Xiao) {
  let data = vm.$options.data

  if (!data) {
    //observe(vm._data = {}, true /* asRootData */)
  }

  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}

  // proxy data on instance
  const keys = Object.keys(data)
  const props = vm.$options.props
  const methods = vm.$options.methods

  let i = keys.length

  while (i--) {
    const key = keys[i]

    if (!isReserved(key)) {
      // 这里才是真正的代理数据
      proxy(vm, `_data`, key)
    }
  }

  // observe data
  observe(data, true /* asRootData */)
}

export function getData(data: Function, vm: Xiao): any {
  try {
    return data.call(vm, vm)
  } catch (e) {
    warn("get data error:", e);
    return {}
  }
}

xwjie avatar Jan 21 '18 14:01 xwjie