• JS 实现对象监听 - Kaiqisan


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

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

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

    // 第一个参数填写欲监听的对象
    // 第二个参数填写欲监听的对象下的属性
    Object.defineProperty(obj, 'attr', {
    	get() {
    		return val
        },
    	set(newValue) {
            console.log('触发!');
    		val= newValue
        }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    监听的功能通过上述的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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在打开页面之后的三秒后,输出框会自动修改对象的值并触发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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    扩展

    上述的方法虽然能监听对象内部的属性值的变化,如果只是监听外部的对象,是很难具体获取内部的哪个属性值发生了变化。这个还需后序的比较,非常麻烦,所以,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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    总结

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

  • 相关阅读:
    【Azure 事件中心】 org.slf4j.Logger 收集 Event Hub SDK(Java) 输出日志并以文件形式保存
    数组更新检测
    java版微信小程序商城 免 费 搭 建 java版直播商城平台规划及常见的营销模式有哪些?电商源码/小程序/三级分销
    燃气管网监测系统,让城市生命线更安全
    CSS transition和animation的用法和区别
    c# SafeGuardLock安全锁mutex
    mongodb-批量刷新数据
    白盒子测试总结
    如何在linux(Ubuntu)下安装unity(Unity engine游戏引擎)
    【机器学习】期望最大算法(EM算法)解析:Expectation Maximization Algorithm
  • 原文地址:https://blog.csdn.net/qq_33933205/article/details/125428983