问题如题,vue2.x里watch data里的属性导致其它data属性的filter不断调用的问题(下面的代码控制台会不断打出---filter),vue1.x无此类问题。
这是bug,还是有其它配置可以设置?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
{{str}} = {{str | myUppercase}}<br>
{{index}} = {{myIndex}}
</div>
<script src="//cdn.bootcss.com/vue/2.0.3/vue.js"></script>
<!--<script src="//cdn.bootcss.com/vue/1.0.28/vue.js"></script>-->
<script>
var vm=new Vue({
el:"#app",
data:{
index:0,
myIndex:0,
str:'hello'
},
mounted:function(){
var vm=this;
setInterval(function(){
vm.index++;
},200);
},
/*created:function(){
var vm=this;
setInterval(function(){
vm.index++;
},200);
},*/
filters:{
myUppercase:function(value){
console.log('---filter');
if(!value) return '';
value=value.toString();
return value.toUpperCase();
}
},
watch:{
index:function(newValue,oldValue){
this.myIndex=newValue*2;
}
}
})
</script>
</body>
</html>
简单来说,是因为 Vue2 有了 Virtual DOM,index 的变化导致 render 函数被调用,继而导致 filter 函数被调用。
首先,你出现的问题跟你有没有 watch 其实没有关系,这点你可以把 watch 去掉试试。
其次, Vue1 因为没有 Virtual DOM,当观察到变化后去做 DOM 更新的时候是直接更新对应的节点,而 Vue2 则是先调用组件的 render 函数更新 Virtual DOM,再去做真实的 DOM 操作。而你的例子中,模板中有 index 和 str,所以组件的 render 函数依赖了 index 和 str,所以 index 变化的时候 render 函数被调用。
使用 Vue.compile 得到的 render 函数如下:
最后,filter 理应是一个纯函数,不应该产生副作用(比如上述的输出)。
参考:
https://segmentfault.com/a/11...
https://vuejs.org/v2/guide/re...
https://github.com/youngwind/...