仅以此记录 vue 中遇到的坑
组件的复用问题
Vue的虚拟DOM中,Vue会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。
然后我遇到了这样的bug:同事做了一个scrollbar的组件,我用在了steps组件中,用了多个。在点击下一步的时候当前step下的组件会销毁,我特意加了v-if,下一个step下的组件会创建,问题来了…上一步的scrollbar组件影响到了当前创建下的scrollbar组件。
原因:Vue的算法会尝试复用组件
解决方案:使用key,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。加了key之后,就会重新渲染,而不是复用了。
代码:
1  | <div class="stepContent" key="1" v-else-if="currentStep == 1">  | 
结语:我想大多数玩家和我一样,都是在v-for里用到了key,我虽然用到了,但是没有真正理解它,所以才会碰到这个bug不知道原因,还傻乎乎的去看组件的源码,浪费了很长时间。理解最值得重视…
最后附上:key的官方介绍
数据的拷贝和动态组件产生的bug
自己用
element的input和tree合成了一个inputTree组件
想使用动态组件来生成不同的表单,代码如下:
1  | <component :is="getDynamicComp(item)" v-for="(item,index) in list" :key="index"></component>  | 
结果:input和select都生成了,但是改变不了数据
原因:改变input和select的值时,list数组会变化,这个list其实还在我另外一个组件中使用,另外一个组件监听了这个list的变化,由此getDynamicComp()重新计算,然后重新生成动态组件,动态组件里面的input、select又恢复到了初始渲染状态,所以改变数据无效
最后:提供对象浅拷贝和深拷贝的方法
浅拷贝:
1
Object.assign({}, obj)
深拷贝: 参考 这儿
将对象序列化为字符串,然后将其反序列化
1
JSON.parse(JSON.stringify(obj))
非常简单,但是有两个常见的错误:
- 如果属性是不可序列化值类型,结果并不是期盼的值。比如 函数会被忽略, 
Date类型会被JSON.parse()解释为字符串 - 如果有循环引用会报错
 
JSON.stringify()拥有三个参数(参考官方描述),第一个错误可以用下面的代码修复:1
2
3
4
5
6
7
8
9
10
11
12JSON.parse(JSON.stringify(json, function(key,val){
if(typeof val=='function'){
return val+''//手动将其字符串化
}
return val;
}
),function(key,val){
if(val.indexOf&&val.indexOf('function') !== -1){
return eval("(function(){return "+val+" })()")
}
return val;
});第二个错误只能望而叹之。
- 如果属性是不可序列化值类型,结果并不是期盼的值。比如 函数会被忽略, 
 递归拷贝:
可以使用lodash的_.cloneDeep(obj)方法,通过学习这个库,咱们可以简单实现这样的一个方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31function cloneDeep(value) {
if(value instanceof Object) {
var result;
if(value.constructor === Object) { // 对象
result = {};
for (let i in value) {
result[i] = cloneDeep(value[i]);
}
} else if (value.constructor === Array) { // 数组
result = [];
value.forEach(function(item, index) {
result[index] = cloneDeep(item);
});
} else if (value.constructor === Function) { // 函数
// 方式1
result = new Function("return " + value.toString())();
// 方式2
result = function() {
return value.apply(this, arguments);
}
} else if (value instanceof Date) { // new Date() 时间对象
result = new Date();
result.setTime(result.getTime());
} else { // new String...的instanceof Object也为true,这个直接赋值,
result = value;
}
return result;
} else {
return value;
}
}里面对于循环引用没做处理,因为对
lodash的封装的Stack还不是很明白…


