最近在项目里接手别人的代码来做完善,其中一个是修复获取不到MAC地址的bug,仔细看了下代码,发现需要用到Activex控件。
上一位同事在写的时候把<object></object>写在index.html文件中,获取mac地址的js代码也写在了index.html中,读取完之后保存在localStorage里面,但是这里有个问题,这个Activex控件获取mac地址是一个异步操作,如果第一次获取mac地址并且缓存没有mac地址的信息,必定会报错。
这次修改的关键点就是如何将这个异步操作变成同步操作,或者当控件获取到mac之后传播到组件里,组件再做相对应的动作。
所以,演变成index.html文件的数据如何跟组件通信。
既然找到关键点,那么就来解决问题吧!
我们都知道vue组件里通信有几个办法:
子 -> 父组件通信:子组件$emit,父组件$on;
父 -> 子组件通信:子组件定义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...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。