当前位置:首页 > VUE

自己动手实现vue

2026-01-16 04:20:36VUE

实现简易 Vue 的核心功能

Vue 的核心功能包括数据响应式、模板编译和虚拟 DOM。以下是一个简化版的实现思路:

数据响应式(Reactivity) 通过 Object.definePropertyProxy 监听数据变化。使用 Proxy 的示例:

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key)
      return target[key]
    },
    set(target, key, value) {
      target[key] = value
      trigger(target, key)
      return true
    }
  })
}

依赖收集系统 实现一个简单的依赖追踪机制:

let activeEffect
function track(target, key) {
  if (activeEffect) {
    const depsMap = targetMap.get(target) || new Map()
    const dep = depsMap.get(key) || new Set()
    dep.add(activeEffect)
    targetMap.set(target, depsMap)
    depsMap.set(key, dep)
  }
}

function trigger(target, key) {
  const depsMap = targetMap.get(target)
  if (!depsMap) return
  const dep = depsMap.get(key)
  dep && dep.forEach(effect => effect())
}

模板编译

将模板字符串转换为渲染函数:

function compile(template) {
  // 简单实现:替换插值表达式
  const renderCode = template.replace(
    /\{\{(.*?)\}\}/g,
    '${_ctx.$1}'
  )
  return new Function('_ctx', `return \`${renderCode}\``)
}

虚拟 DOM 实现

简化版的虚拟 DOM 和 diff 算法:

function createVNode(tag, props, children) {
  return { tag, props, children }
}

function patch(oldVNode, newVNode) {
  if (!oldVNode) {
    // 初次渲染
    return mount(newVNode)
  } else {
    // 更新
    if (oldVNode.tag === newVNode.tag) {
      // 更新属性
      updateProps(oldVNode, newVNode)
      // 递归更新子节点
      patchChildren(oldVNode, newVNode)
    } else {
      // 替换节点
      replaceNode(oldVNode, newVNode)
    }
  }
}

组件系统基础

实现最简单的组件机制:

class Component {
  constructor(options) {
    this.$options = options
    this._data = reactive(options.data())
    this._el = null
  }

  mount(el) {
    this._el = el
    this.update()
  }

  update() {
    const vnode = this.$options.render.call(this)
    patch(this._prevVNode, vnode)
    this._prevVNode = vnode
  }
}

完整示例整合

将这些部分组合成一个简易 Vue 类:

自己动手实现vue

class MiniVue {
  constructor(options) {
    this.$options = options
    this._data = reactive(options.data())
    this._el = document.querySelector(options.el)
    this._prevVNode = null

    effect(() => {
      const vnode = options.render.call(this)
      patch(this._prevVNode, vnode)
      this._prevVNode = vnode
    })
  }
}

使用示例

const app = new MiniVue({
  el: '#app',
  data() {
    return { count: 0 }
  },
  render() {
    return createVNode('div', {
      onClick: () => this.count++
    }, `Count: ${this.count}`)
  }
})

这个实现包含了 Vue 最核心的功能:响应式数据、虚拟 DOM 和组件系统。实际 Vue 的实现要复杂得多,还包括生命周期、指令系统、插槽等高级功能。

标签: 自己动手vue
分享给朋友:

相关文章

vue实现hover

vue实现hover

Vue 实现 hover 效果的方法 在 Vue 中实现 hover 效果可以通过多种方式实现,包括使用 CSS、Vue 指令或事件监听。以下是几种常见的方法: 使用 CSS :hover 伪类 通…

vue实现portal

vue实现portal

Vue 实现 Portal 功能 Portal 是一种将子节点渲染到父组件 DOM 层级之外的 DOM 节点的技术,常用于实现模态框、弹出层等需要脱离当前组件层级的场景。Vue 可以通过多种方式实现…

vue 实现平面

vue 实现平面

Vue 实现平面的方法 在 Vue 中实现平面效果通常涉及 CSS 样式、UI 框架或自定义组件的使用。以下是几种常见方法: 使用 CSS 样式 通过 Vue 的样式绑定或 scoped CSS 为…

vue模版实现

vue模版实现

Vue 模板实现方法 Vue 模板是 Vue.js 的核心特性之一,用于声明式地将 DOM 绑定至底层 Vue 实例的数据。以下是几种常见的 Vue 模板实现方式: 单文件组件(SFC) 使用 .v…

vue实现输入地址

vue实现输入地址

Vue 实现输入地址功能 在 Vue 中实现输入地址功能,可以通过结合表单输入、地图 API(如高德、百度或 Google Maps)以及地址自动补全等方式完成。以下是几种常见方法: 使用高德地图…

vue radio组件实现

vue radio组件实现

Vue Radio 组件实现 在 Vue 中实现 Radio 组件可以通过原生 HTML 的 <input type="radio"> 结合 Vue 的响应式特性,或者使用第三方 UI 库…