当前位置:首页 > VUE

从0实现vue

2026-03-08 07:04:04VUE

实现简易 Vue 的核心模块

数据响应式系统
通过 Object.definePropertyProxy 监听数据变化。以下为基于 Object.defineProperty 的简化实现:

function defineReactive(obj, key, val) {
  const dep = new Dep();
  Object.defineProperty(obj, key, {
    get() {
      Dep.target && dep.addSub(Dep.target);
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify();
    }
  });
}

依赖收集与发布
实现 Dep(依赖管理器)和 Watcher(观察者):

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

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

模板编译

解析 DOM 模板
将模板中的 {{}} 和指令转换为数据绑定:

从0实现vue

function compile(el, vm) {
  const fragment = document.createDocumentFragment();
  let child;
  while (child = el.firstChild) {
    fragment.appendChild(child);
  }

  function replace(frag) {
    Array.from(frag.childNodes).forEach(node => {
      const txt = node.textContent;
      const reg = /\{\{(.*?)\}\}/g;
      if (node.nodeType === 3 && reg.test(txt)) {
        const key = RegExp.$1.trim();
        new Watcher(vm, key, newVal => {
          node.textContent = txt.replace(reg, newVal);
        });
        node.textContent = txt.replace(reg, vm[key]);
      }
      if (node.childNodes) replace(node);
    });
  }
  replace(fragment);
  el.appendChild(fragment);
}

初始化 Vue 实例

整合核心模块创建构造函数:

class Vue {
  constructor(options) {
    this.$options = options;
    this.$data = options.data;
    this.observe(this.$data);
    compile(options.el, this);
  }

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

示例用法

<div id="app">{{ message }}</div>
<script>
  const vm = new Vue({
    el: '#app',
    data: { message: 'Hello Vue!' }
  });
  setTimeout(() => {
    vm.message = 'Updated!'; // 视图自动更新
  }, 1000);
</script>

扩展方向

  1. 虚拟 DOM
    实现 patch 函数对比新旧 VNode,提升渲染性能。

    从0实现vue

  2. 指令系统
    支持 v-modelv-for 等指令,例如通过扩展 compile 函数解析指令。

  3. 生命周期钩子
    在特定阶段触发 createdmounted 等回调函数。

  4. 组件化
    通过 Vue.component 注册组件,支持嵌套和 props 通信。

该实现省略了错误处理和边缘情况,实际 Vue 源码包含更复杂的优化和兼容性处理。

标签: vue
分享给朋友:

相关文章

vue实现走势图

vue实现走势图

Vue 实现走势图的方法 使用 ECharts 库 ECharts 是一个强大的数据可视化库,支持多种图表类型,包括走势图(折线图)。在 Vue 项目中可以通过 vue-echarts 封装库或直接使…

vue请求实现进度条

vue请求实现进度条

实现请求进度条的方法 在Vue中实现请求进度条可以通过多种方式完成,常见的有使用第三方库如axios结合nprogress或自定义进度条组件。以下是几种实现方法: 使用axios和nprogress…

vue实现switch

vue实现switch

Vue 实现 Switch 开关组件 在 Vue 中实现 Switch 开关组件可以通过自定义组件或使用现有 UI 库完成。以下是几种常见实现方式: 自定义 Switch 组件 创建一个基础 Sw…

vue实现返回

vue实现返回

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

vue实现录像

vue实现录像

Vue 实现录像功能 在 Vue 中实现录像功能通常需要借助浏览器的 MediaDevices API 和 MediaRecorder API。以下是实现步骤: 获取用户摄像头和麦克风权限 使用 n…

vue实现气泡

vue实现气泡

Vue 实现气泡效果的方法 在 Vue 中实现气泡效果可以通过 CSS 动画、第三方库或自定义组件完成。以下是几种常见实现方式: 使用纯 CSS 和 Vue 过渡 通过 Vue 的过渡系统结合 CS…