zoukankan      html  css  js  c++  java
  • 小型mvvm实现原理

    关键词:

    defineReactive:数据劫持,用来监听获取数据set和get,其中,get将实现发布订阅直接的绑定,set则发布事件,实现订阅者更新

    Watcher:观察者,绑定Dept,在dept调用notify时候,触发Watcher回调

    Dept:依赖关系,在数据更新的时候(set),调用自身的观察回调函数

    具体代码如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>MVVM</title>
    </head>
    <body>
      <div></div>
      
    </body>
    <script>
      // 通过 Dep 解耦
    class Dep {
      constructor() {
        this.subs = []
      }
      addSub(sub) {
        // sub 是 Watcher 实例
        this.subs.push(sub)
      }
      notify() {
        this.subs.forEach(sub => {
          sub.update()
        })
      }
    }
    // 全局属性,通过该属性配置 Watcher
    Dep.target = null
    
    function update(value) {
      document.querySelector('div').innerText = value
    }
    
    class Watcher {
      constructor(obj, key, cb) {
        // 将 Dep.target 指向自己
        // 然后触发属性的 getter 添加监听
        // 最后将 Dep.target 置空
        Dep.target = this
        this.cb = cb
        this.obj = obj
        this.key = key
        this.value = obj[key] // 触发obj的get方法,与dep联系起来
        Dep.target = null
      }
      update() {
        // 获得新值
        this.value = this.obj[this.key]
        // 调用 update 方法更新 Dom
        this.cb(this.value)
      }
    }
    function observe(obj) {
      // 判断类型
      if (!obj || typeof obj !== 'object') {
        return
      }
      Object.keys(obj).forEach(key => {
        defineReactive(obj, key, obj[key])
      })
    }
    
    function defineReactive(obj, key, val) {
      // 递归子属性
      observe(val)
      let dp = new Dep()
      Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter() {
          console.log('get value')
          // 将 Watcher 添加到订阅
          if (Dep.target) {
            dp.addSub(Dep.target)
          }
          return val
        },
        set: function reactiveSetter(newVal) {
          console.log('change value')
          val = newVal
          // 执行 watcher 的 update 方法
          dp.notify()
        }
      })
    }
    var data = { name: 'yck' }
    observe(data)
    // // 模拟解析到 `{{name}}` 触发的操作
    new Watcher(data, 'name', update)
    // // update Dom innerText
    // data.name = 'yyy'
    
    
    
    </script>
    </html>

    具体逻辑分析如下

  • 相关阅读:
    OCX控件的注册卸载,以及判断是否注册
    SimpleJdbcTemplate批量更新(BeanPropertySqlParameterSource)
    hibernateTemplate封装jdbc的一个简单思路
    Dao层查询
    ==与equals方法的区别(Java基础)
    中文乱码解决办法
    spring核心配置文件_ActiveMQ消息队列配置
    spring核心配置文件_Elasticsearch搜索配置
    spring核心配置文件_数据库连接信息
    spring核心配置文件_数据库连接信息_数据库信息
  • 原文地址:https://www.cnblogs.com/peace1/p/15046423.html
Copyright © 2011-2022 走看看