vue 遇到了一个奇怪的问题.jpg - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaome
V2EX    Vue.js

vue 遇到了一个奇怪的问题.jpg

  •  
  •   xiaome 2018-07-18 17:34:19 +08:00 2546 次点击
    这是一个创建于 2716 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天遇到个比较奇怪的问题,导致了死循环,请教了一系列大佬之后最终判断为 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> 
    10 条回复    2018-08-22 09:47:09 +08:00
    noe132
        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 的源码才知道了
    ccceeeooo
        2
    ccceeeooo  
       2018-07-18 18:46:05 +08:00
    在 template 里调用函数修改数据本来就是不对的
    chairuosen
        3
    chairuosen  
       2018-07-18 18:50:42 +08:00
    在 get 里不要 set,在 render 里只调 get
    luoway
        4
    luoway  
       2018-07-18 19:24:54 +08:00   1
    v2ex 帖子不能删,过一年楼主回来看这个 isShow 会感到羞愧的
    ioc
        5
    ioc  
       2018-07-18 19:31:50 +08:00 via Android
    @luoway 可以删的
    panyanyany
        6
    panyanyany  
       2018-07-18 22:03:47 +08:00
    @luoway #4 你不说还没注意到,这个 isShow 确实有点意思……
    billyu
        7
    billyu  
       2018-07-19 06:49:16 +08:00 via Android
    @panyanyany hh break 被吃了
    yinjunjian0
        8
    yinjunjian0  
       2018-07-19 10:14:30 +08:00
    isShow 有丶东西
    dengshen
        9
    dengshen  
       2018-08-22 09:37:29 +08:00
    @billyu 已经 return 没必要在写 break 了 如果用了标准 eslint 的话写 break 反而会报错
    billyu
        10
    billyu  
       2018-08-22 09:47:09 +08:00
    @dengshen #9 嗯嗯 是的 多谢提醒
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2955 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 12:22 PVG 20:22 LAX 04:22 JFK 07:22
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86