IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 简单实现VUE2.0双向绑定 -> 正文阅读

[JavaScript知识库]简单实现VUE2.0双向绑定

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>简单实现vue双向绑定</title></title>
  </head>
  <script>
    class Vue {
      constructor(options) {

        // 1,保存数据
        this.$options = options
        this.$data = options.data
        this.$el = options.el

        // 2,将data添加到响应式数据中
        new Observer(this.$data)

        // 3,代理this.$data的数据
        Object.keys(this.$data).forEach(key => {
          this._proxy(key)
        })

        // 4,处理el
        new Compiler(this.$el, this)
      }

      _proxy(key) {
        Object.defineProperty(this, key, {
          configurable: true,
          enumerable: true,
          set(newValue) {
            this.$data[key] = newValue
          },
          get() {
            return this.$data[key]
          }
        })
      }
    }

    class Observer {
      constructor(data) {
        this.data = data

        Object.keys(data).forEach(key => {
          this.defineReactive(this.data, key, data[key])
        })
      }

      defineReactive(data, key, val) {
        const dep = new Dep()
        Object.defineProperty(data, key, {
          enumerable: true,
          configurable: true,
          get() {
            if(Dep.target) {
              dep.addSub(Dep.target)
            }
            return val
          },
          set(newValue) {
            if(newValue === val) {
              return
            }
            val = newValue
            dep.notify()
          }
        })
      }

    }

    class Dep {
      constructor() {
        this.subs = []
      }

      addSub(sub) {
        this.subs.push(sub)
      }

      notify() {
        this.subs.forEach(sub => {
          sub.update()
        })
      }
    }

    class Watcher {
      constructor(node, name, vm) {
        this.node = node
        this.name = name 
        this.vm = vm
        Dep.target = this
        this.update()
        Dep.target = null
      }

      update() {
        if(this.node.nodeName === 'INPUT') {
          this.node.value = this.vm[this.name]
        } else {
          this.node.nodeValue = this.vm[this.name]
        }
      }
    }

    const reg = /\{\{(.*)\}\}/

    class Compiler {
      constructor(el, vm) {
        this.el = document.querySelector(el)
        this.vm = vm

        this.frag = this._createFragment()
        this.el.appendChild(this.frag)
      }

      _createFragment() {
        const frag = document.createDocumentFragment()

        let child
        while( child = this.el.firstChild ) {
          this._compile(child)
          frag.appendChild(child)
        }
        return frag
      }

      _compile(node) {
        console.dir(node)
        if( node.nodeType === 1 ) {
          const attrs = node.attributes
          if(attrs.hasOwnProperty('v-model')) {
            const name = attrs['v-model'].nodeValue
            if(node.nodeName === 'INPUT') {
              node.addEventListener('input', e => {
                this.vm[name] = e.target.value
              })
              new Watcher(node, name, this.vm)
            }
          }
        }

        if( node.nodeType === 3 ) {
          if(reg.test(node.nodeValue)) {
            const name = RegExp.$1.trim()
            new Watcher(node, name, this.vm)
          }
        }
      }

    }
  </script>
  <body>
    <div id="app">
      <input v-model="name"></input> 
      {{name}}
    </div>
  </body>
  <script>
    let app = new Vue({
      el: "#app",
      data: {
        name: 'Adam'
      }
    })
  </script>
  
</html>

代码与思路整理自B站老师ilovecoding的教程(补充了一点对input的处理)最全最新Vue、Vuejs教程,从入门到精通_哔哩哔哩_bilibili?

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-24 15:11:47  更:2022-02-24 15:13:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:24:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码