【问题标题】:Vue.js: child components are not being re-renderedVue.js:子组件没有被重新渲染
【发布时间】:2020-01-22 19:53:30
【问题描述】:

我试图弄清楚 props 是如何传递给子组件的,以及它们是如何从那里更新的。

// parent.vue
<template>
    <div>
        <div v-for="elem in getCurrentArray">
            <child-component :elem="elem"></child-component>
        </div>
        <button @click.prevent="currentIdx--">Prev</button>
        <button @click.prevent="currentIdx++">Next</button>
    </div>
</template>
<script>
    export default {
        components : {
            ChildComponent
        },
        data(){
            return {
                arr : [ ["A", "B", "C" ], [ "D", "E" ]], // this would be populated from vue store
                currentIdx : 0
            }
        },
        computed : {
            getCurrentArray(){
                return this.arr[this.currentIdx]
            }
        },
    }
</script>
// child.vue
<template>
    <div>Prop: {{elem}} <input type="text" v-model="myinput" @blur="save" /></div>
</template>
<script>
    export default {
        props : [ "elem" ],
        data(){
            return {
                myinput : this.elem
            }
        },
        methods : {
            save(){
               // this.$store.dispatch("saveChildElement", { myinput }
            }
        },
        mounted(){ console.log( this.elem + " being rendered" ) }
    }
</script>

在这个例子中,我有两组数组 ['A','B','C'] 和 ['D','E']。在页面加载时,第一组通过子组件呈现。

看起来不错。但是,当我单击下一步转到第二组时,我得到了这个:

因此,当正确传递道具时,文本框输入值不会更新。当我检查 console.log 时,很明显 vue 不会为“D”和“E”重新渲染子组件。相反,它只是使用“A”和“B”的现有组件。

有没有办法强制 vue 重新渲染组件?如果没有,我如何确保文本框输入获得最新的道具值?请记住,我希望能够通过 vue store 保存对输入值的更改。

【问题讨论】:

  • 是的,看起来像复制品。但是,该帖子缺少示例代码(断开的链接),因此它可能没有那么有用
  • 我的错,完全错过了。谢谢。

标签: javascript vue.js vuejs2


【解决方案1】:

按照cool-man所说的添加密钥,它会解决问题。

但是,您对组件重新渲染的检查存在缺陷,您使用了子挂载生命周期,并且因为您仅在您认为组件未重新渲染时才看到它运行。但这是错误的。 “挂载”在组件生命周期中只发生一次,因为您将相同的组件用于 ['A','B','C'] 然后用于 ['D','E'] vue 不知道重新创建组件并使用新的道具重新渲染它们。

【讨论】:

    【解决方案2】:

    尝试在v-for 循环中添加:Key 属性

    <div v-for="elem in getCurrentArray" :key="elem">
    

    要给 Vue 一个提示,以便它可以跟踪每个节点的身份,从而重用和重新排序现有元素,您需要为每个项目提供唯一的 key 属性:

    ...List Rendering - Maintaining State

    键必须是唯一的,如果你的数组中有两个或多个相同的值,例如['A',' B', 'A'],它会产生冲突,解决这个问题的最好方法是为每个实例添加一个生成的唯一“ID”。

    或者替代方案(短期解决方案)

    您可以将循环索引与数组值结合使用,这应该会给您一个或多或少的唯一键。

    &lt;div v-for="(elem, index) in getCurrentArray" :key="elem + index"&gt;

    【讨论】:

    • elem 用于key 似乎可能会导致冲突。
    • 更新了我的答案,这个“索引 + 值”应该能让你明白......但是为每个实例设置一个唯一的 ID 是最好的方法。
    【解决方案3】:

    您只需将key 添加到v-for 循环即可。

    替换

    &lt;div v-for="elem in getCurrentArray"&gt;

    &lt;div v-for="elem in getCurrentArray" :key="elem"&gt;

    参考:https://vuejs.org/v2/guide/list.html#v-for-with-a-Component

    【讨论】:

      【解决方案4】:

      您可以要求您的组件重新渲染。 (更新密钥的其他答案都是正确的)。

      但是,如果您确实想使用 Vuex 来管理状态,我建议您首先这样做,因为(本质上)有一种不同的机制可以为您重新渲染,并且感觉更容易。即“计算属性”可能会为您解决这个问题。

      我记得刚开始的时候就卡在了这个问题上,一旦我实现了 Vuex,我希望我只是这样做,作为其工作流程的一部分,这只是为我解决了这个问题。 (这可能意味着您不需要更新密钥,但如果您遇到复杂情况时仍需要强制重新渲染,则可以这样做)。

      编辑: 正如@JonyB 正确指出的那样,您正在尝试重新渲染整个组件。如果你仔细想想,你真正想做的不是重新渲染整个组件,而只是更新状态。因此,一旦你实现了 Vuex,它可能会为你解决这个问题,因为它允许你单独处理状态。

      【讨论】:

        猜你喜欢
        • 2018-05-19
        • 2017-06-11
        • 2021-11-24
        • 1970-01-01
        • 2020-09-17
        • 2018-08-12
        • 2019-06-01
        • 1970-01-01
        • 2020-02-13
        相关资源
        最近更新 更多