iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >JS监听变量改变如何实现
  • 407
分享到

JS监听变量改变如何实现

2023-07-06 04:07:10 407人浏览 八月长安
摘要

这篇文章主要介绍“js监听变量改变如何实现”,在日常操作中,相信很多人在JS监听变量改变如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JS监听变量改变如何实现”的疑惑有所帮助!接下来,请跟着小编一起来

这篇文章主要介绍“js监听变量改变如何实现”,在日常操作中,相信很多人在JS监听变量改变如何实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JS监听变量改变如何实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    需求和背景

    在业务中,由于项目采用微前端架构,需要通过A应用的某个值的变化对B应用中的DOM进行改变(如弹出一个Modal),第一个想到的可能是发布订阅模式,其实不如将问题缩小化,采用原生的能力去解决。

    下面给出两种解决方案,同时也是尤大写Vue时的思路

    • ES5 的 Object.defineProperty

    • es6Proxy

    Object.defineProperty

    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

    ——MDN

    用法如下:

    Object.defineProperty(obj, prop, option)

    入参用法:

    • obj:代理对象;

    • prop:代理对象中的key;

    • option:配置对象,getset都在其中配置;

    例子:

    var obj = {   name: 'sorryhc' }var rocordName = 'sorryhc';Object.defineProperty(obj, 'name', {  enumerable: true,  configurable:true,  set: function(newVal) {      rocordName = newVal       console.log('set: ' + rocordName)  },  get: function() {      console.log('get: ' + rocordName)      return rocordName  }})obj.name = 'sorrycc' // set: sorryccconsole.log(obj.name) // get: sorrycc

    对一个对象进行整体响应式监听:

    // 监视对象function observe(obj) {  // 遍历对象,使用 get/set 重新定义对象的每个属性值   Object.keys(obj).forEach(key => {       defineReactive(obj, key, obj[key])   })}function defineReactive(obj, k, v) {   // 递归子属性   if (typeof(v) === 'object') observe(v)      // 重定义 get/set   Object.defineProperty(obj, k, {       enumerable: true,       configurable: true,       get: function reactiveGetter() {           console.log('get: ' + v)           return v       },       // 重新设置值时,触发收集器的通知机制       set: function reactiveSetter(newV) {           console.log('set: ' + newV)           v = newV       },   })}let data = {a: 1}// 监视对象observe(data)data.a // get: 1data.a = 2 // set: 2

    整体思路就是遇到子对象就递归,和深拷贝一样的读参顺序。

    缺陷

    如果学习过Vue2源码的同学可能比较熟,基于下面的缺陷,也是出现了$set$get的用法。

    • IE8 及更低版本 IE 是不支持的

    • 无法检测到对象属性的新增或删除

    • 如果修改数组的 length ( Object.defineProperty 不能监听数组的长度),以及数组的 push 等变异方法是无法触发 setter 的

    Proxy

    Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)

    — MDN

    const obj = new Proxy(target, handler)

    其中:

    • target :要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)

    • handler :一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 obj 的行为

    例子

    const handler = {  get: function(target, name){      return name in target ? target[name] : 'no prop!'  },  set: function(target, prop, value, receiver) {      target[prop] = value;      console.log('property set: ' + prop + ' = ' + value);      return true;  }};var user = new Proxy({}, handler)user.name = 'sorryhc' // property set: name = sorryhcconsole.log(user.name) // sorryhcconsole.log(user.age) // no prop!

    并且Proxy提供了更丰富的代理能力:

    • getPrototypeOf / setPrototypeOf

    • isExtensible / preventExtensions

    • ownKeys / getOwnPropertyDescriptor

    • defineProperty / deleteProperty

    • get / set / has

    • apply / construct

    感兴趣的可以查看 MDN ,一一尝试一下,这里不再赘述

    在React中的实践

    这里展示两段伪代码,大概业务流程是,当点击页面某个按钮(打开/关闭弹窗),触发window.obj.showModal的切换,从而被监听到全局变量的变化,从而改变React中的state状态,最终触发Modal的弹窗。

    Object.defineProperty

    window.obj = {  showModal: false}const [visible, setVisible] = useState(false);useEffect(() => {  visible && Modal.show({    // ...  })}, [visible])Object.defineProperty(window.obj, 'showModal', {  enumerable: true,  configurable:true,  set: function(newVal) {    setVisible(newVal);      console.log('set: ' + newVal)  },  get: function() {      console.log('get: ' + visible)      return visible  }})window.obj.showModal = !window.obj.showModal // set: trueconsole.log(window.obj.showModal) // get: true

    Proxy

    const [visible, setVisible] = useState(false);useEffect(() => {  visible && Modal.show({    // ...  })}, [visible])const handler = {  get: function(target, name){      return name in target ? target[name] : 'no prop!'  },  set: function(target, prop, value, receiver) {      target[prop] = value;      setVisible(value);      console.log('property set: ' + prop + ' = ' + value);      return true;  }};window.obj = new Proxy({showModal: false}, handler)window.obj.showModal = !window.obj.showModal // property set: showModal = trueconsole.log(window.obj.showModal) // true

    到此,关于“JS监听变量改变如何实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

    --结束END--

    本文标题: JS监听变量改变如何实现

    本文链接: https://www.lsjlt.com/news/357685.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • C++ 生态系统中流行库和框架的贡献指南
      作为 c++++ 开发人员,通过遵循以下步骤即可为流行库和框架做出贡献:选择一个项目并熟悉其代码库。在 issue 跟踪器中寻找适合初学者的问题。创建一个新分支,实现修复并添加测试。提交...
      99+
      2024-05-14
      框架 c++ 流行库 git
    • C++ 生态系统中流行库和框架的社区支持情况
      c++++生态系统中流行库和框架的社区支持情况:boost:活跃的社区提供广泛的文档、教程和讨论区,确保持续的维护和更新。qt:庞大的社区提供丰富的文档、示例和论坛,积极参与开发和维护。...
      99+
      2024-05-14
      生态系统 社区支持 c++ overflow 标准库
    • c++中if elseif使用规则
      c++ 中 if-else if 语句的使用规则为:语法:if (条件1) { // 执行代码块 1} else if (条件 2) { // 执行代码块 2}// ...else ...
      99+
      2024-05-14
      c++
    • c++中的继承怎么写
      继承是一种允许类从现有类派生并访问其成员的强大机制。在 c++ 中,继承类型包括:单继承:一个子类从一个基类继承。多继承:一个子类从多个基类继承。层次继承:多个子类从同一个基类继承。多层...
      99+
      2024-05-14
      c++
    • c++中如何使用类和对象掌握目标
      在 c++ 中创建类和对象:使用 class 关键字定义类,包含数据成员和方法。使用对象名称和类名称创建对象。访问权限包括:公有、受保护和私有。数据成员是类的变量,每个对象拥有自己的副本...
      99+
      2024-05-14
      c++
    • c++中优先级是什么意思
      c++ 中的优先级规则:优先级高的操作符先执行,相同优先级的从左到右执行,括号可改变执行顺序。操作符优先级表包含从最高到最低的优先级列表,其中赋值运算符具有最低优先级。通过了解优先级,可...
      99+
      2024-05-14
      c++
    • c++中a+是什么意思
      c++ 中的 a+ 运算符表示自增运算符,用于将变量递增 1 并将结果存储在同一变量中。语法为 a++,用法包括循环和计数器。它可与后置递增运算符 ++a 交换使用,后者在表达式求值后递...
      99+
      2024-05-14
      c++
    • c++中a.b什么意思
      c++kquote>“a.b”表示对象“a”的成员“b”,用于访问对象成员,可用“对象名.成员名”的语法。它还可以用于访问嵌套成员,如“对象名.嵌套成员名.成员名”的语法。 c++...
      99+
      2024-05-14
      c++
    • C++ 并发编程库的优缺点
      c++++ 提供了多种并发编程库,满足不同场景下的需求。线程库 (std::thread) 易于使用但开销大;异步库 (std::async) 可异步执行任务,但 api 复杂;协程库 ...
      99+
      2024-05-14
      c++ 并发编程
    • 如何在 Golang 中备份数据库?
      在 golang 中备份数据库对于保护数据至关重要。可以使用标准库中的 database/sql 包,或第三方包如 github.com/go-sql-driver/mysql。具体步骤...
      99+
      2024-05-14
      golang 数据库备份 mysql git 标准库
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作