整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Vue 3 進階用法:Provide / Inject 機制

          、屬性下鉆

          屬性可用于父組件向子組件傳遞參數,但僅限于相鄰父子組件。如果一個組件要給它的子組件的子組件(即孫組件)傳遞參數,不得不拆成兩個步驟:先傳給它的兒子,再由兒子傳給孫子。

          祖孫三代之間的屬性透傳

          盡管可以實現目的,但是中間層組件需要定義自身用不到的屬性。如果嵌套層級更深,需要傳遞的屬性更多,可以想象,這條鏈路的每個中間層組件都會變得不幸。這種為了透傳而聲明屬性造成的不幸,Vue 叫它屬性下鉆(Prop Drilling)。

          二、Provide 和 Inject

          為了解決屬性下鉆的問題,Vue 提供了 Provide/Inject 解決方案。這個方案定義了兩個角色:ProviderInjector,Provider 是數據的提供方,Injector 是數據的消費方。

          Provider 通過 provide(key, data) 把數據存放在特定區域,Injector 通過 inject(key) 從特定區域獲取數據。其中的 key 用于區分不同用途的數據。

          數據的提供和獲取

          這套機制跟智能取餐柜有些類似。送餐員是食物(數據)的 Provider,你是食物的 Injector,而 key 是取餐柜號。送餐員通過 provide(key, food) 把食物放到特定柜子,你通過 inject(key) 從正確的柜子取走食物并消費它。

          和取餐柜不同的是,一個 Provider 可以對應多個 Injector。即父組件提供一條數據后,可以被子子孫孫組件反復消費。

          provide() 函數的兩個參數,第一個參數叫注入鍵(injection key),類型可以是字符串或 Symbol。第二個參數是注入的數據,可以是任意類型,包括響應式數據。

          使用 provide 和 inject 傳遞數據

          渲染效果:

          使用 provide 和 inject 的渲染結果

          三、同名覆蓋

          在一個層級較深的組件樹中,如果出現多個 Provider 組件,且提供的 key 是相同的,最終 Injector 取到的數據是怎樣的?

          Injector 永遠獲取離它最近的祖先組件提供的數據,再往上的數據會被同名覆蓋。用代碼驗證一下:

          同名覆蓋

          渲染效果:

          同名覆蓋的渲染結果

          如果你在開發一個很大的應用,為了防止同名覆蓋,可以在 provide() 中使用 Symbol 類型代替字符串。

          四、最頂級的 Provider

          在 Vue 3 中,最頂級的 Provider 是 app。通過 app.provide(key, value) 提供數據。數據的消費方法沒有什么不同。

          頂級 Provider

          頂級 Provider 的渲染結果

          五、Inject 默認值

          如果子組件通過 inject(key) 消費了一個 key,但是所有的上級組件都沒提供數據,會讓 Vue 惱火,并發出警告信息。

          上游沒有提供數據,但下游用了

          沒有注入數據的渲染結果

          為了平息 Vue 的警告信息,可以在子組件使用 inject() 時,傳入第二個參數當作默認值。

          使用默認值

          這樣,當所有上級都不提供數據時,子組件就會啟用默認值。

          正常顯示默認值

          有的時候,默認值需要調用工廠函數計算才能獲得。此時,函數本身不是默認值,函數的返回值才是默認值,需要將 inject() 第三個參數設為 true,表示第二個參數的特殊作用。

          標記默認的工廠函數

          六、處理響應式數據

          如果提供的數據是響應式數據,建議把響應式數據變更數據的方法放在一個地方,打包一并提供給下游。誰聲明誰治理,這樣職責比較清晰。

          響應式數據的聲明和變更在一個地方

          渲染結果:

          響應式數據的渲染結果

          對于某些重要數據,如果上游組件不希望下游組件改動,可以先用 readonly() 方法保護好,然后再打包發送給下游。

          設定為只讀數據

          下游修改只讀數據時,Vue 不僅會阻止操作,還會發出警告:

          修改只讀數據時的警告信息

          參考資料

          • Provide / Inject,https://vuejs.org/guide/components/provide-inject.html

          rovide 和 inject 主要在開發高階插件/組件庫時使用。并不推薦用于普通應用程序代碼中。
          這對選項需要一起使用,以允許一個祖先組件向其所有子孫后代注入一個依賴,不論組件層次有多深,并在起上下游關系成立的時間里始終生效。

          provide 選項應該是一個對象或返回一個對象的函數。該對象包含可注入其子孫的 property。在該對象中你可以使用 ES2015 Symbols 作為 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的環境下可工作。

          一、簡單示例

          向子組件注入數據

          <!DOCTYPE html>
          <html lang="en">
          
          <head>
              <meta charset="UTF-8">
              <title>provide / inject</title>
              <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
          </head>
          
          <body>
              <div id="js_app">
                  <children></children>
              </div>
              <script>
              var Children = {
                  inject: ['list'],
                  template: '<ul><li v-for="(v,i) in list" :key="i">姓名:{{ v.name }} 分數:{{ v.score }}</li></ul>'
              };
              var app = new Vue({
                  el: '#js_app',
                  provide: {
                      list: [
                          { name: 'tom', score: 88 },
                          { name: 'jack', score: 75 },
                          { name: 'rose', score: 96 }
                      ]
                  },
                  components: {
                      children: Children
                  }
              });
              </script>
          </body>
          
          </html>

          二、配合Symbol使用

          var symbol = Symbol();
          var Children = {
              inject: { // 這里是一個對象,自定義key指定值
                  list: symbol
              },
              template: '<ul><li v-for="(v,i) in list" :key="i">姓名:{{ v.name }} 分數:{{ v.score }}</li></ul>'
          };
          var app = new Vue({
              el: '#js_app',
              provide: function() { // 這里是一個函數,返回一個對象
                  return {
                      [symbol]: [
                          { name: 'tom', score: 88 },
                          { name: 'jack', score: 75 },
                          { name: 'rose', score: 96 }
                      ]
                  };
              },
              components: {
                  children: Children
              }
          });

          三、使用默認值

          var Children = {
              inject: {
                  list: {
                      from: 'list',
                      default: function() {
                          return [
                              { name: 'tom', score: 88 },
                              { name: 'jack', score: 75 },
                              { name: 'rose', score: 96 }
                          ];
                      }
                  }
              },
              template: '<ul><li v-for="(v,i) in list" :key="i">姓名:{{ v.name }} 分數:{{ v.score }}</li></ul>'
          };
          var app = new Vue({
              el: '#js_app',
              components: {
                  children: Children
              }
          });

          四、配合props使用

          瀏覽器開發者工具在爬蟲中常用來進行簡單的抓包分析、JS逆向調試,打開方式:

          1. F12;
          2. 快捷鍵 Ctrl+Shift+I;
          3. 鼠標右鍵檢查或者審查元素;
          4. 瀏覽器右上角 —> 更多工具 —> 開發者工具

          常見禁用開發者工具手段:https://blog.csdn.net/cplvfx/article/details/108518077

          官方文檔:https://developer.chrome.com/docs/devtools/

          • Elements(元素面板):使用“元素”面板可以通過自由操縱 DOM 和 CSS 來重您網站的布局和設計。
          • Console(控制臺面板):在開發期間,可以使用控制臺面板記錄診斷信息,或者使用它作為 shell,在頁面上與 JavaScript 交互。
          • Sources(源代碼面板):在源代碼面板中設置斷點來調試 JavaScript ,或者通過 Workspaces(工作區)連接本地文件來使用開發者工具的實時編輯器。
          • Network(網絡面板):從發起網頁頁面請求 Request 后得到的各個請求資源信息(包括狀態、資源類型、大小、所用時間等),并可以根據這個進行網絡性能優化。
          • Performance(性能面板):使用時間軸面板,可以通過記錄和查看網站生命周期內發生的各種事件來提高頁面運行時的性能。
          • Memory(內存面板):分析 web 應用或者頁面的執行時間以及內存使用情況。
          • Application(應用面板):記錄網站加載的所有資源信息,包括存儲數據(Local Storage、Session Storage、IndexedDB、Web SQL、Cookies)、緩存數據、字體、圖片、腳本、樣式表等。
          • Security(安全面板):使用安全面板調試混合內容問題,證書問題等等。
          • Lighthouse(診斷面板):對當前網頁進行網絡利用情況、網頁性能方面的診斷,并給出一些優化建議。


          元素選擇

          可以直接點擊頁面的元素,會自動跳轉到對應的源代碼。

          終端模擬

          模擬各種終端設備,支持自定義終端。

          設置

          開發者工具設置,包括一些外觀、快捷置、終端設備、地理位置設置等。

          自定義

          自定義和控制開發者工具,包括調整工具的位置、全局搜索、運行命令、其他工具等。

          終端模擬

          終端模擬

          可以模擬各種終端設備,適合查看手機頁面的數據,點擊【More tools】—> 【Sensors】可以模擬終端的地理位置、終端朝向等;工具欄可以選擇要模擬的終端型號,其中 Responsive 是自適應。

          Network 面板

          Controls 控制器

          • Preserve log:是否在頁面重加載后,清除請求列表。
          • Disable cache:是否啟用緩存。

          是否開啟抓包

          清除請求

          是否隱藏 Filter(過濾器)窗格

          搜索

          Network conditions,網絡條件,允許在各種網絡環境中測試網站,包括 3G,離線等,還可以自定義限制最大下載和上傳流量。

          Import/Export HAR file,導入導出抓包數據。

          Filter 過濾器

          • Hide data URLs:data URLs 指一些嵌入到文檔中的小型文件,在請求表里面以 data: 開頭的文件就是,如較為常見的 svg 文件。勾選 Hide data URLs復選框即可隱藏此類文件。
          • All:顯示所有請求。
          • XHR:全稱 XMLHttpRequest,是一種創建 AJAX 請求的 JavaScript API,通常抓取 Ajax 請求可以選擇 XHR。
          • WS:全稱 WebSocket,是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協議。
          • Manifest 安卓開發文件名,屬于 AndroidManifest.xml 文件,在簡單的 Android 系統的應用中提出了重要的信息碼。
          • Has blocked cookies:僅顯示具有阻止響應 cookie 的請求。
          • Blocked Requests:只顯示被阻止的請求。

          斷點調試

          常規斷點調試

          適用于分析關鍵函數代碼邏輯

          1. Ctrl+Shift+F 或者右上角三個點打開全局搜索,搜索關鍵字。
          2. 定位到可疑代碼,點擊行號埋下斷點。
          3. 調試代碼,分析邏輯,其中 console 模板可以直接編寫 JS 代碼進行調試。

          各個選項功能:

          執行到下一個斷點

          執行下一步,不會進入所調用的函數內部

          進入所調用的函數內部

          跳出函數內部

          一步步執行代碼,遇到有函數調用,則進入函數

          停用斷點

          不要在出現異常時暫停。

          • Breakpoints:可以看到已經埋下的斷點。
          • Scope:可以看到當前局部或者全局變量的值,可對值進行修改。
          • Call Stack:可以看到當前代碼調用的堆棧信息,代碼執行順序為由下至上。

          XHR 斷點

          匹配 url 中關鍵詞,匹配到則跳轉到參數生成處,適用 于url 中的加密參數全局搜索搜不到,可采用這種方式攔截。

          行為斷點

          Event Listener Breakpoints,事件偵聽器斷點,當鼠標點擊、移動、鍵盤按鍵等行為或者其他事件發生時可以觸發斷點,比如 Mouse —> click,可快速定位點擊按鈕后,所執行的 JS。

          插入 JS

          在 sources —> snippets 下可以新建 JS 腳本。

          打印 windows 對象的值

          在 console 中輸入如下代碼,如只打印 `_$` 開頭的變量值:

          for (var p in window) {
              if (p.substr(0, 2) !== "_$") 
                  continue;
              console.log(p + " >>> " + eval(p))
          }

          無限 debugger 防調試

          某些頁面打開調試工具會出現無限 debugger 的現象:

          中間人攔截替換無限 debug 函數

          查看調用棧,點擊第二行跳轉到原函數:

          可以看到 _0x2ba9bc[_0x20b2('0x79')]_0x2ba9bc[_0x20b2('0x7a')] 分別對應 debu 和 gger,連起來就是 debugger,在本地重寫這個 JS,直接將這兩個值置空:

          使用插件 ReRes,編寫規則,遇到此 JS,就替換成我們本地經過修改過的 JS,替換后無限 debugger 就不存在了:

          方法置空

          直接在 Console 中將無限 debugger 的函數重寫置空也可以破解無限 debugger,缺點是刷新后失效。

          解除定時器

          適用于定時器類觸發的 debug:

          for (var i = 1; i < 99999; i++)window.clearInterval(i);

          Hook 鉤子

          鉤子英文 Hook,在 windows 系統中,所有的都是消息,按了一下鍵盤,就是一個消息,Hook 的意思就是勾住,在消息過去之前先把消息勾住,不讓其執行,然后自己優先處理。也就是這個技術提供了一個入口,能夠針對不同的消息或者 api 在執行前,先執行我的操作?!拔业牟僮鳌本褪倾^子函數。在開發者工具中以 chrome 插件的方式,在匹配到關鍵詞處插入斷點。

          創建一個文件夾,文件夾中創建一個鉤子函數文件 inject.js 以及插件的配置文件 manifest.json :

          打開 chrome 的擴展程序, 打開開發者模式,加載已解壓的擴展程序,選擇創建的文件夾即可:

          配置文件 manifest.json

          以一個 header 鉤子為例,其配置文件如下:

          {
             "name": "Injection",
              "version": "1.0",
              "description": "RequestHeader鉤子",
              "manifest_version": 1,
              "content_scripts": [
                  {
                      "matches": [
                          "<all_urls>"
                      ],
                      "js": [
                          "inject.js"
                      ],
                      "all_frames": true,
                      "permissions": [
                          "tabs"
                      ],
                      "run_at": "document_start"
                  }
              ]
          }

          header 鉤子

          header 鉤子用于定位 header 中關鍵參數生成位置,以下代碼演示了當 header 中包含 `Authorization` 時,則插入斷點

          var code = function(){
          var org = window.XMLHttpRequest.prototype.setRequestHeader;
          window.XMLHttpRequest.prototype.setRequestHeader = function(key,value){
              if(key=='Authorization'){
                  debugger;
              }
              return org.apply(this,arguments);
          }
          }
          var script = document.createElement('script');
          script.textContent = '(' + code + ')()';
          (document.head||document.documentElement).appendChild(script);
          script.parentNode.removeChild(script);

          cookie 鉤子

          cookie 鉤子用于定位 cookie 中關鍵參數生成位置,以下代碼演示了當 cookie 中匹配到了 `abcdefghijk`, 則插入斷點:

          var code = function(){
              var org = document.cookie.__lookupSetter__('cookie');
              document.__defineSetter__("cookie",function(cookie){
                  if(cookie.indexOf('abcdefghijk')>-1){
                      debugger;
                  }
                  org = cookie;
              });
              document.__defineGetter__("cookie",function(){return org;});
          }
          var script = document.createElement('script');
          script.textContent = '(' + code + ')()';
          (document.head||document.documentElement).appendChild(script);
          script.parentNode.removeChild(script);

          請求鉤子

          請求鉤子用于定位請求中關鍵參數生成位置,以下代碼演示了當請求的 url 里包含 `AbCdE` 時,則插入斷點:


          主站蜘蛛池模板: 国产成人无码一区二区三区在线 | 国产一区二区三区免费视频| 国产拳头交一区二区| 精品人妻一区二区三区毛片| 伊人无码精品久久一区二区| 久久亚洲一区二区| 国产午夜精品一区二区三区不卡| 成人在线观看一区| 国产精品香蕉在线一区| 在线视频一区二区| 无码精品人妻一区二区三区人妻斩| 免费观看日本污污ww网站一区| 亚州AV综合色区无码一区| 激情亚洲一区国产精品| 在线观看亚洲一区二区| 色偷偷av一区二区三区| 国产成人久久精品一区二区三区| 久久无码人妻精品一区二区三区| 日韩少妇无码一区二区三区| 国产乱码精品一区三上| 福利视频一区二区牛牛 | 无码精品人妻一区二区三区人妻斩| 精品亚洲一区二区三区在线观看| 日本一区二区三区精品国产 | 国产精品久久一区二区三区| 亚洲一区中文字幕久久| 日韩精品一区二区三区色欲AV| 国产成人精品一区二区三区无码 | 日本内射精品一区二区视频| 亚洲国产精品一区| 色噜噜狠狠一区二区| 无码国产精品一区二区免费I6| 亚洲av成人一区二区三区观看在线| 男插女高潮一区二区| 久久中文字幕无码一区二区| 国产精品成人一区无码| 一区二区精品在线观看| 蜜桃传媒视频麻豆第一区| 亚洲天堂一区在线| 国产一区美女视频| 亚洲永久无码3D动漫一区|