使用嵌套组件进行VueTwo Way数据绑定

时间:2017-03-28 20:22:37

标签: vue.js

假设我想显示一个问题列表。对于每个问题,都有一个答案列表,其中没有一个是对还是错。对于每个问题,用户都可以选择答案。我想知道如何在所选答案上创建双向绑定。

Vue:

new Vue(
{
    el: "#app",

    data:
    {
        questions: [{}]
    }
}

示例问题模型:

{
    id: 1,
    name: "Which color is your favorite?",
    selectedAnswerId: null,
    selectedAnswerName: null,
    answers:
    [
        {id: 1, name: red, photoUrl: ".../red", selected: false},
        {id: 2, name: green, photoUrl: ".../green", selected: false},
        {id: 3, name: blue, photoUrl: ".../blue", selected: false},
    ]
}

组件:

var myAnswer =
{
    props: ["id", "name", "url", "selected"],
    template:
    `
        <div class="answer" v-bind:class="{selected: selected}">
            <img class="answer-photo" v-bind:src="url">
            <div class="answer-name">{{name}}</div>
        </div>
    `
};

Vue.component("my-question",
{
    props: ["id", "name", "answers"],
    components:
    {
        "my-answer": myAnswer
    },
    template:
    `
        <div class ="question">
            <div class="question-name">{{name}}</div>
            <div class="question-answers">
                <my-answer v-for="answer in answers" v-bind:id="answer.id" v-bind:name="answer.name" v-bind:url="answer.photoUrl" v-bind:selected="answer.selected"></my-answer>
            </div>
        </div>
    `
});

当用户通过单击div选择问题的答案时,我希望问题模型的selectedAnswerId / selectedAnswerName以及所选答案属性相应地设置。因此,为了完成这种双向绑定,我需要添加到组件中?我相信它需要输入元素和v模型,但我无法弄明白。此外,我只有一天进入Vue.js并且没有相关框架的经验。因此,如果我做任何明显错误或违反最佳做法的事情,那么也应该知道。提前谢谢!

1 个答案:

答案 0 :(得分:0)

答案将处理点击事件并发出(自定义)选定答案事件。问题将有自己的数据项来存储选定的答案ID;答案组件的selected道具将基于此。该问题将通过设置其selectedId来处理选定答案事件。

var myAnswer = {
  props: ["id", "name", "url", "selected"],
  template: `
        <div class="answer" v-bind:class="{selected: selected}"
         @click="setSelection()"
        >
            <img class="answer-photo" :src="url">
            <div class="answer-name">{{name}}</div>
        </div>
    `,
  methods: {
    setSelection() {
      this.$emit('selected-answer', this.id);
    }
  }
};

Vue.component("my-question", {
  props: ["id", "name", "answers"],
  data() {
    return {
      selectedId: null
    };
  },
  components: {
    "my-answer": myAnswer
  },
  template: `
        <div class ="question">
            <div class="question-name">{{name}}</div>
            <div class="question-answers">
                <my-answer v-for="answer in answers"
                :id="answer.id" :name="answer.name" :url="answer.photoUrl"
                :selected="answer.id === selectedId" @selected-answer="selectAnswer"></my-answer>
            </div>
        </div>
    `,
  methods: {
    selectAnswer(answerId) {
      this.selectedId = answerId;
    }
  }
});

new Vue({
  el: '#app',
  data: {
    questions: [{
      id: 1,
      name: "Which color is your favorite?",
      answers: [{
          id: 1,
          name: 'red',
          photoUrl: ".../red"
        },
        {
          id: 2,
          name: 'green',
          photoUrl: ".../green"
        },
        {
          id: 3,
          name: 'blue',
          photoUrl: ".../blue"
        },
      ]
    }]
  }
});
.answer {
  cursor: pointer;
}

.selected {
  background-color: #f0f0f0;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<div id="app">
  <my-question v-for="q in questions" :name="q.name" :answers="q.answers"></my-question>
</div>