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

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

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

    code1code2code3code4code5

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

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

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

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