JS 实现对象监听 - Kaiqisan

JS 实现对对象内参数的监听

哈嗨哈,这里是超会拖更的Kaiqisan,自从成为社畜之后就很少有空撰写博客了,今天下午后端那边服务器在维修,这就给了我很多整理博客的时间(摸鱼?)

使用过vue的人都知道vue拥有对参数监听的便捷方法,其原理就是使用数据劫持,在每次数据产生变化的时候触发其内在的函数,其书写方式如下

// 第一个参数填写欲监听的对象
// 第二个参数填写欲监听的对象下的属性
Object.defineProperty(obj, 'attr', {
	get() {
		return val
    },
	set(newValue) {
        console.log('触发!');
		val= newValue
    }
})

监听的功能通过上述的Object.defineProperty来实现,并借助了其第三个参数----属性描述符完成数据劫持,每次获取或修改数据,都将走过这一步,这也是vue的监听实现的底层逻辑。

如果开发者不设置这个高级选项,那么也就是进行一个默认的选项,getter默认返回当前对象的值,setter默认在修改值之后不进行任何操作。

下面的代码为具体的一个实例

	let obj = {
        name: 'John',
        uid: '12345',
    }
    let _uid = obj.uid;

    Object.defineProperty(obj, 'uid', {
		get() {
			return _uid
        },
		set(newValue) {
            console.log('触发!');
			_uid = newValue
        }
    })
    // 测试代码
	setTimeout(() => {
		obj.uid = '54321'
		console.log(obj.uid);
	}, 3000)

在打开页面之后的三秒后,输出框会自动修改对象的值并触发setter内的事件。
其中值得注意的是上面的一个临时参数_uid,这个参数的作用就在用户获取uid的时候能够获取正确的数据。
因为一些内在原因,getter和setter无法调用自己所监听的对象属性。
在这里插入图片描述
所以需要借助第三方的参数_uid来实现对象属性值的存储。

注意

这个监听的方法不仅可以实现对属性值的监听,也可以监听整个对象,如果对象内部的值产生变化就会回调setter。

    let obj = {
        name: 'John',
        uid: '12345',
		details: {
            phoneNumber: '1234567890',
		}
    }
    let details = obj.details;

    Object.defineProperty(obj, 'details', {
		get() {
			return details
        },
		set(newValue) {
            console.log('触发!');
			details = newValue
        }
    })
	setTimeout(() => {
		// 修改了obj.details内部的手机号
		obj.details.phoneNumber= '12345678901'
		console.log(obj.details);
	}, 3000)

扩展

上述的方法虽然能监听对象内部的属性值的变化,如果只是监听外部的对象,是很难具体获取内部的哪个属性值发生了变化。这个还需后序的比较,非常麻烦,所以,JS原生还有一种方法可以批量地监听,这不仅能够监听对象内部的多个属性,也可以极大地减少代码量。

这个方法就是使用Object.defineProperty所衍生的Object.defineProperties

    let obj = {
        name: 'John',
        uid: '12345',
        phoneNumber: '123456789',
    }
    let name = obj.name
    let uid = obj.uid
    let phoneNumber = obj.phoneNumber

    Object.defineProperties(obj, {
        'name': {
            get() {
                return name
            },
            set(value) {
                console.log('名字发生变化' + value)
                name = value
            }

        },
        'uid': {
            get() {
                return uid
            },
            set(value) {
                console.log('uid发生变化' + value)
                uid = value
            }
        },
        'phoneNumber': {
            get() {
                return phoneNumber
            },
            set(value) {
                console.log('phoneNumber发生变化' + value)
				phoneNumber = value
            }
        }
    })

    setTimeout(() => {
        obj.name = 'Tom'
	}, 1000)

	setTimeout(() => {
		obj.uid = '123456'
	}, 2000)
	
	setTimeout(() => {
		obj.phoneNumber = '123456789'
	}, 3000)

总结

好了,我们了解了监听的底层逻辑了,是时候自己模拟一遍vue的watch的方法了!!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kaiqisan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值