当前位置:首页 > JavaScript

js实现vue

2026-04-05 06:44:18JavaScript

使用原生 JavaScript 实现类似 Vue 的功能

原生 JavaScript 可以通过数据绑定、观察者模式和虚拟 DOM 等技术实现类似 Vue 的功能。以下是一个简化版的实现示例:

class MiniVue {
  constructor(options) {
    this.$options = options
    this.$data = options.data()
    this.$el = document.querySelector(options.el)

    this.proxyData()
    this.observe(this.$data)
    this.compile(this.$el)
  }

  proxyData() {
    for (let key in this.$data) {
      Object.defineProperty(this, key, {
        get() {
          return this.$data[key]
        },
        set(newVal) {
          this.$data[key] = newVal
        }
      })
    }
  }

  observe(data) {
    if (!data || typeof data !== 'object') return

    Object.keys(data).forEach(key => {
      let value = data[key]
      const dep = new Dep()

      Object.defineProperty(data, key, {
        get() {
          Dep.target && dep.addSub(Dep.target)
          return value
        },
        set(newVal) {
          if (newVal === value) return
          value = newVal
          dep.notify()
        }
      })

      this.observe(value)
    })
  }

  compile(el) {
    const nodes = el.childNodes

    nodes.forEach(node => {
      if (node.nodeType === 1) {
        this.compileElement(node)
      } else if (node.nodeType === 3) {
        this.compileText(node)
      }

      if (node.childNodes && node.childNodes.length) {
        this.compile(node)
      }
    })
  }

  compileElement(node) {
    const attrs = node.attributes

    Array.from(attrs).forEach(attr => {
      if (attr.name.startsWith('v-')) {
        const dir = attr.name.substring(2)
        const exp = attr.value

        if (dir === 'model') {
          this.handleModel(node, exp)
        }

        node.removeAttribute(attr.name)
      }
    })
  }

  compileText(node) {
    const reg = /\{\{(.+?)\}\}/
    const text = node.textContent

    if (reg.test(text)) {
      const exp = RegExp.$1.trim()
      new Watcher(this, exp, (val) => {
        node.textContent = text.replace(reg, val)
      })

      node.textContent = text.replace(reg, this[exp])
    }
  }

  handleModel(node, exp) {
    node.value = this[exp]

    new Watcher(this, exp, (val) => {
      node.value = val
    })

    node.addEventListener('input', (e) => {
      this[exp] = e.target.value
    })
  }
}

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

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

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

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

    Dep.target = this
    this.value = vm[exp]
    Dep.target = null
  }

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

使用示例

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

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

实现原理说明

  1. 数据代理:通过 proxyData 方法将 data 中的属性代理到 Vue 实例上,可以直接通过 this.xxx 访问 data 中的属性

  2. 数据劫持:使用 Object.defineProperty 对数据进行劫持,当数据变化时通知依赖更新

  3. 依赖收集:通过 Dep 类管理依赖,Watcher 类作为观察者,在数据变化时执行回调

  4. 模板编译:通过 compile 方法解析模板,处理指令和插值表达式

  5. 双向绑定v-model 指令实现了双向数据绑定,将输入框的值与数据进行关联

功能扩展方向

  1. 计算属性:可以添加 computed 选项,通过缓存计算结果优化性能

  2. 方法处理:添加 methods 选项,处理用户定义的方法

  3. 生命周期:实现 created、mounted 等生命周期钩子

  4. 组件系统:支持组件化开发,实现组件注册和嵌套

  5. 虚拟DOM:引入虚拟DOM提高渲染性能,实现更高效的DOM更新

    js实现vue

这个实现展示了 Vue 的核心原理,实际 Vue 源码更为复杂,包含更多优化和功能。

标签: jsvue
分享给朋友:

相关文章

vue实现排序

vue实现排序

Vue 实现排序的方法 在 Vue 中实现排序可以通过多种方式完成,以下是一些常见的方法: 使用计算属性排序数组 计算属性非常适合对数据进行排序,因为它会在依赖的数据变化时自动更新。以下是一个示例:…

vue实现骰子

vue实现骰子

Vue 实现骰子功能 创建 Vue 组件 在 Vue 项目中创建一个骰子组件,例如 Dice.vue。该组件包含骰子的外观和逻辑。 <template> <div class=…

vue 实现全屏

vue 实现全屏

Vue 实现全屏功能 在 Vue 中实现全屏功能可以通过浏览器提供的 Fullscreen API 完成。以下是一个完整的实现方案: 安装依赖(可选) 如果需要跨浏览器兼容性更好,可以安装 scre…

vue实现dag

vue实现dag

Vue实现DAG(有向无环图) 在Vue中实现DAG(Directed Acyclic Graph,有向无环图)通常涉及数据结构的建模、可视化渲染以及交互逻辑处理。以下是关键实现步骤和示例代码: 数…

vue 实现聊天

vue 实现聊天

使用 Vue 实现聊天功能 创建 Vue 项目并安装依赖 确保已安装 Vue CLI,通过以下命令创建新项目: vue create chat-app 进入项目目录后,安装必要的依赖(如 Socke…

vue实现数据

vue实现数据

Vue 实现数据绑定的方法 Vue.js 提供了多种方式实现数据绑定,包括双向绑定、单向绑定以及动态数据绑定。以下是几种常见的实现方式: 双向数据绑定(v-model) 双向数据绑定通常用于表单元素…