美文网首页
一个简易的双向绑定demo

一个简易的双向绑定demo

作者: 苍老师的眼泪 | 来源:发表于2022-04-04 23:47 被阅读0次
<!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">
  <title>Document</title>
</head>

<body>

  <div id="app">
    <div>
      一个叫<strong>{{ name }}</strong>的人,他今年
      <strong>{{ age }}</strong>岁,
      家住在<strong>{{ home.location }}</strong>
      他有一个朋友也是 <strong> {{ age }}</strong> 岁
    </div>
  </div>

  <script>
    let data = {
      name: "Edison",
      age: 26,
      home: {
        location: 'Guangdong'
      }
    }
    let el = "#app"

    let vm = {
    
    }


    function reactive(target, obj) {

      for (let key of Object.keys(obj)) {

        if (typeof obj[key] == 'object') {
          vm[key] = {}
          reactive(vm[key], obj[key])
          return
        }

        // 记录依赖的watcher
        let dep = []

        Object.defineProperty(target, key, {
          get: function () {

            if (global_watcher) {
              dep.push(global_watcher)
            }

            return obj[key]
          },
          set: function (val) {

            // console.log('哈哈, ' + key + '的值为:' + val)
            
            obj[key] = val

            dep.forEach(element => {

              element.update(val)
            });
          }
        })
      }

    }

    let global_watcher = null
  
    reactive(vm, data)

    class Watcher {
      constructor(node) {
        this.node = node
      }
      update(new_value) {
        
        this.node.textContent = new_value
      }
    }

    compile(el)

    function compile(root) {
      let root_node = document.querySelector(root)

      compile_node(root_node)

    }

    function compile_node(node) {
      if (node.nodeType == 1) {
        // 元素节点

        node.childNodes.forEach(child => {
          compile_node(child)
        })

      } else if (node.nodeType == 3) {
        // 文本节点

        let reg_exp = /\{\{(.*)\}\}/

        if (reg_exp.test(node.textContent)) {
          let exp = RegExp.$1.trim()

          // 怎么才能放到 exp 属性对应的dep里面呢?
          // 通过触发getter和setter来访问相应的dep
          
          global_watcher = new Watcher(node.parentNode)
          // 触发一下相应的getter, 以便在get中将watcher加入刀相应的dep
          // 顺便改一下相应html节点的值
          node.textContent = get_value(vm, exp)

          global_watcher = null

        }

      } else 
        throw '暂时考虑别的类型的节点'
      

    }

  
    function get_value(vm, exp) {

      let value = vm

      exp.split('.').forEach(e => {
        value = value[e]
      })

      return value
    }

    

  </script>

</body>

</html>

相关文章

  • 一个简易的双向绑定demo

  • 指令2

    实现双向绑定v-model 注:双向绑定只能用在表单控件上 点击事件绑定(单向) 简易计算器 通过class绑定赋...

  • RxSwift之双向绑定实战

    什么是双向绑定?双向绑定是View与Model之间的一种相互响应的关系。 下面?以一个Demo实战来体验一下双向绑...

  • 双向数据绑定demo

    1.遍历dom树解析指令,寻找事件对应的属性名。2.将属性名分类存储在订阅者信息中,并根据不同的dom生成对应的w...

  • 音乐播放

    rxswiftPlayer 这是一个音乐播放器,基于swift与rxswift双向绑定架构编写,git地址 简易播...

  • [JS][Vue]学习记录之双向绑定

    Demo地址双向绑定有两种方式 ref v-model ref 这里对一个input标签进行绑定: v-model...

  • 玩转Vue_指令2

    数据的双向绑定:v-model 简易计算器练习 通过绑定class赋予样式 使用内联样式 v-for v-for中...

  • vue笔记-v-model指令学习(四)

    v-model实现了数据和表单标签的双向绑定。 示例代码: 通过v-model的双向数据实现简易计算器:

  • 双向绑定之最简单的demo

    从上一篇中,我们理解了数据监听的原理,接下来我们来实现一个最简单的demo本demo中,通过定义数据对象的get ...

  • Vue之表单双向数据绑定和组件

    三、表单双向数据绑定和组件 目录:双向数据绑定、组件 1.双向数据绑定 1)什么是双向数据绑定Vue.js是一个M...

网友评论

      本文标题:一个简易的双向绑定demo

      本文链接:https://www.haomeiwen.com/subject/yuihsrtx.html