当前位置:首页 > VUE

vue数据驱动模拟实现

2026-01-23 13:09:29VUE

Vue 数据驱动模拟实现

Vue 的数据驱动核心基于响应式系统,通过劫持数据变化触发视图更新。以下是模拟实现的关键步骤:

响应式数据劫持

使用 Object.definePropertyProxy 监听对象属性变化:

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() {
    const newValue = this.vm[this.key];
    if (newValue !== this.value) {
      this.cb(newValue);
      this.value = newValue;
    }
  }
}

模板编译与绑定

模拟 compile 解析模板并绑定数据:

vue数据驱动模拟实现

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

  const nodes = fragment.querySelectorAll('[v-model]');
  nodes.forEach(node => {
    const key = node.getAttribute('v-model');
    new Watcher(vm, key, value => {
      node.value = value;
    });
    node.addEventListener('input', e => {
      vm[key] = e.target.value;
    });
  });

  el.appendChild(fragment);
}

完整示例整合

class MiniVue {
  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(this, key, data[key]);
    });
  }
}

使用示例

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

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

关键点说明

  • 数据劫持:通过拦截对象的读写操作实现响应式。
  • 依赖收集:在 getter 中收集依赖,在 setter 中触发更新。
  • 异步更新队列:实际 Vue 会使用队列优化多次更新(此处简化实现)。
  • 虚拟 DOM 差异:完整版 Vue 会结合虚拟 DOM 提升性能,模拟实现可省略此步骤。

标签: 数据vue
分享给朋友:

相关文章

vue实现弹窗

vue实现弹窗

Vue 实现弹窗的常见方法 使用组件化方式封装弹窗 创建一个独立的弹窗组件(如 Modal.vue),通过 v-if 或 v-show 控制显示隐藏: <template> <…

vue实现picker

vue实现picker

Vue 实现 Picker 组件的方法 在 Vue 中实现 Picker 组件可以通过多种方式完成,以下是几种常见的实现方法: 使用原生 HTML 和 CSS 实现 通过 Vue 的模板和样式绑定,…

vue实现拖拉

vue实现拖拉

实现拖拽功能的基本步骤 在Vue中实现拖拽功能可以通过原生HTML5的拖放API或第三方库如vuedraggable完成。以下是两种方法的详细说明。 使用HTML5原生拖放API HTML5提供了原…

vue实现画板

vue实现画板

Vue 实现画板功能 在 Vue 中实现画板功能可以通过 HTML5 的 Canvas API 实现。以下是一个完整的实现方案: 创建 Vue 组件 新建一个 Vue 单文件组件(SFC),命名为…

vue实现复制

vue实现复制

Vue 实现复制功能 在 Vue 中实现复制功能可以通过多种方式完成,以下是几种常见的方法: 方法一:使用 Clipboard API Clipboard API 是现代浏览器提供的一种原生 AP…

vue实现上划

vue实现上划

Vue 实现上划功能 在Vue中实现上划功能,可以通过监听触摸事件(touchstart、touchmove、touchend)来判断用户的手势方向。以下是实现上划功能的几种方法: 监听触摸事件 通…