代码之家  ›  专栏  ›  技术社区  ›  Sletheren

VueJS传递默认属性而不引用子组件

  •  1
  • Sletheren  · 技术社区  · 6 年前

    我偶然发现了这样一种情况,我想将道具传递给一个子组件,该子组件将是 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 它还将收到 违约 不应更改的值,仅在上的实际值为空时用作值 blur

    这个 违约 初始值为 data.something 它不应该改变!

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

    1 回复  |  直到 6 年前
        1
  •  3
  •   Decade Moon    6 年前

    因此,如果我正确理解了你的问题,你希望这种行为: blur 您的 <multi-line-input> 组件,如果输入值为空,则将该值设置为父级(通过道具)指定的默认值。

    首先,这样做是错误的 this.value = ... 在组件中。您不能修改道具,道具只能将数据从父级传递到子级,通过道具传递的数据不是您可以直接从组件内部修改的。

    尝试以下操作:

    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);
      },
    });
    <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>

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

    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',
        };
      },
    });
    <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>

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