【问题标题】:VueTwo Way Data Binding with Nested ComponentsVueTwo Way 数据绑定与嵌套组件
【发布时间】:2017-03-28 20:22:36
【问题描述】:

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

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 选择问题的答案时,我希望相应地设置 Question 模型的 selectedAnswerId/selectedAnswerName 以及 answers selected 属性。因此,为了完成这种双向绑定,我需要向我的组件添加什么?我相信它需要输入元素和 v-model,但我不太明白。另外,我只接触了 Vue.js 一天,并且没有相关框架的经验。因此,如果我在做任何公然错误或违反最佳实践的事情,我也很高兴知道这一点。提前致谢!

【问题讨论】:

  • 好吧,有两种方式绑定,你应该有一些输入有 v-model 指令它绑定到一些数据。到目前为止我在这里看不到任何输入......你呢是否想使用select 输入来选择答案?
  • 我希望用户单击包含名称和图片的答案 div。因此,如果用户想选择红色作为自己喜欢的颜色,他们会点击标题为“红色”的红色图片。因此,我相信我需要一个隐藏的输入元素,其中答案 div 包含在触发正确输入的标签中。
  • 您根本不需要输入。您只需要您的组件接受一个值并发出输入事件。 vuejs.org/v2/guide/…

标签: vue.js


【解决方案1】:

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

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>

【讨论】:

    猜你喜欢
    • 2012-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 2014-07-24
    • 1970-01-01
    • 2016-12-24
    相关资源
    最近更新 更多