xwjie / VueStudyNote

vue学习笔记

Home Page:https://xwjie.github.io/VueStudyNote/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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()
    }
  })
}