VueJS传递默认道具而不参考子组件

时间:2018-03-09 11:17:32

标签: javascript vue.js ecmascript-6 reference vuejs2

我偶然发现了这种情况,我希望将prop传递给子组件,该子组件将是组件的default值,但只有在初始值为空时才会显示。

父组件:

<multi-line-input v-model="data.something" placeholder="Enter Something" :default="data.something"/>

子组件

props: {
  value: {
    type: String,
    default: ''
  },
  default: {
    type: String,
    default: ''
  },
},
methods: {
  emitBlur (e) {
    if (!this.value && this.default) {
      this.value = this.default
    }
    this.$emit('blur')
  },
  emitInput () {
    this.$emit('input', this.$el.value)
  }
}

所以我基本上想要实现的是,当组件加载时会从v-model获取值,它也会收到一个不应更改的default值,并且仅用作值当blur

上的实际值为空时

default的初始值为data.something,不应更改!

我试图使用JSON.parse(JSON.stringify(this.value))删除引用,但它似乎也不起作用!

1 个答案:

答案 0 :(得分:2)

因此,如果我正确理解您的问题,您需要此行为:在blur组件上的<multi-line-input>事件上,如果输入的值为空,则将值设置为默认值由父母指定(通过道具)。

首先,在组件中执行this.value = ...是一个错误。你不能修改道具,道具只能将数据从父传递给子,通过道具传递的数据不是你自己直接从组件内修改的。

尝试这样的事情:

&#13;
&#13;
Vue.component('multi-line-input', {
  template: '<input @blur="onBlur" @input="onInput" :value="value">',
  props: {
    value: {
      type: String,
      default: '',
    },
    default: {
      type: String,
      default: '',
    },
  },
  methods: {
    onBlur() {
      if (!this.value && this.default) {
        this.$emit('input', this.default);
      }
    },
    onInput(e) {
      this.$emit('input', e.target.value);
    },
  },
});

new Vue({
  el: '#app',
  data: {
    user: null,
    initialUser: null,
  },
  created() {
    // Pretend that I'm pulling this data from some API
    this.user = {
      name: 'Fred',
      email: 'fred@email.com',
      address: '123 Fake St',
    };
    
    // Make a copy of the data for the purpose of assigning the
    // default prop of each input
    this.initialUser = _.cloneDeep(this.user);
  },
});
&#13;
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

<div id="app">
  <template v-if="user">
    <multi-line-input v-model="user.name" :default="initialUser.name"></multi-line-input>
    <multi-line-input v-model="user.email" :default="initialUser.email"></multi-line-input>
    <multi-line-input v-model="user.address" :default="initialUser.address"></multi-line-input>
  </template>
</div>
&#13;
&#13;
&#13;

或者,如果您希望组件而不是父组件(通过道具)确定默认值,则可以执行以下操作:

&#13;
&#13;
Vue.component('multi-line-input', {
  template: '<input @blur="onBlur" @input="onInput" :value="value">',
  props: {
    value: {
      type: String,
      default: '',
    },
  },
  created() {
    this.def = this.value;
  },
  methods: {
    onBlur() {
      if (!this.value && this.def) {
        this.$emit('input', this.def);
      }
    },
    onInput(e) {
      this.$emit('input', e.target.value);
    },
  },
});

new Vue({
  el: '#app',
  data: {
    user: null,
  },
  created() {
    // Pretend that I'm pulling this data from some API
    this.user = {
      name: 'Fred',
      email: 'fred@email.com',
      address: '123 Fake St',
    };
  },
});
&#13;
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

<div id="app">
  <template v-if="user">
    <multi-line-input v-model="user.name"></multi-line-input>
    <multi-line-input v-model="user.email"></multi-line-input>
    <multi-line-input v-model="user.address"></multi-line-input>
  </template>
</div>
&#13;
&#13;
&#13;

但是我不推荐第二种方法,因为子组件实例在其整个生命周期中只有一个默认值。 Vue尽可能重用组件实例,因此如果Vue将它绑定到不同的父组件(如何/何时更新其自己的default状态?)它将无法工作。