背景
在使用组内架构的Vue框架,开发交付助手web端的过程中,发现了组内框架存在着一些问题,在查阅资料以及实践之后,找到了解决方案
问题一
发现从老框架照搬过来的方法在vue下可能有些水土不服,比如下面这个调用协议,执行success
或者error
回调的方法,
oWebsdk.WSDK_GetDeviceConfig(null, "getToolUsage", option, {
success: function(status, data, xhr) {
console.log(option);
},
error: function(status, data, xhr) {
console.log(this);
}
回调这里的this
实质上指向的是经过层层封装之后发给ajax
的对象,而不是指向vue
实例的this
,如下图所示:
所以如果定义这种回调函数结构,那么我们必须要在每个涉及到调用协议的函数里定义let self=this
,来把指向vue
实例的this
保存下来使用,非常繁琐并会引起混淆。如下:
confirm() {
let self = this;
self.bVisible = false;
"len" === self.szCurrentOperate
? self.restoreLensOk()
: self.restorePlanOk();
},
解决方案
可能在组内老框架angular
下,不支持es6的箭头函数的情况下,写一写let self=this
就这么过去了,但是在vue下这么写,不仅繁琐,而且最重要的是vue
下的this
指向的是vue
实例,会引起混淆,造成难以发现的BUG。故对于调用协议的方法,可执行以下修改:
oWebsdk.WSDK_GetDeviceConfig(
null,
"getToolUsage",
{ type: "day" },
{
success: (status, data, xhr)=> {
this.newDownloads = oUtils.numFormat(data.newDownloads);
this.totalDownloads = oUtils.numFormat(data.totalDownloads);
this.userCount = oUtils.numFormat(data.userCount);
},
error: (status, data, xhr)=> {
console.log(this);
}
}
);
在不改动上层ajax请求封装函数的情况下,我们可以使用es6的箭头函数,让调用协议的success
或者error
回调方法里的this
固定指向全局作用域,即vue
实例,那么这个项目就不用let self=this
这种写法了。
问题二
在选择多语言的方法里,发现用for..in
遍历数组,以及运用如下:
selectLanguage(szLanguage) {
for (let i in this.aLanguageList) {
if (this.aLanguageList[i].value === szLanguage) {
this.szCurrentLanguage = this.$i18n.locale = this.aLanguageList[i].value;
// 保存后,下次刷新将会默认之前选择的语言
oWebSession.setItem("currentLanguage", this.aLanguageList[i].value);
break;//跳出循环
}
}
以及出现了js的连续赋值写法,
this.szCurrentLanguage = this.$i18n.locale = this.aLanguageList[i].value;
解决方案
1.不论在es5及之前抑或是es6的语言规范,都不推荐用for..in
遍历数组,因为会遍历到原型链上的属性影响获取值。
推荐使用map
foreach
,以及es6的for...of
2.不推荐写js的连续赋值写法,可能会造成很难发现的BUG,并且阅读困难,不易维护
将上述代码使用es6的for...of
改写为如下代码即可:
selectLanguage(szLanguage) {
for (let item in this.aLanguageList) {
if (item.value === szLanguage) {
this.$i18n.locale = item.value;
this.szCurrentLanguage = this.$i18n.locale
// 保存后,下次刷新将会默认之前选择的语言
oWebSession.setItem("currentLanguage", item.value);
break;//跳出循环
}
}
另外值得注意的是,这里是单纯赋值,如果涉及到对象或者数组的话,就要考虑深拷贝和浅拷贝的问题了。
问题三
在vue框架里依赖jquery
提供的方法,其实jquery
里的方法都是可以用原生方法实现的。在vue框架里混用jquery
,会导致项目代码耦合度较高,可维护性降低。项目代码如下:
//登录前获取请求
WSDK_Request(szHostName, iHttpProtocal, iPort, options) {
let url = webSdkUtils.formatString(this.CGI[options.cmd].url, iHttpProtocal == 2 ? "https://" : "http://", szHostName, iPort);
let newOptions = {
type: "GET",
url: url,
success: null,
error: null
};
$.extend(newOptions, options);}
解决办法
推荐使用$.extend(newOptions, options);
可以考虑用es6里的Object.assign()
。比如改写代码为:
//登录前获取请求
WSDK_Request(szHostName, iHttpProtocal, iPort, options) {
let url = webSdkUtils.formatString(this.CGI[options.cmd].url, iHttpProtocal == 2 ? "https://" : "http://", szHostName, iPort);
let newOptions = {
type: "GET",
url: url,
success: null,
error: null
};
Object.assign(newOptions, options)}
另外当底下有多层属性时,可以考虑使用JSON.parse
进行深拷贝,具体见我之前的博客,另外最好不要在VUE项目里混用jQuery
,大部分操作都是可以用js原生方法解决的。
##总结
- 组内vue项目较少,组内架构的框架也比较新,从老项目移植过来,确实存在着一些问题,需要开发人员在开发过程中注意代码规范,对于不合理的部分进行优化