Vuejs for 循环内如何更新页面状态 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hoythan
V2EX    Vue.js

Vuejs for 循环内如何更新页面状态

  •  
  •   hoythan 2017-08-24 10:36:05 +08:00 4029 次点击
    这是一个创建于 3036 天前的主题,其中的信息可能已经有所发或是发生改变。

    在点击按钮触发一个 for 循环事件

    that.progress = xxx

    that.progress = Math.ceil((i / fileNumber) * 100) 

    dom 中没有刷新状态,

    console.log(that.progerss) 

    是正常的

    因为这不是对象也不是数组的,不知道为啥会这样

    let that = this let filePath = that.filePath let fileNumber = that.filesNumber let files = that.files let i = 0 async.whilst(() => { return i < fileNumber }, (callback) => { let newPath = path.normalize(files[i]).replace(path.normalize(filePath), path.normalize("C:\\Users\\xxx\\xxx")) fs.copySync(files[i], newPath) i++ that.progress = Math.ceil((i / fileNumber) * 100) console.log(that.progress) callback() },()=> { alert('ok') }) 
    第 1 条附言    2017-08-24 11:30:43 +08:00
    最终用了一个比较尴尬的方法解决

    ```
    async.whilst(() => {
    return i < fileNumber
    },
    (callback) => {
    let newPath = path.normalize(files[i]).replace(path.normalize(filePath), path.normalize("C:\\Users\\hoyt\\Desktop\\webs2\\"))
    fs.copySync(files[i], newPath)
    i++
    that.progress = Math.ceil((i / fileNumber) * 100)
    that.$nextTick(() => {
    setTimeout(() => {
    callback()
    },0)
    })

    }, () => {
    alert('ok')
    })
    ```
    在 nextTick 中使用 settimeout 0 后再执行下一次循环
    ```
    that.$nextTick(() => {
    setTimeout(() => {
    callback()
    },0)
    })
    ```
    第 2 条附言    2017-08-24 11:32:32 +08:00
    v2ex 只有主题里面才能用 markdown 吗?



    最终在 nextTick 结束后使用 settimeout 0 触发下一次循环有效
    19 条回复    2017-08-24 11:52:51 +08:00
    littlepanzh
        1
    littlepanzh  
       2017-08-24 10:36:58 +08:00   1
    talk is cheap, show me your code
    hoythan
        2
    hoythan  
    OP
       2017-08-24 10:40:08 +08:00
    @littlepanzh 就是 for 循环里面修改参数,console 显示正常,dom 不刷新
    SourceMan
        3
    SourceMan  
       2017-08-24 10:41:55 +08:00   1
    Vue.set()
    hoythan
        4
    hoythan  
    OP
       2017-08-24 10:43:26 +08:00
    @SourceMan 我这不是数组对象呀?
    hoythan
        5
    hoythan  
    OP
       2017-08-24 10:45:44 +08:00
    @SourceMan 我先试一下
    hoythan
        6
    hoythan  
    OP
       2017-08-24 10:50:21 +08:00
    @SourceMan 果然不行
    66beta
        7
    66beta  
       2017-08-24 10:55:28 +08:00   1
    如果 console.log 都看到变化了,应该没毛病
    watch 下看看呢
    hoythan
        8
    hoythan  
    OP
       2017-08-24 11:01:03 +08:00
    @66beta watch 只有触发了一次
    Lothar
        9
    Lothar  
       2017-08-24 11:01:07 +08:00   1
    一个循环里的更新,统一被放在一个缓存队列里,循环结束后一起更新。你想啊,如果不这么做,一个循环你的页面不就崩了。
    Lothar
        10
    Lothar  
       2017-08-24 11:03:45 +08:00   1
    > In case you haven ’ t noticed yet, Vue performs DOM updates asynchronously. Whenever a data change is observed, it will open a queue and buffer all the data changes that happen in the same event loop. If the same watcher is triggered multiple times, it will be pushed into the queue only once. This buffered de-duplication is important in avoiding unnecessary calculations and DOM manipulations. Then, in the next event loop “ tick ”, Vue flushes the queue and performs the actual (already de-duped) work. Internally Vue tries native Promise.then and MutationObserver for the asynchronous queuing and falls back to setTimeout(fn, 0).
    hoythan
        11
    hoythan  
    OP
       2017-08-24 11:07:32 +08:00
    @Lothar 所以我要实现的话是不是得直接自己修改 dom 比较好一点?
    hoythan
        12
    hoythan  
    OP
       2017-08-24 11:14:13 +08:00
    @Lothar 好像是我想多了,直接修改 dom 为啥也不会改变 555

    document.getElementById('xxx').innerHTML
    loveyu
        13
    loveyu  
       2017-08-24 11:16:45 +08:00 via Android   1
    Var.nextTick
    hoythan
        14
    hoythan  
    OP
       2017-08-24 11:24:46 +08:00
    @loveyu
    that.progress = Math.ceil((i / fileNumber) * 100)
    Vue.nextTick()

    还是无法刷新 dom,循环结束才更新
    qiqico
        15
    qiqico  
       2017-08-24 11:27:56 +08:00   1
    试试 this.$forceUpdate() ?
    maplerecall
        16
    maplerecall  
       2017-08-24 11:32:29 +08:00   1
    用$forceUpdate 试试,另外如果循环操作阻塞了主线程也是不会更新 dom 的
    hoythan
        17
    hoythan  
    OP
       2017-08-24 11:34:23 +08:00
    @qiqico
    @maplerecall

    看来真的是阻塞了主线程,我的异步用的方法可能不对
    jin5354
        18
    jin5354  
       2017-08-24 11:49:04 +08:00   1
    你想在每次循环时都更新 DOM,制造一种高频率渲染的效果?
    用 requestAnimationFrame 循环来写异步
    jin5354
        19
    jin5354  
       2017-08-24 11:52:51 +08:00   1
    你即使用 for 循环直接改 DOM 也没用,且不说 vue 自带事件队列,每个 tick 里的数据变动会做合并。你一个 for 循环在一个 eventloop 的 task 里就跑完了,最多就渲染一次 DOM。必须把 for 任务用 requestAnimationFrame 打碎到每一帧里
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     893 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 21:09 PVG 05:09 LAX 13:09 JFK 16:09
    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