首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  程序员

求助, vue 轮询请求更新数据渲染时闪烁

  •  
  •   SanGo · 153 天前 · 2860 次点击
    这是一个创建于 153 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我遇到一个问题,做一个监控平台,采用轮询请求更新 data,但是由于相关联的视图试用 vfor 渲染的,更新视图时会导致闪烁更新,搜过狗哥也没解决方案,还请大佬们指点一下
    第 1 条附言  ·  153 天前

    code1code2code3code4code5

    第 2 条附言  ·  153 天前
    这个是当前的问题,因为 data 的更新会导致重新渲染,然后发生闪烁,这块的话父级和子级都要分别获取,先定时轮询父级然后触发 watch 去变更 data 触发子级的请求
    ![show1]( https://s2.ax1x.com/2019/07/05/ZaaObR.png)
    ![show2]( https://s2.ax1x.com/2019/07/05/ZaavUx.png)
    47 回复  |  直到 2019-07-05 15:26:26 +08:00
        1
    jorneyr   153 天前
    试试 throttle 或者 debounce 进行节流,避免频繁更新,可以使用 underscore 或者 lodash 的实现,也可以自己实现这 2 个函数,参考 https://underscorejs.org/#throttle
        2
    NaVient   153 天前
    是你想的太复杂了把,这不就是更新数据先声明成临时变量,再循环去看页面数据和更新数据不同的地方,更新数据变更的项不就行了吗?
        3
    clandyuki   153 天前
    加上 key
        4
    SanGo   153 天前
    @jorneyr 是定时更新的,所以不用节流
        5
    SanGo   153 天前
    @NaVient 绑定的 data 发生变化,就会重新触发 v-for 去渲染导致闪烁
    @clandyuki vfor 加 key 很常规啊。。。
        6
    15651980765   153 天前
    v-for 的时候绑定 key,值用数据的 id,不要用遍历的索引,这样可以保证数据变化后可以最大程度复用之前的 DOM。
        7
    NaVient   153 天前
    @SanGo #5 你不变更 data 整体,变更 data 的一个 index 不会触发的,VUE 内部是根据 key 去更新的
        8
    shenyu1996   153 天前
    是不是 data 更新前顺便赋了个 null
        9
    TrickWu   153 天前
    照理不会闪烁的,是根据 data 变化来触发视图更新,应该是你代码写的有问题
        10
    Vegetable   153 天前
    上代码吧兄弟
        11
    cuzfinal   153 天前
    这种引发列表重新渲染的肯定是用了不稳定 key,代码都不用看。
        12
    no1xsyzy   153 天前
    先复制一份然后尽可能缩,产生一份最小可复现样本。
    如果如 #8 所言,或者类似地更新操作导致 data 暂时地不可用化,应该会在 console 里有报错,或者有 v-if="data"。
    另外闪烁的样子录个 gif 吧,有可能甚至跟前端无关,是硬件跟不上也有可能。
        13
    qiaobeier   153 天前
    尝试闪烁的节点上加上 css 属性 transform: translateZ(0);
        14
    f056917   153 天前
    我的 key 都是 item.index,而且很少使用
        15
    jorneyr   153 天前   ♥ 3
    代码那点破事真不是难事,码农更重要的是学会沟通,不要抱怨没人回答你的问题,
    首先需要学会如何提问,其他人才能更好的理解你的问题。

    如何有效地提问:
    - 你做了什么,怎么做的
    - 你查过什么资料,怎么说的
    - 你是怎么设计的
    - 贴出你的代码
    - 编译错误是什么
    - 代码截图,错误截图
    - 结果有什么错,你期望的结果是什么
    - 你是怎么想的

    回答你的问题是情义,不理你是我的权力,没有人有义务要帮助你
    你是在寻求帮助,态度好点,但也不要委屈自己

    最后,如果你啥都不会,或者只会一点基础,不要期望我们告诉你怎么做
        16
    sugars   153 天前
    楼上正解,就提问者提供的信息,不够详情,无从下手(就这情况,更新时加了动画 css 也不是不可能)
        17
    a852695   153 天前
    能否贴个 GIF 和对应的部分代码,这样问题也好定位
        18
    SanGo   153 天前
    不知道 V2EX 怎么上图。。。
        19
    SanGo   153 天前
    我现在把这边的 key 改成了 index 了,依然会导致闪烁 Orz
    https://s2.ax1x.com/2019/07/05/ZawEy4.png
        20
    SanGo   153 天前
    @sugars css 没加=-=。。
        21
    SanGo   153 天前
    @shenyu1996 data 更新前没有做赋值操作,初始渲染的时候是为空的不用管
        22
    SanGo   153 天前
        23
    ytxbnahn   153 天前
    更新数据时 你是不是先初始化了 data=[] 然后在重新赋值[email protected]
        24
    SanGo   153 天前
    @ytxbnahn 没有,只有第一次加载的时候是有初始化的,更新的时候没有初始化 data,代码在附加的图里面
        25
    wdspro   153 天前
    @SanGo 楼上整理了三种可能
    一个是你的 key 尽量不要用 index 用用其他的 ID 啥的 尽量减少重绘
    二就是你取回新的 data 前是不是有初始化数组为[] 肯定就又完完整整重新渲染了两次 会闪烁
    第三种就是有可能硬件有影响 数据量太大的时候 排除方式是最小化自己的数据量来例化测一下 楼上说的 transfromZ 也有可能
    别着急问 先看看大家的回答 这么多楼了 你的 key 还没改试一下
        26
    wdspro   153 天前
    你的图里 第二个 for 循环里怎么有两个:key
        28
    SanGo   153 天前
    @wdspro 哦哦,现在第二个 for 现在改了,还是一样的
    1.不用 key 的话用 item.id 这类的 key 也会因为 data 的对象导致更新
    2.去会心的 data 前没有初始化数组
    3.数据量在#22 的图有...非常少
        29
    ASpiral   153 天前
    点开第一张图就看到 :key="item.CtiNo + i",key 不要用到 index …
        30
    SanGo   153 天前
    @jorneyr 设计和效果都上了附图了,附 1 是代码,附 2 和#22 是效果,
    搜索过 data 更新闪烁,大多数都是说采用 v-cloak 来解决,但是我这里不是初始化的空白闪烁问题,是更新数据的异步闪烁 Orz,期望#22 的数据更新时不发生闪烁,该代码目标是实现监控组通话数量(数量还没绑定进去渲染),谢谢
        31
    SanGo   153 天前
    关于各位说到的 key 不要用到 index 的问题,现在已经改成了下图
    https://s2.ax1x.com/2019/07/05/ZagvC9.png
    也没有改变结果 Orz
        32
    no1xsyzy   153 天前
    res.Cti 的值是?
    你还说没有先清空再添加?
        33
    SanGo   153 天前
    @no1xsyzy 直接赋值呀。。是个数组包对象
        34
    no1xsyzy   153 天前   ♥ 1
    你用了两个接口去获取
    一个 getCti 一个 getTrunk
    你先把 getCti 的结果填充进去,然后再去获取的 getTrunk
    我有理由相信 getCti 本身没有 Trunk 的信息,所以 Trunk 被清空了,然后又通过 watch 添加的,中间必然差至少一帧。
        35
    no1xsyzy   153 天前
    这个问题不管是开 vue debugger (浏览器插件)还是开 Network 选项卡都是可以轻易得知的。
        36
    jorneyr   153 天前
    看不出问题来,如果可能的话, 弄一个最小的测试案例,大家可以重现,然后才能去调试。
    数据模拟生成就好,不用走服务器端
        37
    SanGo   153 天前
    @no1xsyzy 是的,是这个问题 Orz 所以难以处理这块
        38
    no1xsyzy   153 天前
    @SanGo 这难解决?请回炉重造(指程序员)。
        39
    lhstock   153 天前
    watch 监听 CTI 又修改 CTI 是作死
        40
    SanGo   153 天前
    @no1xsyzy 给多一个变量拿到 trunk 插入 cti 以后再直接替换是可以,但是感觉都是绕了一圈- -
        42
    liuy1994g   153 天前 via Android
    求求你打开控制台看看 network 到底发了多少个请求吧。
    你在 watch 里面对每一项都重新取值了。
        43
    SanGo   153 天前
    @liuy1994g #34 说了
        44
    crs0910   153 天前
    你可以不用 watch,第一级拿完直接拿第二级返回完整数据不就得了。我看你都不关心 id 是不是变了,每次都是拿的全量新数据。那就直接都拿完拼完呗。
        45
    no1xsyzy   153 天前   ♥ 1
    @SanGo 还有一种就是把 CTI 和 Trunk 分开存两个属性里,分别更新。
    但那样其实就是自己手工写一个简陋、粗糙、残缺、低效的关系型数据库。
    为什么不让后端做?一件事多个接口还不是做成 RESTful 的。
    graphQL 或者 RESTful 你总得选一个。
        46
    SanGo   153 天前
    @no1xsyzy 后端表示反正给我了....然后就 emmm,graphQL 我看一看如何处理,谢谢解答
        47
    a4854857   153 天前
    看了楼上的你的渲染数据如果是两个接口的数据拼成的. 你用 promise.all 保证一次两个请求都返回值了再更新数据不就好了..
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   988 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 25ms · UTC 20:54 · PVG 04:54 · LAX 12:54 · JFK 15:54
    ♥ Do have faith in what you're doing.