当前位置:首页 > JavaScript

js watch 实现

2026-04-05 23:09:05JavaScript

js watch 实现

js watch 实现

实现 JavaScript 的 watch 功能

在 JavaScript 中实现类似 Vue 的 watch 功能,可以通过以下几种方式:

使用 Proxy 实现数据监听

function createWatcher(target, callback) {
  return new Proxy(target, {
    set(obj, prop, value) {
      const oldValue = obj[prop];
      obj[prop] = value;
      callback(prop, oldValue, value);
      return true;
    }
  });
}

const data = { count: 0 };
const watchedData = createWatcher(data, (key, oldValue, newValue) => {
  console.log(`属性 ${key} 从 ${oldValue} 变为 ${newValue}`);
});

watchedData.count = 1; // 输出: 属性 count 从 0 变为 1

使用 Object.defineProperty 实现

function defineReactive(obj, key, val, callback) {
  Object.defineProperty(obj, key, {
    get() {
      return val;
    },
    set(newVal) {
      const oldVal = val;
      val = newVal;
      callback(key, oldVal, newVal);
    }
  });
}

const data = {};
defineReactive(data, 'message', 'hello', (key, oldVal, newVal) => {
  console.log(`${key} changed from ${oldVal} to ${newVal}`);
});

data.message = 'world'; // 输出: message changed from hello to world

使用 ES6 的 Reflect 和 Proxy

class Watcher {
  constructor(data, callback) {
    this.data = data;
    this.callback = callback;
    return this.proxy();
  }

  proxy() {
    return new Proxy(this.data, {
      set: (target, key, value) => {
        const oldValue = target[key];
        Reflect.set(target, key, value);
        this.callback(key, oldValue, value);
        return true;
      }
    });
  }
}

const obj = { name: 'Alice' };
const watchedObj = new Watcher(obj, (key, oldVal, newVal) => {
  console.log(`属性 ${key} 变化: ${oldVal} -> ${newVal}`);
});

watchedObj.name = 'Bob'; // 输出: 属性 name 变化: Alice -> Bob

实现深度监听

function deepWatch(obj, callback, path = []) {
  return new Proxy(obj, {
    get(target, key) {
      const value = Reflect.get(target, key);
      if (typeof value === 'object' && value !== null) {
        return deepWatch(value, callback, [...path, key]);
      }
      return value;
    },
    set(target, key, value) {
      const oldValue = target[key];
      const result = Reflect.set(target, key, value);
      if (result) {
        const fullPath = [...path, key].join('.');
        callback(fullPath, oldValue, value);
      }
      return result;
    }
  });
}

const nestedObj = { user: { name: 'John' } };
const watchedNested = deepWatch(nestedObj, (path, oldVal, newVal) => {
  console.log(`${path} changed from ${oldVal} to ${newVal}`);
});

watchedNested.user.name = 'Doe'; // 输出: user.name changed from John to Doe

注意事项

  • Proxy 无法监听数组的某些方法(如 push/pop),需要额外处理
  • Object.defineProperty 对数组支持有限,且无法监听新增属性
  • 深度监听可能影响性能,应根据实际需求决定监听层级
  • 现代前端框架(如 Vue 3)已使用 Proxy 替代 Object.defineProperty

以上方法可以根据具体需求选择使用,Proxy 方案更现代且功能更强大,但需要考虑浏览器兼容性。

标签: jswatch
分享给朋友:

相关文章

js实现轮播图

js实现轮播图

轮播图实现方法 基础HTML结构 <div class="slider"> <div class="slides"> <img src="image1.jpg…

js如何实现继承

js如何实现继承

原型链继承 通过将子类的原型指向父类的实例实现继承。子类实例能够访问父类原型上的属性和方法。 function Parent() { this.name = 'parent'; } Parent…

js实现图片放大缩小

js实现图片放大缩小

实现图片放大缩小的基础方法 使用CSS的transform: scale()属性可以快速实现图片的放大缩小效果。通过JavaScript动态修改该属性值: const img = document.…

js实现防洪

js实现防洪

防抖(Debounce)实现 防抖的核心思想是在事件触发后延迟执行回调函数,若在延迟时间内再次触发事件,则重新计时。适用于输入框搜索、窗口调整等场景。 function debounce(f…

js树实现

js树实现

树的基本概念 树是一种非线性的数据结构,由节点和边组成。每个节点包含一个值和指向子节点的引用。树的顶部节点称为根节点,没有子节点的节点称为叶节点。 树的实现方式 在JavaScript中,树可以通过…

js实现吸色

js实现吸色

使用Canvas实现吸色功能 通过Canvas的getImageData方法获取像素颜色数据。创建一个Canvas元素,将目标图像绘制到Canvas上,通过鼠标事件获取坐标对应的颜色值。 c…