当前位置:首页 > JavaScript

如何js实现watch

2026-02-03 08:22:00JavaScript

实现数据监听(Watch)的方法

在JavaScript中实现类似Vue的watch功能,可以通过以下几种方式监听对象属性的变化:

使用Object.defineProperty

通过定义属性的getter/setter实现基础监听:

如何js实现watch

function observe(obj, key, callback) {
  let value = obj[key]
  Object.defineProperty(obj, key, {
    get() {
      return value
    },
    set(newVal) {
      if (newVal !== value) {
        const oldVal = value
        value = newVal
        callback(newVal, oldVal)
      }
    }
  })
}

const data = { count: 0 }
observe(data, 'count', (newVal, oldVal) => {
  console.log(`count changed from ${oldVal} to ${newVal}`)
})

使用Proxy实现深度监听

Proxy可以拦截整个对象的操作,适合深层监听:

如何js实现watch

function createWatcher(target, callback) {
  return new Proxy(target, {
    set(target, key, value, receiver) {
      const oldValue = target[key]
      if (oldValue !== value) {
        Reflect.set(target, key, value, receiver)
        callback(key, value, oldValue)
      }
      return true
    }
  })
}

const store = createWatcher({ price: 10 }, (key, newVal, oldVal) => {
  console.log(`${key} updated: ${oldVal} -> ${newVal}`)
})

第三方库实现

使用现成的观察者模式库更高效:

// 使用MobX
import { observable, observe } from 'mobx'

const obj = observable({ value: 1 })
const disposer = observe(obj, change => {
  console.log(`${change.name} changed`, change)
})

obj.value = 2
disposer() // 停止监听

自定义发布订阅模式

实现简单的观察者模式:

class Watcher {
  constructor() {
    this.subscribers = new Map()
  }

  watch(target, key, callback) {
    if (!this.subscribers.has(target)) {
      this.subscribers.set(target, new Map())
    }
    this.subscribers.get(target).set(key, callback)
  }

  notify(target, key, newVal, oldVal) {
    const callbacks = this.subscribers.get(target)?.get(key)
    callbacks?.(newVal, oldVal)
  }
}

const watcher = new Watcher()
const obj = { data: '' }
watcher.watch(obj, 'data', (newVal) => console.log('Data changed:', newVal))

注意事项

  • 原始方法无法检测数组变化,需特殊处理数组方法
  • Proxy有更好的性能但存在浏览器兼容性问题
  • 深层嵌套对象需要递归处理
  • 考虑使用WeakMap避免内存泄漏

标签: jswatch
分享给朋友:

相关文章

js实现拖拽

js实现拖拽

实现拖拽的基本步骤 通过监听鼠标事件(mousedown、mousemove、mouseup)实现拖拽功能。以下是核心代码逻辑: const draggableElement = document.…

js如何实现继承

js如何实现继承

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

js实现复制到剪贴板

js实现复制到剪贴板

使用document.execCommand方法(传统方式,已废弃但部分浏览器仍支持) 该方法适用于旧版浏览器,但已被标记为废弃。执行前需确保文本已被选中: function copyToClipb…

js实现pdf在线预览

js实现pdf在线预览

使用PDF.js实现PDF在线预览 PDF.js是由Mozilla开发的一个开源JavaScript库,可以在网页中直接渲染PDF文件。以下是实现PDF在线预览的步骤: 引入PDF.js库 在HT…

js实现瀑布流

js实现瀑布流

实现瀑布流布局 瀑布流布局是一种常见的网页布局方式,常用于图片展示、商品列表等场景。以下是使用 JavaScript 实现瀑布流布局的几种方法。 纯 JavaScript 实现 通过计算元素的位置和…

js实现tab选项卡切换

js实现tab选项卡切换

实现Tab选项卡切换的JavaScript方法 使用纯JavaScript实现Tab切换功能,可以通过监听点击事件动态切换内容显示状态。以下是两种常见实现方式: 基础DOM操作实现 /…