当前位置:首页 > VUE

vue怎样实现mvvm

2026-03-28 05:27:04VUE

Vue 的 MVVM 实现原理

Vue 通过数据绑定和响应式系统实现 MVVM(Model-View-ViewModel)模式,核心是数据驱动视图更新。

数据劫持(Observer)

Vue 使用 Object.definePropertyProxy 劫持数据对象的属性,在属性被访问或修改时触发依赖收集和更新。

vue怎样实现mvvm

// 简化版数据劫持
function defineReactive(obj, key) {
  let value = obj[key]
  Object.defineProperty(obj, key, {
    get() {
      console.log('收集依赖')
      return value
    },
    set(newVal) {
      if (newVal !== value) {
        console.log('触发更新')
        value = newVal
      }
    }
  })
}

依赖收集(Dep)

每个被劫持的属性都有一个 Dep 实例,用于管理所有依赖该属性的 Watcher

class Dep {
  constructor() {
    this.subs = []
  }
  addSub(sub) {
    this.subs.push(sub)
  }
  notify() {
    this.subs.forEach(sub => sub.update())
  }
}

观察者(Watcher)

Watcher 是视图和数据的桥梁,在数据变化时触发视图更新。

vue怎样实现mvvm

class Watcher {
  constructor(vm, exp, cb) {
    this.vm = vm
    this.exp = exp
    this.cb = cb
    this.value = this.get()
  }
  get() {
    Dep.target = this
    let value = this.vm[this.exp]
    Dep.target = null
    return value
  }
  update() {
    const newValue = this.vm[this.exp]
    if (newValue !== this.value) {
      this.value = newValue
      this.cb.call(this.vm, newValue)
    }
  }
}

模板编译(Compiler)

Vue 将模板编译为渲染函数,解析指令和插值表达式,创建对应的 Watcher

// 简化的文本节点编译
function compileText(node, vm) {
  const reg = /\{\{(.*)\}\}/
  if (reg.test(node.textContent)) {
    const exp = RegExp.$1.trim()
    new Watcher(vm, exp, function(value) {
      node.textContent = value
    })
    node.textContent = vm[exp]
  }
}

响应式流程

  1. 初始化时劫持数据属性
  2. 编译模板时遇到数据绑定创建 Watcher
  3. Watcher 读取数据触发 getterDep 收集依赖
  4. 数据变化时触发 setterDep 通知所有 Watcher 更新
  5. Watcher 执行回调更新视图

实现示例

class Vue {
  constructor(options) {
    this.$options = options
    this._data = options.data
    this.observe(this._data)
    this.compile()
  }
  observe(data) {
    Object.keys(data).forEach(key => {
      defineReactive(data, key)
    })
  }
  compile() {
    const el = document.querySelector(this.$options.el)
    this.compileNode(el)
  }
  compileNode(node) {
    if (node.nodeType === 1) {
      // 元素节点处理指令
    } else if (node.nodeType === 3) {
      // 文本节点处理插值
      compileText(node, this)
    }
  }
}

现代 Vue 的优化

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) {
      const result = Reflect.set(target, key, value)
      trigger(target, key)
      return result
    }
  })
}

标签: vuemvvm
分享给朋友:

相关文章

vue 实现全选

vue 实现全选

Vue 实现全选功能 在 Vue 中实现全选功能通常需要结合复选框的状态管理,以下是几种常见的实现方式: 使用 v-model 绑定数组 通过 v-model 绑定一个数组来管理选中的项,全选时将该…

vue实现菜单栏锚点

vue实现菜单栏锚点

实现锚点菜单的基本思路 在Vue中实现菜单栏锚点功能,主要涉及两个方面:创建可跳转的锚点位置,以及菜单项的点击滚动控制。通过监听滚动事件可以高亮当前可见区域的对应菜单项。 创建页面锚点位置 在需要跳…

vue实现granfana

vue实现granfana

Vue 实现类似 Grafana 的仪表盘 要在 Vue 中实现类似 Grafana 的仪表盘功能,需要结合数据可视化库、状态管理和 UI 组件。以下是关键步骤和推荐工具: 数据可视化库 使用 E…

vue实现返回

vue实现返回

返回按钮功能实现 在Vue中实现返回功能通常有两种方式:使用浏览器历史记录的history.back()或结合Vue Router进行编程式导航。以下是具体实现方法: 使用浏览器API metho…

vue实现fullpage

vue实现fullpage

Vue 实现 FullPage 效果 在 Vue 中实现全屏滚动(FullPage)效果可以通过多种方式完成,以下是几种常见的方法: 使用现有库 vue-fullpage.js 安装 vue-ful…

vue实现slidetoggle

vue实现slidetoggle

Vue 实现 SlideToggle 效果 SlideToggle 是一种常见的交互效果,元素以滑动方式展开或收起。以下是几种实现方法: 使用 CSS Transition 和 v-show…