当前位置:首页 > VUE

自己实现vue双括号

2026-02-24 04:08:01VUE

实现 Vue 双括号插值的基本原理

Vue 的双括号插值({{}})是一种数据绑定的语法,核心是通过解析模板中的双括号内容,将其替换为对应数据对象的属性值,并实现数据变化时的自动更新。

核心步骤

数据劫持与响应式 通过 Object.definePropertyProxy 监听数据对象属性的变化。当数据被访问或修改时,触发相应的 getter/setter。

function observe(data) {
  if (!data || typeof data !== 'object') return;
  Object.keys(data).forEach(key => {
    let value = data[key];
    const dep = new Dep();
    observe(value);
    Object.defineProperty(data, key, {
      get() {
        Dep.target && dep.addSub(Dep.target);
        return value;
      },
      set(newVal) {
        if (newVal === value) return;
        value = newVal;
        observe(newVal);
        dep.notify();
      }
    });
  });
}

依赖收集与发布订阅 定义一个 Dep 类管理依赖(Watcher),并在数据变化时通知所有订阅者更新。

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

模板编译 解析 HTML 模板,提取双括号中的表达式,并创建对应的 Watcher 实例。

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

function replace(node, vm) {
  const reg = /\{\{(.*?)\}\}/g;
  if (node.nodeType === 3) {
    const text = node.textContent;
    if (reg.test(text)) {
      const exp = RegExp.$1.trim();
      node.textContent = text.replace(reg, vm[exp]);
      new Watcher(vm, exp, val => {
        node.textContent = text.replace(reg, val);
      });
    }
  }
  if (node.nodeType === 1) {
    Array.from(node.childNodes).forEach(child => replace(child, vm));
  }
}

Watcher 实现 Watcher 作为观察者,在初始化时触发 getter 收集依赖,并在数据更新时执行回调。

自己实现vue双括号

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

完整示例

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

function proxy(vm, sourceKey) {
  Object.keys(vm[sourceKey]).forEach(key => {
    Object.defineProperty(vm, key, {
      get() {
        return vm[sourceKey][key];
      },
      set(newVal) {
        vm[sourceKey][key] = newVal;
      }
    });
  });
}

// 使用示例
const vm = new MiniVue({
  el: '#app',
  data: { message: 'Hello Vue!' }
});

关键点说明

  • 数据劫持通过 Object.defineProperty 实现,Vue 3 改用 Proxy
  • 模板编译通过递归遍历 DOM 节点,匹配双括号内容。
  • 依赖收集在 getter 中完成,更新通知在 setter 中触发。
  • Watcher 是连接数据和视图的桥梁,负责更新 DOM。

标签: 括号vue
分享给朋友:

相关文章

vue实现菜单栏锚点

vue实现菜单栏锚点

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

vue实现app

vue实现app

Vue 实现 App 的常见方法 使用 Vue 开发移动端 App 主要有两种主流方案:混合开发(Hybrid)和原生渲染。以下是具体实现方式和工具链: 混合开发方案(WebView 嵌入) 通过…

vue router 实现

vue router 实现

Vue Router 的实现 Vue Router 是 Vue.js 的官方路由管理器,用于构建单页面应用(SPA)。以下是 Vue Router 的核心实现方式。 安装 Vue Router 通过…

mvvm实现vue

mvvm实现vue

MVVM 模式在 Vue 中的实现 MVVM(Model-View-ViewModel)是一种前端架构模式,Vue 的设计灵感来源于此。以下是 MVVM 在 Vue 中的核心实现方式: 数据绑定(M…

vue实现gridlayout

vue实现gridlayout

Vue 实现 Grid Layout 使用 CSS Grid 布局 CSS Grid 是一种强大的布局系统,可以直接在 Vue 组件的样式中使用。通过定义网格容器和网格项,可以快速实现复杂的布局结构。…

vue实现录音

vue实现录音

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