V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hoythan
V2EX  ›  Vue.js

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

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

    在点击按钮触发一个 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   ·   实用小工具   ·   2790 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 12:55 · PVG 20:55 · LAX 04:55 · JFK 07:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.