当前位置:首页 > VUE

vue双向绑定简单实现

2026-02-25 01:08:11VUE

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

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

数据劫持(Object.defineProperty)

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

vue双向绑定简单实现

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 类)

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

vue双向绑定简单实现

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 数据绑定实现

vue 数据绑定实现

Vue 数据绑定的实现方式 Vue 的数据绑定主要通过响应式系统和模板语法实现,以下是核心方法: 双向数据绑定(v-model) 通过 v-model 指令实现表单元素与数据的双向绑定,自动同步数据…

vue 双向绑定实现

vue 双向绑定实现

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

vue实现双休绑定

vue实现双休绑定

Vue 实现双向绑定 Vue.js 通过 v-model 指令实现双向绑定,主要用于表单输入元素(如 <input>、<textarea>、<select>)与组件…

vue双向绑定如何实现

vue双向绑定如何实现

Vue 双向绑定的实现原理 Vue 的双向绑定是通过数据劫持结合发布者-订阅者模式实现的,核心是 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)。 Vu…

vue实现双向绑定代码

vue实现双向绑定代码

Vue 双向绑定实现代码 Vue 的双向绑定主要通过 v-model 指令实现,它结合了 v-bind(属性绑定)和 v-on(事件监听)的功能。以下是几种常见场景的实现代码: 基础输入框绑定 &l…

react如何实现双向

react如何实现双向

React 实现双向绑定的方法 在 React 中实现双向绑定通常需要结合状态管理和事件处理机制。以下是几种常见的方法: 使用受控组件 受控组件是 React 推荐的方式,通过将组件的状态与表单元素…