浅谈vue设计核心 01-数据响应式

2021-09-28  本文已影响0人  江川哇

vue的设计核心是 mvvm
mvvm的核心三要素:数据响应式、 模板引擎、 渲染
1、数据响应式:监听数据变化并且在视图中更新,vue中利用Object.defineProperty()实现变更检测
Object.defineProperty()
Proxy

简单实现:

const obj = {}
function definePropery(obj,key,val) {
  Object.definePropery(obj,key,{
    get() {
      console.log('get',val)
    }
    set(newval) {
      if(newval!=val) {
        val = newval
      }
    }
  })
}
definePropery(obj,'foo','foo')
obj.foo
obj.foo='fooooooo'

结合视图

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="app"></div>
   <script>
      function defineReactive(obj,key,{
        get(val) {
          return val
        }
        set(newval)  {
          if(val!=newval) {
            val = newval
            update()
          }
        }
      })
      defineReactive(obj,'foo','')
      obj.foo = new Date().toLocaleTimeString()
      function update() {
        app.innetText = obj.foo
      }
      setInterval (()=>{
         obj.foo = new Date().toLocaleTimeString()
      },1000)
  </script>
  </body>
</html>

遍历要响应的对象

//对象响应化,遍历每个key,定义getter setter
function observe(obj) {
  if(typeof obj !='object' || obj==null) {
    return
  }
  Object.keys(obj).forEach(key=>{
    defineReactive(obj,key,obj[key])
  })
}
const obj = {foo:'foo',bar:'bar',baz:{a:1}}
obj.foo
obj.foo = 'fff'
obj.bar
obj.bar = 'barrrrrr'
obj.baz.a = 2 //嵌套对象no ok

解决嵌套对象 用递归

function defineReactive(obj,key,val) {
  observe(val)
  Object.defineProperty(obj,key,{
    //...
  })
}

解决赋值是对象的情况

obj.baz = {a:1}
obj.baz.a = 10 //no ok
set(newval) {
  if(newval!=val) {
    observe(newval) //新值是对象的情况
    notifyUpdate()
  }
}

解决添加/删除新属性无法检测 类似vue的$set

obj.dong = 'dong'
obj.dong //并没有get信息
function set(obj,key,val) {
  difineReactive(obj,key,val)
}
//测试
set(obj,'dong','dong')
obj.dong

完整代码

//对象响应式原理
//1 Object.defineProperty()
function defineReactive(obj, key, val) {
  //val 可能是对象,需要递归处理
  observe(val)
  Object.defineProperty(obj, key, {
    get() {
      console.log('get', val)
      return val
    },
    set(newval) {
      if (newval != val) {
        observe(newval)
        console.log('set', newval)
        val = newval
      }
    },
  })
}

//对象响应式处理
function observe(obj) {
  //判断obj类型必须是对象
  if (typeof obj != 'object' || obj == null) {
    return
  }
  Object.keys(obj).forEach((key) => defineReactive(obj, key, obj[key]))
}
//设置新的属性 类似$set
function set(obj, key, val) {
  defineReactive(obj, key, val)
}
const obj = { name: 'aa', age: 11, baz: { a: 1 } }
observe(obj)
// obj.name
// obj.name = 'fffff'
//1 对象嵌套 就用到了递归,在defineReactive 里面再调用一次 observe(val)
// obj.baz.a

//2 这种情况 在set里面再调用一次observe(val)
//obj.baz={a:10}

//3 设置新的obj属性 类似$set
set(obj, 'dong', 'dong')
obj.dong

2、模板引擎:提供描述视图的模板语法
插值:{{}}
指令: v-bind v-on v-for v-if v-model
3、渲染:如何将模板转换成html
模板=> vdom =>dom

上一篇 下一篇

猜你喜欢

热点阅读