【问题标题】:Vue binding parent and child componentsvue绑定父子组件
【发布时间】:2018-07-03 22:34:30
【问题描述】:

如何在 Vue.js 中将父模型绑定到子模型?

下面的这些代码可以正常工作。如果我手动填写输入,则子模型将其值返回给父模型。

但问题是,如果来自父级的 AJAX 请求的数据集,输入不会自动填充。

谁能帮我解决这个问题?

Form.vue

<template>
    <form-input v-model="o.name" :fieldModel="o.name" @listenChanges="o.name = $event"/>
    <form-input v-model="o.address" :fieldModel="o.address" @listenChanges="o.address = $event"/>
</template>

<script>
    import FormInput from '../share/FormInput.vue'

    export default {
        data () {
            return {
                o: {
                    name: '',
                    address: ''
                }
            }
        },
        components: { 'form-input': FormInput },
        created: function() {
            axios.get('http://api.example.com')
                .then(response => { 
                    this.o.name = response.data.name
                    this.o.address = response.data.address
                })
                .catch(e => { console.log(e) })
        }
    }
</script>

FormInput.vue

<template>
    <input type="text" v-model='fieldModelValue' @input="forceUpper($event, fieldModel)">
</template>

<script>
    export default {
        props: ['fieldModel'],
        data() {
            return {
                fieldModelValue: ''
            }
        },
        mounted: function() {
            this.fieldModelValue = this.fieldModel;
        },
        methods: {
            forceUpper(e, m) {
                const start = e.target.selectionStart;
                e.target.value = e.target.value.toUpperCase();
                this.fieldModelValue = e.target.value.toUpperCase();
                this.$emit('listenChanges', this.fieldModelValue)
            }
        }
    }
</script>

【问题讨论】:

  • 使用v-bind而不是v-model
  • 在父模板中,绑定 Props=fieldModel。
  • @Ohgodwhy 我应该更改哪个 v-model?
  • @Sphinx 它实际上是绑定的,我已经更新了代码
  • 还是不行?

标签: javascript vue.js vuejs2


【解决方案1】:

如果您利用v-model in components,事情会变得更简单。

如果您将v-model 放在组件上,该组件应采用名为value 的道具,并应发出input 事件以触发其更新。

我喜欢创建一个computed 来隐藏事件发射,并允许我在我的组件中只使用v-model computed

new Vue({
  el: '#app',
  data: {
    o: {
      name: '',
      address: ''
    }
  },
  components: {
    'form-input': {
      template: '#form-input',
      props: ['value'],
      computed: {
        fieldModelValue: {
          get() {
            return this.value;
          },
          set(newValue) {
            this.$emit('input', newValue.toUpperCase());
          }
        }
      }
    }
  },
  // Simulate axios call
  created: function() {
    setTimeout(() => {
      this.o.name = 'the name';
      this.o.address = 'and address';
    }, 500);
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  Name ({{o.name}})
  <form-input v-model="o.name"></form-input>
  Address ({{o.address}})
  <form-input v-model="o.address"></form-input>
</div>

<template id="form-input">
    <input type="text" v-model='fieldModelValue'>
</template>

【讨论】:

  • 非常感谢,您的解释帮助我摆脱了this Vue warning,而不会丢失数据同步,终于!
【解决方案2】:

mounted() 挂钩阻止来自父级的后续更新。

移除挂载并将 v-model 更改为 'fieldModel'

<template>
    <input type="text" :value='fieldModel' @input="forceUpper($event, fieldModel)">
</template>

<script>
  export default {
    props: ['fieldModel'],
    data() {
      return {
          fieldModelValue: ''
      }
    },
    // mounted: function() {
    //   this.fieldModelValue = this.fieldModel;
    // },
    methods: {
      forceUpper(e, m) {
        const start = e.target.selectionStart;
        e.target.value = e.target.value.toUpperCase();
        this.fieldModelValue = e.target.value.toUpperCase();
        this.$emit('listenChanges', this.fieldModelValue)
      }
    }
  }
</script>

演示 CodeSandbox

【讨论】:

  • 不要使用v-model,使用valuev-model 是双向的,你想要单向绑定。
  • 如果你在处理返回值,v-model不是,所以它没有做双向绑定。
  • 我在这里评论你的代码,特别是这一行:v-model='fieldModel' @input="forceUpper($event, fieldModel)" 它应该是:value 而不是v-model,因为你正在分别处理input 事件。跨度>
  • 你的两个答案都达到了目标。顺便说一句,RichardMatsen 的回答给我警告说 避免直接改变道具,因为只要父组件重新渲染,该值就会被覆盖。相反,请使用基于道具值的数据或计算属性。。所以我选择了罗伊的答案。
  • 很公平,他有更全面的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
  • 2020-04-15
  • 1970-01-01
  • 1970-01-01
  • 2021-06-27
  • 2018-02-13
相关资源
最近更新 更多