最近在項目裏接手別人的代碼來作完善,其中一個是修復獲取不到MAC地址的bug,仔細看了下代碼,發現須要用到Activex控件。html
上一位同事在寫的時候把<object></object>寫在index.html文件中,獲取mac地址的js代碼也寫在了index.html中,讀取完以後保存在localStorage裏面,可是這裏有個問題,這個Activex控件獲取mac地址是一個異步操做,若是第一次獲取mac地址而且緩存沒有mac地址的信息,一定會報錯。vue
此次修改的關鍵點就是如何將這個異步操做變成同步操做,或者當控件獲取到mac以後傳播到組件裏,組件再作相對應的動做。vuex
因此,演變成index.html文件的數據如何跟組件通訊。segmentfault
既然找到關鍵點,那麼就來解決問題吧!緩存
咱們都知道vue組件裏通訊有幾個辦法:異步
子 -> 父組件通訊:子組件$emit,父組件$on;函數
父 -> 子組件通訊:子組件定義props,父組件使用子組件時經過props向子組件傳值;this
兄弟組件或者平行組件:定義一個eventBus,引入eventBus,經過eventBus的$on和$emit來通訊;spa
若是項目比較大,推薦使用vuex來通訊。.net
上面的方法,在index.html中貌似都用不上...除非將它們綁在window對象上...
因此變通一下,
window.eventBus = new Vue();
接下來咱們在index.html中的script標籤打印下eventBus:
很好,能打印出來就行。
<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 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>
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 } }
<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...