VueStudyNote
VueStudyNote copied to clipboard
17 实现子组件data方法
原因
如果子组件的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 {}
}
}