最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS監(jiān)聽一個(gè)變量改變的兩種方法

 更新時(shí)間:2023年11月14日 11:37:24   作者:sorryhc  
在業(yè)務(wù)中,由于項(xiàng)目采用微前端架構(gòu),需要通過A應(yīng)用的某個(gè)值的變化對(duì)B應(yīng)用中的DOM進(jìn)行改變(如彈出一個(gè)Modal),第一個(gè)想到的可能是發(fā)布訂閱模式,其實(shí)不如將問題縮小化,采用原生的能力去解決,本文介紹了兩種方法來使用JS監(jiān)聽一個(gè)變量改變,需要的朋友可以參考下

需求和背景

在業(yè)務(wù)中,由于項(xiàng)目采用微前端架構(gòu),需要通過A應(yīng)用的某個(gè)值的變化對(duì)B應(yīng)用中的DOM進(jìn)行改變(如彈出一個(gè)Modal),第一個(gè)想到的可能是發(fā)布訂閱模式,其實(shí)不如將問題縮小化,采用原生的能力去解決。

下面給出兩種解決方案,同時(shí)也是尤大寫Vue時(shí)的思路

  • ES5 的 Object.defineProperty
  • ES6 的 Proxy

Object.defineProperty

Object.defineProperty() 方法會(huì)直接在一個(gè)對(duì)象上定義一個(gè)新屬性,或者修改一個(gè)對(duì)象的現(xiàn)有屬性,并返回此對(duì)象

——MDN

用法如下:

Object.defineProperty(obj, prop, option)

入?yún)⒂梅ǎ?/h3>
  • obj:代理對(duì)象;
  • prop:代理對(duì)象中的key;
  • option:配置對(duì)象,get、set都在其中配置;

例子:

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: sorrycc
console.log(obj.name) // get: sorrycc

對(duì)一個(gè)對(duì)象進(jìn)行整體響應(yīng)式監(jiān)聽:

// 監(jiān)視對(duì)象
function observe(obj) {
  // 遍歷對(duì)象,使用 get/set 重新定義對(duì)象的每個(gè)屬性值
   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
       },
       // 重新設(shè)置值時(shí),觸發(fā)收集器的通知機(jī)制
       set: function reactiveSetter(newV) {
           console.log('set: ' + newV)
           v = newV
       },
   })
}

let data = {a: 1}
// 監(jiān)視對(duì)象
observe(data)
data.a // get: 1
data.a = 2 // set: 2

整體思路就是遇到子對(duì)象就遞歸,和深拷貝一樣的讀參順序。

缺陷

如果學(xué)習(xí)過Vue2源碼的同學(xué)可能比較熟,基于下面的缺陷,也是出現(xiàn)了$set、$get的用法。

  • IE8 及更低版本 IE 是不支持的
  • 無法檢測(cè)到對(duì)象屬性的新增或刪除
  • 如果修改數(shù)組的 length ( Object.defineProperty 不能監(jiān)聽數(shù)組的長度),以及數(shù)組的 push 等變異方法是無法觸發(fā) setter 的

Proxy

Proxy 對(duì)象用于創(chuàng)建一個(gè)對(duì)象的代理,從而實(shí)現(xiàn)基本操作的攔截和自定義(如屬性查找、賦值、枚舉、函數(shù)調(diào)用等)

— MDN

const obj = new Proxy(target, handler)

其中:

  • target :要使用 Proxy 包裝的目標(biāo)對(duì)象(可以是任何類型的對(duì)象,包括原生數(shù)組,函數(shù),甚至另一個(gè)代理)
  • handler :一個(gè)通常以函數(shù)作為屬性的對(duì)象,各屬性中的函數(shù)分別定義了在執(zhí)行各種操作時(shí)代理 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 = sorryhc

console.log(user.name) // sorryhc
console.log(user.age) // no prop!

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

  • getPrototypeOf / setPrototypeOf

  • isExtensible / preventExtensions

  • ownKeys / getOwnPropertyDescriptor

  • defineProperty / deleteProperty

  • get / set / has

  • apply / construct

感興趣的可以查看 MDN ,一一嘗試一下,這里不再贅述

在React中的實(shí)踐

這里展示兩段偽代碼,大概業(yè)務(wù)流程是,當(dāng)點(diǎn)擊頁面某個(gè)按鈕(打開/關(guān)閉彈窗),觸發(fā)window.obj.showModal的切換,從而被監(jiān)聽到全局變量的變化,從而改變React中的state狀態(tài),最終觸發(fā)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: true
console.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 = true

console.log(window.obj.showModal) // true

總結(jié)

Proxy 相比于 defineProperty 的優(yōu)勢(shì):

  • 基于 ProxyReflect ,可以原生監(jiān)聽數(shù)組,可以監(jiān)聽對(duì)象屬性的添加和刪除
  • 不需要深度遍歷監(jiān)聽:判斷當(dāng)前 Reflect.get 的返回值是否為 Object ,如果是則再通過 reactive 方法做代理, 這樣就實(shí)現(xiàn)了深度觀測(cè)
  • 只在 getter 時(shí)才對(duì)對(duì)象的下一層進(jìn)行劫持(優(yōu)化了性能)

