今天遇到个比较奇怪的问题,导致了死循环,请教了一系列大佬之后最终判断为 vue 视图重绘了。 记录一下,也想请求一下各位大佬更好的解决方案, 这里感谢各位了。
贴上代码, 如果需要执行请注释
<html>
<head>
<title>测试</title>
<link href="https://cdn.bootcss.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id="app">
<div class="alert alert-primary" v-for="item in datas">
<ul v-for="month in item.months">
<li>{{month.month}} - {{month.name}}</li>
<!-- 循环方法 -->
<li>{{lastMonthStaff(item)}}</li>
</ul>
</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
datas: [
{
title: 2018,
months: [
{ month: 1, name: '12asds' },
{ month: 2, name: 'adsfsdf' },
{ month: 3, name: 'zcvzcv' },
{ month: 4, name: 'zvcc' },
{ month: 5, name: 'eqr124' },
{ month: 6, name: 'asdfsd' },
{ month: 7, name: 'dsafds' },
{ month: 8, name: 'adsfsdfv' },
{ month: 9, name: 'yiyu' },
{ month: 10, name: 'cxvcxv' },
]
},
{
title: 2019,
months: [
{ month: 1, name: 'uteye' },
{ month: 2, name: 'dfgh' },
{ month: 3, name: 'AF' },
{ month: 4, name: 'FAGSGH' },
{ month: 5, name: 'DSGS' },
{ month: 6, name: '' },
{ month: 7, name: 'SFDG' },
{ month: 8, name: 'DSFG' },
{ month: 9, name: 'SDFG' },
{ month: 10, name: 'FDHDG' },
]
},
{
title: 2020,
months: [
{ month: 1, name: 'FGHGF' },
{ month: 2, name: 'FGH' },
{ month: 3, name: 'FDH' },
{ month: 4, name: 'FGHCVN' },
{ month: 5, name: 'BVCN' },
{ month: 6, name: '' },
{ month: 7, name: 'UIY' },
{ month: 8, name: 'DSHFM' },
{ month: 9, name: 'FSD' },
{ month: 10, name: 'DFSFDG' },
]
},
],
allotUsers: []
},
methods: {
isShow(val) {
switch (val) {
case undefined:
return false
case '':
return false
case null:
return false
default:
return true
}
},
lastMonthStaff (row) {
for (var obj of row.months) {
if (obj.month === new Date().getMonth()) {
if (this.isShow(obj.name)) {
// 触发方法
this.setAllotUsers(obj.name)
// 输出上月 name
return obj.name
} else {
return '无'
}
}
}
},
setAllotUsers(val) {
console.log(val)
// 会触发视图更新导致死循环
this.allotUser.push(val)
// 想的笨办法解决方案
this.allotUsers[this.allotUsers.length] = val
},
}
})
</script>
</body>
</html>
1
noe132 2018-07-18 18:42:10 +08:00 1
vue 确实会在控制台报错 render loop.
你的 setAllotUsers 循环执行了 1000 多次后被 vue 叫停了。 setAllotUsers 会触发 render,render 会调用 lastMonthStaff,于是就死循环了。 设置数组的属性不会被 vue 监测到所以不会有问题。 你的 view 编译成的 render 函数中调用了 lastMonthStaff, lastMonthStaff 调用了 setAllotUsers setAllotUsers 调用了 allotUsers,被 vue 感觉到了(对,跟踪你的依赖) 让 vue 以为 allotUsers 的更改会对 view 造成变化,需要重新 render,于是重新 render 又造成了属性变化。 我的建议是,数据的处理,放在 view 渲染之前。不要再 view 里添加修改数据的代码,这样会让逻辑变得不够清晰。因为 render 函数并不是你调用的,你不清楚具体什么时候 render 函数会被调用。render 函数应该是无副作用的。 具体 vue 是怎么跟踪依赖的,这还要翻翻 vue 的源码才知道了 |
2
xiaochocking 2018-07-18 18:46:05 +08:00
在 template 里调用函数修改数据本来就是不对的
|
3
chairuosen 2018-07-18 18:50:42 +08:00
在 get 里不要 set,在 render 里只调 get
|
4
luoway 2018-07-18 19:24:54 +08:00 1
v2ex 帖子不能删,过一年楼主回来看这个 isShow 会感到羞愧的
|
6
panyanyany 2018-07-18 22:03:47 +08:00
@luoway #4 你不说还没注意到,这个 isShow 确实有点意思……
|
7
billyu 2018-07-19 06:49:16 +08:00 via Android
@panyanyany hh break 被吃了
|
8
yinjunjian0 2018-07-19 10:14:30 +08:00
isShow 有丶东西
|