当前位置:首页 > 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 的局限性:

vue双向绑定简单实现

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实现双向

vue实现双向

Vue 实现双向绑定的方法 Vue 主要通过 v-model 指令实现双向绑定,适用于表单元素或自定义组件。以下是几种常见实现方式: 表单元素的双向绑定 在表单元素(如 input、textarea…

vue双向绑定实现

vue双向绑定实现

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

vue 实现双向绑定

vue 实现双向绑定

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

vue自己实现双向绑定

vue自己实现双向绑定

实现 Vue 双向绑定的核心原理 双向绑定的核心是通过数据劫持结合发布-订阅模式实现的。主要涉及 Object.defineProperty 或 Proxy 来监听数据变化,并通过观察者模式通知视图更…

实现Vue双向数据绑定

实现Vue双向数据绑定

Vue 双向数据绑定的实现原理 Vue 的双向数据绑定是通过 v-model 指令实现的,其核心基于 数据劫持 和 发布-订阅模式。具体实现分为以下几个部分: 数据劫持(Object.defineP…

vue props实现双向绑定

vue props实现双向绑定

在 Vue 中,props 默认是单向数据流(父组件 → 子组件),但可以通过以下方法实现类似双向绑定的效果: 使用 v-model 语法糖 父组件通过 v-model 传递数据,子组件通过 mod…