支持更新后的Vue.js组件渲染

时间:2018-01-26 08:34:26

标签: javascript vue.js vuejs2

在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>

如果在父母(问题组件)中,我更新&#34;选择&#34;该元素的属性,不会重新呈现此组件。

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 Developer Console中,我检查了答案组件数据是否已更新,因此答案被标记为已选中。无论如何,不​​会使用&#34; quiz-input-choice - selected&#34;类。

奇怪的是,如果我从道具的父级其他属性更新(例如(answer.title)),那么子组件也会正确呈现,并且类别为#34; quiz-input-choice - selected&# 34 ;. 所以我想这是一个检测孩子变化的问题。

2 个答案:

答案 0 :(得分:1)

谢谢大家的答案。

我发现了这个问题。答案的“selected”属性不存在于初始对象中,因此Vue无法使该属性具有反应性。 https://vuejs.org/v2/guide/reactivity.html

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

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

答案 1 :(得分:0)

我认为你在这里有结构性问题。您不应该向父母提交活动,因为该组件应该是自包含的。

然而,您可以做的是在子组件中发出一个事件(答案),该事件将在父组件中被捕获(问题)。

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;
    },
  },
};