【问题标题】:Vue.js Component rendering after prop updateprop 更新后的 Vue.js 组件渲染
【发布时间】:2018-07-05 14:12:02
【问题描述】:

在 Vue.js 中,我有一个像这样的组件(答案组件):

<template>
    <a class="quiz-input-choice" :class="{'quiz-input-choice--selected': answer.selected}"
       @click="toggleSelect()" :selected="answer.selected">
        <img :src="answer.image_path"/>
        <p class="quiz-input-choice__description">{{answer.title}}</p>
    </a>
</template>
<script>
    export default {
        props: ['answer'],
        methods: {
            toggleSelect() {
                this.$parent.$emit('answer-selected', this.answer.id);
            }
        }
    }
</script>

如果在父级(问题组件)中我更新了元素的“selected”属性,这个组件将不会被重新渲染。

export default {
        props: ['question'],
        components: {QuizAnswer},
        created: function () {
            let _self = this;
            this.$on('answer-selected', id => {
                let i = _self.question.answers.map(item => item.id).indexOf(id);
                let answer = _self.question.answers[i];
                answer.selected = !answer.selected;
            });
        }
    }

在 Vue 开发者控制台中,我检查了答案组件数据是否已更新,因此答案被标记为选中。无论如何,不​​是用“quiz-input-choice--selected”类渲染的。

奇怪的是,如果我从 prop 的父级其他属性(例如 (answer.title))更新,则子组件也会正确呈现类“quiz-input-choice--selected”。 所以我想这是检测孩子变化的问题。

【问题讨论】:

  • 旁注:您不需要_self = this 模式,因为您使用的是箭头函数

标签: javascript vue.js vuejs2


【解决方案1】:

谢谢大家的回答。

我发现了问题。初始对象中不存在答案的“已选择”属性,因此 Vue 无法响应该属性。 https://vuejs.org/v2/guide/reactivity.html

我解决了在父组件中使该属性反应的问题。

created() {
            let self = this;
            this.question.answers.forEach(function (answer) {
                self.$set(answer, 'selected', false);
            });
        },

【讨论】:

    【解决方案2】:

    我认为您在这里遇到了结构性问题。您不应该将事件提交给您的父级,因为该组件应该是自包含的。

    但是,您可以做的是在子组件 (Answer) 中发出一个事件,该事件将在父组件 (Question) 中捕获。

    Answer.vue

    <template>
        <a class="quiz-input-choice" :class="{'quiz-input-choice--selected': answer.selected}"
           @click="toggleSelect()" :selected="answer.selected">
            <img :src="answer.image_path"/>
            <p class="quiz-input-choice__description">{{answer.title}}</p>
        </a>
    </template>
    <script>
        export default {
            props: ['answer'],
            methods: {
                toggleSelect() {
                    this.$emit('answer-selected');
                }
            }
        }
    </script>
    

    Question.vue

    您的模板将捕捉到这样的事件(我不知道您的答案在哪里,所以我假设您有一个 answers 数组):

    <answer 
      v-for="(answer, index) in answers"
      :answer="answer" 
      @answer-selected="answerSelected(index)"
    ></answer>
    

    您的脚本将如下所示:

    export default {
      props: ['question'],
      components: {QuizAnswer},
      data() {
        return {
          answers: [],
          selectedAnswer: -1,
        };
      },
      watch: {
        selectedAnswer(newIndex, oldIndex) {
          if (oldIndex > -1 && this.answers.length > oldIndex) {
            // Reset old value
            this.answers[oldIndex].selected = false;
          }
          if (newIndex > -1 && this.answers.length > newIndex) {
            // Set new value
            this.answers[newIndex].selected = true;
          }
        },
      },
      methods: {
        answerSelected(index) {
          this.selectedAnswer = index;
        },
      },
    };
    

    【讨论】:

      猜你喜欢
      • 2018-04-20
      • 1970-01-01
      • 2023-03-28
      • 2019-12-27
      • 2021-12-15
      • 2018-10-14
      • 1970-01-01
      • 1970-01-01
      • 2022-06-30
      相关资源
      最近更新 更多