当前位置:首页 > VUE

vue双向绑定简单实现

2026-02-25 01:08:11VUE

实现 Vue 双向绑定的核心原理

Vue 的双向绑定主要通过数据劫持和发布-订阅模式实现。以下是简化版的实现思路:

数据劫持(Object.defineProperty)

通过 Object.defineProperty 拦截对象的属性读写操作:

function observe(data) {
  if (!data || typeof data !== 'object') return
  Object.keys(data).forEach(key => {
    defineReactive(data, key, data[key])
  })
}

function defineReactive(obj, key, val) {
  observe(val) // 递归处理嵌套对象
  const dep = new Dep() // 每个属性对应一个 Dep 实例

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      Dep.target && dep.addSub(Dep.target) // 收集依赖
      return val
    },
    set(newVal) {
      if (newVal === val) return
      val = newVal
      observe(newVal) // 新值是对象时继续劫持
      dep.notify() // 通知更新
    }
  })
}

依赖收集(Dep 类)

实现一个简单的依赖收集器:

class Dep {
  constructor() {
    this.subs = []
  }
  addSub(sub) {
    this.subs.push(sub)
  }
  notify() {
    this.subs.forEach(sub => sub.update())
  }
}
Dep.target = null // 全局唯一的 Watcher 标记

观察者(Watcher 类)

class Watcher {
  constructor(vm, exp, cb) {
    this.vm = vm
    this.exp = exp
    this.cb = cb
    this.value = this.get()
  }

  get() {
    Dep.target = this
    const value = this.vm[this.exp] // 触发 getter
    Dep.target = null
    return value
  }

  update() {
    const newValue = this.vm[this.exp]
    if (newValue !== this.value) {
      this.value = newValue
      this.cb(newValue)
    }
  }
}

编译器(Compile)

简单模板编译实现:

function compile(node, vm) {
  if (node.nodeType === 1) { // 元素节点
    Array.from(node.attributes).forEach(attr => {
      if (attr.name.startsWith('v-')) {
        const exp = attr.value
        if (attr.name === 'v-model') {
          node.value = vm[exp]
          node.addEventListener('input', e => {
            vm[exp] = e.target.value
          })
        }
      }
    })
  }
}

整合实现

class Vue {
  constructor(options) {
    this.$options = options
    this._data = options.data
    observe(this._data)
    this._proxyData()
    new Compile(options.el, this)
  }

  _proxyData() {
    Object.keys(this._data).forEach(key => {
      Object.defineProperty(this, key, {
        get() {
          return this._data[key]
        },
        set(newVal) {
          this._data[key] = newVal
        }
      })
    })
  }
}

使用示例

<div id="app">
  <input v-model="message">
  <p>{{ message }}</p>
</div>

<script>
  const vm = new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue'
    }
  })
</script>

现代 Vue 3 的改进

Vue 3 改用 Proxy 实现响应式,解决了 Object.defineProperty 的局限性:

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key)
      return Reflect.get(target, key)
    },
    set(target, key, value) {
      Reflect.set(target, key, value)
      trigger(target, key)
    }
  })
}

这个简化实现展示了 Vue 双向绑定的核心机制,实际 Vue 源码还包含虚拟 DOM、组件系统等更多复杂功能。

vue双向绑定简单实现

标签: 绑定双向
分享给朋友:

相关文章

react如何绑定事件

react如何绑定事件

React 事件绑定方法 在 React 中绑定事件有多种方式,以下是常见的几种方法: 使用 onClick 或其他事件属性直接绑定 <button onClick={() =>…

vue 实现双向绑定

vue 实现双向绑定

Vue 双向绑定的实现原理 Vue 的双向绑定主要通过 v-model 指令实现,底层基于数据劫持和发布-订阅模式。以下是核心实现机制: 数据劫持(响应式系统) Vue 使用 Object.def…

vue实现数组双向绑定

vue实现数组双向绑定

实现数组双向绑定的方法 在Vue中,实现数组的双向绑定通常需要结合v-model指令或自定义事件处理。以下是几种常见的方法: 使用v-model绑定数组 Vue的v-model指令默认支持表单元素…

怎么实现vue双向绑定

怎么实现vue双向绑定

Vue 双向绑定的实现原理 Vue 的双向绑定主要通过 v-model 指令实现,其核心是结合数据劫持(Object.defineProperty 或 Proxy)和发布-订阅模式。 使用 v-…

vue中实现双向数据

vue中实现双向数据

Vue 中实现双向数据绑定的方法 使用 v-model 指令 v-model 是 Vue 提供的语法糖,用于在表单元素上实现双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素的值。 <…

vue双向数据怎么实现

vue双向数据怎么实现

Vue 双向数据绑定的实现 Vue 的双向数据绑定主要通过 v-model 指令实现,结合数据劫持(Object.defineProperty 或 Proxy)和发布-订阅模式完成数据与视图的同步更新…