05 监听子属性和新加的属性
xwjie opened this issue · comments
实现监听子属性以及新加的属性
测试页面
测试文件 Xiao\example\render-data-child.html
<!DOCTYPE html>
<html>
<head>
<title>Xiao框架之helloworld</title>
<script src="../dist/xiao.js"></script>
<style>
</style>
</head>
<body>
<div id="demo1">
</div>
<script>
var app = new Xiao({
template: '<h1>变量1:{{message}}。<br/>变量2:{{submsg.msg}}。</h1>',
data: {
message: '当你看到这句话的时候,表示框架工作正常',
submsg: {
msg:'终于好了',
},
another: '这个变量没有在模板里面'
}
});
app.$mount("#demo1");
var count = 1;
setInterval(function(){
app.message = `第${count}次修改了数据`;
app.submsg.msg = `第${count}次修改了data里面的子节点数据`;
count++;
}, 2000);
setTimeout(function(){
console.log('隔了3秒后修改了模板无关的变量数据');
app.another = "修改了她不应该重新渲染";
}, 3000);
</script>
</body>
</html>
实现过程
设置 get
方法的时候,递归
监听 value
。记住,此时需要把依赖关系登记起来。
// 监听子属性
let childOb = observe(val)
和 设置 set
方法的时候:
// 监听新设置进来的数据
childOb = observe(newVal)
最终代码
/**
* Define a reactive property on an Object.
*/
export function defineReactive(
obj: Object,
key: string,
val: any,
shallow?: boolean
) {
const property = Object.getOwnPropertyDescriptor(obj, key)
if (property && property.configurable === false) {
return
}
// xwjie 这里应该可以考虑优化,如果和模板没有关系,dep不需要创建
const dep = new Dep()
log(`[observer]定义观察者,属性:${key}`)
// cater for pre-defined getter/setters
const getter = property && property.get
const setter = property && property.set
// 监听子属性
let childOb = observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
// log('[observer]get方法被调用,属性:' + key)
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
// 子属性的依赖关系也要登记起来
if (childOb) {
childOb.dep.depend()
}
}
return value
},
set: function reactiveSetter(newVal) {
// log('[observer]set方法被调用,属性:' + key)
const value = getter ? getter.call(obj) : val
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
// 监听新设置进来的数据
childOb = observe(newVal) //!shallow &&
dep.notify()
}
})
}