当前位置:首页 > VUE

proxy实现vue

2026-02-10 12:48:15VUE

使用Proxy实现Vue响应式系统

Proxy是ES6引入的特性,能够拦截对象的操作,Vue3利用Proxy替代了Vue2中的Object.defineProperty来实现响应式。以下是实现核心逻辑的方法:

创建响应式对象

function reactive(target) {
  return new Proxy(target, {
    get(target, key, receiver) {
      track(target, key); // 依赖收集
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(target, key); // 触发更新
      return true;
    }
  });
}

依赖收集与触发

proxy实现vue

const targetMap = new WeakMap();
let activeEffect = null;

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

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

副作用函数处理

function effect(fn) {
  activeEffect = fn;
  fn();
  activeEffect = null;
}

实现计算属性

基于上述响应式系统,可以扩展实现计算属性:

proxy实现vue

function computed(getter) {
  let value;
  let dirty = true;

  const runner = effect(getter, {
    lazy: true,
    scheduler() {
      dirty = true;
      trigger(obj, 'value');
    }
  });

  const obj = {
    get value() {
      if (dirty) {
        value = runner();
        dirty = false;
      }
      track(obj, 'value');
      return value;
    }
  };

  return obj;
}

实现模板编译

结合Proxy响应式系统,可以模拟Vue的模板编译:

function compile(template) {
  return function render(ctx) {
    const div = document.createElement('div');
    div.innerHTML = template.replace(/{{(.*?)}}/g, (_, exp) => {
      return exp.split('.').reduce((obj, k) => obj[k], ctx);
    });
    return div.firstChild;
  };
}

完整示例组合

将各部分组合成简易Vue实现:

class MiniVue {
  constructor(options) {
    this.$options = options;
    this.$data = reactive(options.data());
    this.proxyData();
    this.$el = document.querySelector(options.el);
    this.compile();
  }

  proxyData() {
    for (const key in this.$data) {
      Object.defineProperty(this, key, {
        get: () => this.$data[key],
        set: val => (this.$data[key] = val)
      });
    }
  }

  compile() {
    const render = compile(this.$options.template);
    effect(() => {
      const newNode = render(this.$data);
      this.$el.innerHTML = '';
      this.$el.appendChild(newNode);
    });
  }
}

注意事项

Proxy相比Object.defineProperty的优势在于能检测到新增属性、数组索引变化等,但需要注意以下问题:

  • 浏览器兼容性:Proxy无法被polyfill
  • 性能考虑:嵌套对象的处理需要递归代理
  • 原始值处理:需要额外包装为对象才能被代理

这种实现展示了Vue响应式原理的核心思想,实际Vue3的实现还包含更多优化和边界情况处理。

标签: proxyvue
分享给朋友:

相关文章

vue菜单实现

vue菜单实现

Vue 菜单实现方法 使用 Element UI 的菜单组件 Element UI 提供了现成的菜单组件,适合快速实现导航菜单。安装 Element UI 后,可以直接使用 el-menu 相关组件。…

vue slot实现

vue slot实现

vue slot 的实现方法 在 Vue 中,slot 是一种内容分发机制,允许父组件向子组件传递模板内容。以下是几种常见的 slot 实现方式: 默认 slot 默认 slot 是最基础的 slo…

vue 实现轮播

vue 实现轮播

Vue 实现轮播的方法 使用第三方库(如 Swiper) 安装 Swiper 库: npm install swiper 在 Vue 组件中引入 Swiper: <template>…

vue 实现工具

vue 实现工具

Vue 实现工具的方法 使用 Vue 实现工具功能可以通过多种方式完成,具体取决于工具的类型和需求。以下是几种常见的方法: 组件化实现 创建一个独立的 Vue 组件来封装工具功能。例如,实现一个计…

vue 实现fadeout

vue 实现fadeout

Vue 实现淡出效果 在 Vue 中实现淡出(fade-out)效果可以通过 CSS 过渡或动画结合 Vue 的动态渲染功能完成。以下是几种常见方法: 使用 Vue 过渡(Transition)组件…

vue实现队列

vue实现队列

Vue 实现队列功能 在 Vue 中实现队列功能可以通过多种方式完成,以下是几种常见的方法: 使用数组模拟队列 队列遵循先进先出(FIFO)原则,可以用数组的 push 和 shift 方法模拟入队…