vue專案中,index.html資料與元件之間通訊,傳值,以獲取MAC地址為例

SheldonLee發表於2019-04-28

最近在專案裡接手別人的程式碼來做完善,其中一個是修復獲取不到MAC地址的bug,仔細看了下程式碼,發現需要用到Activex控制元件。

上一位同事在寫的時候把<object></object>寫在index.html檔案中,獲取mac地址的js程式碼也寫在了index.html中,讀取完之後儲存在localStorage裡面,但是這裡有個問題,這個Activex控制元件獲取mac地址是一個非同步操作,如果第一次獲取mac地址並且快取沒有mac地址的資訊,必定會報錯。

這次修改的關鍵點就是如何將這個非同步操作變成同步操作,或者當控制元件獲取到mac之後傳播到元件裡,元件再做相對應的動作。

所以,演變成index.html檔案的資料如何跟元件通訊。

既然找到關鍵點,那麼就來解決問題吧!

我們都知道vue元件裡通訊有幾個辦法:

子 -> 父元件通訊:子元件$on,父元件$emit;

父 -> 子元件通訊:子元件定義props,父元件使用子元件時通過props向子元件傳值;

兄弟元件或者平行元件:定義一個eventBus,引入eventBus,通過eventBus的$on和$emit來通訊;

如果專案比較大,推薦使用vuex來通訊。

上面的方法,在index.html中貌似都用不上...除非將它們綁在window物件上...

所以變通一下,

在main.js檔案中:

window.eventBus = new Vue();

接下來我們在index.html中的script標籤列印下eventBus:
圖片描述

很好,能列印出來就行。

index.html檔案,在body標籤裡插入:

<object classid="CLSID:76A64158-CB41-11D1-8B02-00600806D9B6" id="locator" style="display:none;visibility:hidden"></object>
<object classid="CLSID:75718C9A-F029-11d1-A1AC-00C04FB6C223" id="foo" style="display:none;visibility:hidden"></object>

script程式碼:

<script FOR="foo" EVENT="OnObjectReady(objObject,objAsyncContext)" LANGUAGE="JScript">
  var IPEnabled = objObject.IPEnabled;
  var IPAddress = objObject.IPAddress(0);
  if (IPEnabled != null && IPEnabled != "undefined" && IPEnabled == true ) {
    if (IPAddress) {
      window.sIPAddr = objObject.IPAddress(0);
    }
    if (objObject.MACAddress) {
      window.sMacAddr = objObject.MACAddress;
    }
    if (objObject.DNSHostName) {
      window.sDNSName = objObject.DNSHostName;
    }
  }
</script>
<script FOR="foo" EVENT="OnCompleted(hResult,pErrorObject, pAsyncContext)" LANGUAGE="JScript">
  // console.log("獲取mac地址成功:", sMacAddr);
  window.eventBus.$emit('getMac', window.sMacAddr);
</script>

vue元件裡的方法:

clickPort() {
  var userAgent = navigator.userAgent;
  if (userAgent.indexOf(".NET") > -1 && userAgent.indexOf("NT 10.0") > -1) {
    var service = locator.ConnectServer(); // eslint-disable-line
    service.Security_.ImpersonationLevel = 3;
    service.InstancesOfAsync(foo, "Win32_NetworkAdapterConfiguration"); // eslint-disable-line
  }
  eventBus.$off('getMac'); // 關閉上一次的監聽
  eventBus.$on('getMac', (_mac) => {
    alert(`獲取MAC地址:${_mac}`);
    this.msg = _mac;
  });
}

ok,來執行一把:

圖片描述

成功!

以上是第一種方法,利用的是eventBus,記住在使用eventBus的時候,記得關閉上一次的監聽

下面是第二種方法:

怎麼在index.html中給元件賦值呢?或者說怎麼呼叫元件裡的方法呢?

利用同樣的原理,將this繫結到window上就可以了。

上程式碼,

元件:

clickPort() {
  var userAgent = navigator.userAgent;
  window.thisComponent = this; // 將元件例項賦予一個全域性變數
  if (userAgent.indexOf(".NET") > -1 && userAgent.indexOf("NT 10.0") > -1) {
    var service = locator.ConnectServer(); // eslint-disable-line
    service.Security_.ImpersonationLevel = 3;
    service.InstancesOfAsync(foo, "Win32_NetworkAdapterConfiguration"); // eslint-disable-line
  }
}

index.html:

<script FOR="foo" EVENT="OnCompleted(hResult,pErrorObject, pAsyncContext)" LANGUAGE="JScript">
  // 先判斷是否存在window.thisComponent.componentThis為vue元件例項
  if (window.thisComponent) {
    // 將mac地址賦予例項的一個屬性
    window.thisComponent.sMacAddr = window.sMacAddr;
    // 致空,以免造成記憶體洩露;
    window.thisComponent = null;
    // console.log(window.componentThis);
  }
</script>

執行一把:

圖片描述

沒毛病,並且直接在模板裡展示出來;

使用第二種方法,需要在元件的data函式中初始化sMacAddr欄位,否則不會在模板中展示出來,並且在index.html檔案中window.thisComponent.sMacAddr,這裡的sMacAddr欄位必須跟元件裡初始化的欄位一致

總結:

在這無論用哪個方法,都得利用到window這個物件;這個也是沒辦法的事,其實利用同樣的道理,也是直接繫結在VUE的例項上;
條條大路通羅馬,小弟獻上一點技巧。

文章參考:https://blog.csdn.net/zyw_anq...

歡迎轉載,轉載請注出處!https://segmentfault.com/a/11...

相關文章