【问题标题】:Vue slot is not working in rare and unpredictable cases (potential vue bug?)Vue 插槽在罕见和不可预测的情况下不起作用(潜在的 Vue 错误?)
【发布时间】:2021-10-18 11:04:42
【问题描述】:

我有一个奇怪的错误,其中一个插槽在某些未知情况下不可靠。

组件

有 3 个分层组件。

  • 孙子 (headlessTable),它提供了一个名为 arrayValue 的插槽。
  • 孩子 (collapsableCard),它通过孙子和父母之间的插槽。
  • 父级 (orderDataCard),决定为该插槽呈现链接。

问题:在加载新数据时,正在渲染子级的默认插槽 html,而不是渲染父级的链接。

数据结构(orderDetails)

  • 进程(obj)
    • 标记(字符串)
    • 普通(obj)
      • 附加参数(数组)
        • 类别(字符串)
        • 类型(字符串)
        • 名称(字符串)
        • 值(字符串)
    • salesOrganisation (obj)
    • 发票(数组)
      • invoiceAgreementId(字符串)
      • paymentType(字符串)

复制

StackblitzCodesandbox

请查看additionalArguments 字段,它包含一个链接。 按 ALT+M 模拟获取新数据。现在,不是呈现链接,而是呈现该命名插槽的默认插槽 html。 可以按 ALT+J 加载原始数据,但这次没有链接。

Initial data (ALT+J) Loaded data (ALT+M) Type Equal value
mark str false
common common obj true
salesOrganisation salesOrganisation obj true
invoices (empty) invoices arr false

2如何解决

  • 如果您取消注释 app.js 中的第 68 行(如果您使用的是代码和框,则取消注释 App.vue 中的第 73 行),即名为 mark 的字段
  • 如果 invoices 在 app.js 中最初不是空的
  • 如果mark 在 orderDataCard 中从 html 中删除
  • 如果 salesOrganisation 在 orderDataCard 中从 html 中删除
  • 如果 invoiceItems 的 v-for 模板部分中的 html 在 orderDataCard 中为空

显然,这些不是解决方案。

注意事项

无论如何,任何字段之间都没有依赖关系或任何东西,所以我很难理解为什么会发生这种情况,我怀疑这是 vue 的一个错误。我已经为此创建了一个issue。但是,开发人员不会查看复制,因为他们认为它不是最小的 #lines > 100。只要我删除任何更有意义的行,错误就解决了,删除的代码也没有错误,所以非常令人沮丧在这方面工作。我仍然可以删除无意义的行,但这会使所有相关人员更难理解正在呈现的数据。

是否有人能够承认这是 vue 的问题并且代码不可简化,或者(我更喜欢这个)有人能够解决这个问题吗?

【问题讨论】:

    标签: vue.js vuejs2


    【解决方案1】:

    问题与 Vue 处理同一组件的多个实例有关。在OrderDataCard.vue 中有两个Collapsable-Card 实例,没有唯一键。在这种情况下:

    Vue 使用最小化元素移动的算法并尝试 尽可能就地修补/重用相同类型的元素。

    我不太清楚这些算法是如何工作的,以及为什么显然它重用了第二个实例(没有定义插槽内容),但是为这些组件设置一个唯一键解决了这个问题。

    查看工作代码沙箱:https://codesandbox.io/s/admiring-hamilton-5ytpp?file=/src/components/OrderDataCard.vue:133-149

    注意:我无法在浏览器中触发键盘事件,所以我在点击按钮时触发了它们。

    【讨论】:

    • 谢谢,我在原始代码库中对其进行了测试,效果很好。我实际上有一个类似的方法,我只是错误地解决了它,因为我使用了id 道具而不是key 道具。我认为 key 只用于 v-for 语句,哦。
    【解决方案2】:

    这可能不是解决方案,但可以帮助找到它:

    对象

    我注意到您正在处理对象并将它们转换为数组。使用对象属性可能会出现问题,因为与数组不同,更新的属性不会传播。这是 JavaScript 的问题,而不是 Vue。 Vue 之所以成为可能,是因为引入了观察者,但对象仍然不是其中的一部分。

    当对象被部分更新时,您可能会遇到问题。

    我建议查看Vue.set
    我的旧代码通过 window.Vue.set() 显式调用它以更改对象属性,以便 Vue 可以正确传播它们。

    这是一种 Vue 中的错误,但又源于 JavaScript 本身。

    计算数组

    我不完全确定,但计算数组并​​不能解决使用对象的上述问题。
    在更新对象和对象属性时,我会走安全路线并使用Vue.set()。你仍然可以使用计算数组。

    否则显而易见:用对象创建真正的数组,而不是一半时间处理对象。

    this.process

    您是否有充分的理由明确使用this.process 而不是组件的道具?或者那是来自库的组件?

    插槽

    您是否尝试过完全相同的代码但没有使用collapsable-card?只是输出链接本身?它可能指向collapsable-card 组件中的插槽问题。也可能部分是因为上面的物体。

    【讨论】:

    • 我不怀疑对象的奇怪动态是导致此问题的原因,因为数组槽已正确识别,但未传递给父级。我想我只使用 this.process 是因为我懒得输入完整路径。我没有尝试绕过可折叠卡,但我怀疑它可能会起作用。但是代码库会变得丑陋,所以显然不是一个好的解决方案:(
    • 我的意思是更换折叠卡来查找错误。如果您不更改源代码,您将找不到错误。
    • 是的,我知道,我理解正确。我现在尝试了这个:stackblitz.com/edit/vuejs-starter-dgtdvm?file=orderDataCard.js 并且行为完全符合我的预期。现在让我看看 Vue.set..
    • 所以我刚刚阅读了您关于 Vue.set 的链接。他们说如果你重新分配一个对象的 properties,你应该使用它。这不是我正在做的,因为我重新分配了整个对象。他们告诉你,如果你想重用旧对象,你应该在Object.assign 部分的末尾完全这样做。但同样,这不是我正在做的,因为我使用了一个全新的对象。
    • 嗯,好吧,如果你确定那是排除了潜在的问题。不过,仍然想知道发生了什么。
    猜你喜欢
    • 2022-11-11
    • 2018-08-15
    • 2017-09-08
    • 2017-06-15
    • 1970-01-01
    • 2020-01-28
    • 2020-12-25
    • 2019-06-08
    • 2021-02-06
    相关资源
    最近更新 更多