当前位置:首页 > VUE

实现自己的vue

2026-02-19 14:05:34VUE

实现一个简易 Vue 框架

要实现一个类似 Vue 的响应式框架,需要理解其核心机制:数据劫持、依赖收集和派发更新。以下是关键实现步骤:

数据劫持(响应式系统)

使用 Object.definePropertyProxy 拦截数据访问和修改:

class Observer {
  constructor(data) {
    this.walk(data)
  }

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

  defineReactive(obj, key, val) {
    const dep = new Dep()
    this.walk(val) // 递归处理嵌套对象
    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
        dep.notify()
      }
    })
  }
}

依赖收集系统

实现订阅者管理:

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

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

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

Dep.target = null

观察者(Watcher)

连接响应式数据和视图更新:

class Watcher {
  constructor(vm, key, cb) {
    this.vm = vm
    this.key = key
    this.cb = cb
    Dep.target = this
    this.oldValue = vm[key] // 触发getter
    Dep.target = null
  }

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

编译器

解析模板并建立数据绑定:

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

  compile(node) {
    Array.from(node.childNodes).forEach(node => {
      if (this.isElement(node)) {
        this.compileElement(node)
      } else if (this.isText(node)) {
        this.compileText(node)
      }
      if (node.childNodes && node.childNodes.length) {
        this.compile(node)
      }
    })
  }

  compileElement(node) {
    Array.from(node.attributes).forEach(attr => {
      if (this.isDirective(attr.name)) {
        const dir = attr.name.substring(2)
        this[dir] && this[dir](node, attr.value)
      }
    })
  }

  compileText(node) {
    const reg = /\{\{(.*?)\}\}/
    if (reg.test(node.textContent)) {
      const key = RegExp.$1.trim()
      this.update(node, key, 'text')
    }
  }

  text(node, key) {
    this.update(node, key, 'text')
  }

  model(node, key) {
    this.update(node, key, 'model')
    node.addEventListener('input', e => {
      this.vm[key] = e.target.value
    })
  }

  update(node, key, type) {
    const updaterFn = this[type + 'Updater']
    updaterFn && updaterFn(node, this.vm[key])
    new Watcher(this.vm, key, value => {
      updaterFn(node, value)
    })
  }

  textUpdater(node, value) {
    node.textContent = value
  }

  modelUpdater(node, value) {
    node.value = value
  }

  isDirective(attr) {
    return attr.startsWith('v-')
  }

  isElement(node) {
    return node.nodeType === 1
  }

  isText(node) {
    return node.nodeType === 3
  }
}

整合框架

创建主类连接各模块:

实现自己的vue

class MyVue {
  constructor(options) {
    this.$options = options
    this.$data = options.data
    new Observer(this.$data)
    this.proxyData(this.$data)
    new Compiler(options.el, this)
  }

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

使用示例

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

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

实现要点说明

  1. 响应式系统通过拦截对象属性的访问和修改来实现
  2. 每个响应式属性都有对应的 Dep 实例管理依赖
  3. Watcher 在初始化时会触发属性的 getter 进行依赖收集
  4. 数据变化时通过 setter 触发 Dep 的通知机制
  5. 编译器解析模板中的指令和插值表达式
  6. 通过代理将 data 的属性映射到 Vue 实例上

这个实现包含了 Vue 最核心的响应式原理,实际 Vue 还包含虚拟 DOM、组件系统等更多复杂功能,但以上代码已经展示了其最基础的工作机制。

标签: 自己的vue
分享给朋友:

相关文章

vue实现监听

vue实现监听

监听数据变化 在Vue中,可以通过watch选项或$watch方法监听数据的变化。watch适用于组件选项内声明式监听,$watch适用于动态监听。 // 选项式API export default…

vue实现menu

vue实现menu

Vue 实现 Menu 的方法 使用 Element UI 的 Menu 组件 Element UI 提供了现成的 Menu 组件,适合快速实现导航菜单。安装 Element UI 后,可以直接使用…

vue for实现

vue for实现

Vue 中的 v-for 指令 v-for 是 Vue.js 中用于渲染列表数据的核心指令,通过遍历数组或对象生成动态内容。 基本语法(数组) <ul> <li v-for="…

vue实现反馈

vue实现反馈

Vue 实现反馈功能的方法 在 Vue 中实现反馈功能可以通过多种方式,包括弹窗提示、Toast 消息、表单提交等。以下是几种常见的实现方法。 弹窗反馈 使用 Vue 的组件化特性创建一个弹窗组件,…

vue 实现vshow

vue 实现vshow

Vue 实现 v-show 在 Vue 中,v-show 是一个常用的指令,用于根据条件控制元素的显示或隐藏。与 v-if 不同,v-show 不会移除 DOM 元素,而是通过 CSS 的 displ…

vue实现录音

vue实现录音

Vue 实现录音功能 在 Vue 中实现录音功能可以通过浏览器提供的 MediaRecorder API 完成。以下是具体实现方法: 引入依赖 确保项目支持现代浏览器 API,无需额外安装库…