vue項目中,index.html數據與組件之間通信,傳值,以獲取MAC地址爲例

最近在項目裏接手別人的代碼來做完善,其中一個是修復獲取不到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...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章