In VueJS is it possible to bind something with v-model that is then rebound to another child?

馋奶兔 提交于 2019-12-02 03:41:17

Update: You can propagate v-model-ability down a hierarchy by making a writable computed based on the prop (the prop must be named 'value'). The get function obviously returns the prop value; the set function does the $emit.

The computed spec is entirely fixed, so I have extracted it as a constant.

const vModelComputed = {
  get() {
    return this.value;
  },
  set(newValue) {
    this.$emit('input', newValue);
  }
};

new Vue({
  el: '#app',
  data: {
    numParticipants: 1
  },
  components: {
    middleComponent: {
      props: ['value'],
      template: '<div>Value: {{value}} <q-numeric v-model="localValue"></q-numeric></div>',
      computed: {
        localValue: vModelComputed
      },
      components: {
        qNumeric: {
          props: ['value'],
          template: '<div><input v-model="localValue" type="number"> inner value: {{value}}</div>',
          computed: {
            localValue: vModelComputed
          }
        }
      }
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<div id="app">
  Participants: {{numParticipants}}
  <middle-component v-model="numParticipants"></middle-component>
</div>

This is what I ended up with - seemed like the simplest approach. I was kind of hoping Vue would have a mechanism to hide this away when the 'middle' component effectively promises not to change the model, but just wants to hand it on to a child.

Basically, I created an intermediary data element ivalue, and initialised it in the mounted() event, and use the input() event of the child to emit an input() event back to the parent.

<template>
  <tr>
    <td class="text-right"><slot></slot></td>
    <td class="text-right">
      <q-numeric
        v-model="ivalue"
        :min="min"
        :max="max"
        :step="step"
        @input="$emit('input', ivalue)"
      ></q-numeric>
    </td>
  </tr>
</template>

<script>
  export default {
    data: () => ({
      ivalue: 0
    }),
    mounted () {
      this.ivalue = this.value
    },
    props: {
      label: String,
      value: Number,
      min: {
        type: Number,
        default: 1
      },
      max: {
        type: Number,
        default: 250000
      },
      step: {
        type: Number,
        default: 1
      }
    }
  }
</script>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!