中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JS監聽變量改變如何實現

發布時間:2023-04-15 11:12:01 來源:億速云 閱讀:192 作者:iii 欄目:開發技術

這篇文章主要介紹“JS監聽變量改變如何實現”,在日常操作中,相信很多人在JS監聽變量改變如何實現問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JS監聽變量改變如何實現”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

    需求和背景

    在業務中,由于項目采用微前端架構,需要通過A應用的某個值的變化對B應用中的DOM進行改變(如彈出一個Modal),第一個想到的可能是發布訂閱模式,其實不如將問題縮小化,采用原生的能力去解決。

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

    • ES5 的 Object.defineProperty

    • ES6 的 Proxy

    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: sorrycc
    console.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: 1
    data.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 = 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中的實踐

    這里展示兩段偽代碼,大概業務流程是,當點擊頁面某個按鈕(打開/關閉彈窗),觸發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: 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

    到此,關于“JS監聽變量改變如何實現”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    js
    AI

    金门县| 十堰市| 德格县| 呼玛县| 汉源县| 昭觉县| 揭阳市| 昌吉市| 博湖县| 田林县| 噶尔县| 秦皇岛市| 云和县| 巨野县| 霍邱县| 台州市| 阿荣旗| 兰西县| 谢通门县| 凯里市| 达州市| 北宁市| 阿坝| 巴林右旗| 广饶县| 灌阳县| 镶黄旗| 永修县| 柳州市| 民和| 抚松县| 随州市| 四会市| 东平县| 西峡县| 达拉特旗| 青冈县| 民乐县| 资中县| 龙泉市| 贡觉县|