Proxy除了兼容性不足以外,其他方面的表示都優(yōu)于Object.defineProperty

所以,建議使用 Proxy 監(jiān)測(cè)變量變化

以上就是JS監(jiān)聽一個(gè)變量改變的兩種方法的詳細(xì)內(nèi)容,更多關(guān)于JS監(jiān)聽變量改變的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JS旋轉(zhuǎn)實(shí)現(xiàn)轉(zhuǎn)盤抽獎(jiǎng)效果

    JS旋轉(zhuǎn)實(shí)現(xiàn)轉(zhuǎn)盤抽獎(jiǎng)效果

    這篇文章主要為大家詳細(xì)介紹了JS旋轉(zhuǎn)實(shí)現(xiàn)轉(zhuǎn)盤抽獎(jiǎng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • js實(shí)現(xiàn)固定顯示區(qū)域內(nèi)自動(dòng)縮放圖片的方法

    js實(shí)現(xiàn)固定顯示區(qū)域內(nèi)自動(dòng)縮放圖片的方法

    這篇文章主要介紹了js實(shí)現(xiàn)固定顯示區(qū)域內(nèi)自動(dòng)縮放圖片的方法,實(shí)例分析了javascript操作頁面元素及屬性的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 用js模擬struts2的多action調(diào)用示例

    用js模擬struts2的多action調(diào)用示例

    這篇文章主要介紹了用js模擬struts2的多action調(diào)用的實(shí)現(xiàn)過程,需要的朋友可以參考下
    2014-05-05
  • JavaScript 是什么意思

    JavaScript 是什么意思

    javascript一種由Netscape的LiveScript發(fā)展而來的腳本語言,它提高與Java的兼容性。JavaScript采用HTML頁作為其接口。很多朋友問js是什么意思?下面小編通過分享本教程給大家解答下,感興趣的朋友參考下
    2016-09-09
  • 一文徹底解讀前端深淺拷貝的理解和幾種使用方法

    一文徹底解讀前端深淺拷貝的理解和幾種使用方法

    在前端面試當(dāng)中,經(jīng)常會(huì)被問到淺拷貝與深拷貝的問題,這主要是考察面試者對(duì)基本數(shù)據(jù)類型和引用數(shù)據(jù)類型的理解,這篇文章主要介紹了前端深淺拷貝理解和幾種使用方法的相關(guān)資料,需要的朋友可以參考下
    2026-02-02
  • JavaScript中判斷變量是否存在的四種常用方法整理

    JavaScript中判斷變量是否存在的四種常用方法整理

    在Javascript中我們通常判斷一個(gè)變量是否存在,即不為null或者undefined,這篇文章主要給大家介紹了關(guān)于JavaScript中判斷變量是否存在的四種常用方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • js獲取本日、本周、本月的時(shí)間代碼

    js獲取本日、本周、本月的時(shí)間代碼

    本篇文章給大家分享的內(nèi)容是利用js如何獲取本日、本周、本月的時(shí)間代碼,有一定的參考價(jià)值,有需要的朋友可以參考一下
    2020-02-02
  • UniApp開發(fā)H5接入微信登錄的全過程

    UniApp開發(fā)H5接入微信登錄的全過程

    uni-app是一個(gè)使用Vue.js開發(fā)跨平臺(tái)應(yīng)用的前端框架,下面這篇文章主要給大家介紹了關(guān)于UniApp開發(fā)H5接入微信登錄的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • javascript實(shí)現(xiàn)一個(gè)網(wǎng)頁加載進(jìn)度loading

    javascript實(shí)現(xiàn)一個(gè)網(wǎng)頁加載進(jìn)度loading

    本篇文章主要介紹了javascript實(shí)現(xiàn)一個(gè)頁面加載進(jìn)度loading的具體步驟以及示例代碼,具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2017-01-01
  • 全面解析Bootstrap排版使用方法(標(biāo)題)

    全面解析Bootstrap排版使用方法(標(biāo)題)

    這篇文章全面解析了Bootstrap排版使用方法,本文重點(diǎn)介紹Bootstrap標(biāo)題排版,感興趣的小伙伴們可以參考一下
    2015-11-11

最新評(píng)論

文山县| 彩票| 远安县| 大厂| 夹江县| 射阳县| 普安县| 满洲里市| 酒泉市| 阳江市| 呼伦贝尔市| 三门县| 贵州省| 博乐市| 河东区| 曲阜市| 宝鸡市| 光泽县| 揭西县| 龙门县| 揭阳市| 桐柏县| 米林县| 门头沟区| 翁牛特旗| 健康| 曲周县| 中阳县| 泽州县| 海淀区| 依安县| 尚志市| 双鸭山市| 丰镇市| 巴塘县| 武宁县| 昌图县| 温州市| 蒲城县| 海口市| 定兴县|