从子组件中修改props.value

时间:2018-02-02 03:21:28

标签: vue.js vuejs2

我是Vue的新手并试图建立一个"下拉"零件。我想从像这样的父组件中使用它:

<my-dropdown v-model="selection"></my-dropdown>

其中selection在父项上存储为data,应更新以反映用户的选择。要做到这一点,我相信我的下拉组件需要一个value道具,当选择发生变化时,它需要发出input个事件。

但是,我还想从子项本身修改value,因为我希望能够自己使用下拉组件(我需要修改它,因为否则UI不会更新到如果组件单独使用,则反映新选择的值。

我是否可以像上面那样使用v-model绑定,但也可以修改孩子内部的值(似乎我不能,因为value是道具和孩子不能修改自己的道具。)

5 个答案:

答案 0 :(得分:5)

您需要为处理输入/值值的本地值设置计算属性代理。

props: {
  value: {
    required: true,
  }
},
computed: {
  mySelection: {
    get() {
      return this.value;
    },
    set(v) {
      this.$emit('input', v)
    }
  }
}

现在,您可以将模板设置为使用mySelection值来管理此组件内的数据,并在更改时,正确发出数据并始终与v模型同步({{1}当你在父母身上使用它时。

答案 1 :(得分:2)

您可以使用自定义表单输入组件

Form Input Components using Custom Events

基本上,您的自定义组件应接受value道具并在值更改时发出input事件

答案 2 :(得分:2)

如果要修改组件内的prop,我建议将“默认值”prop传递给组件。我就是这样做的

<MyDropdownComponent
  :default="defaultValue"
  :options="options"
  v-model="defaultValue"
/>

然后有两种方法可供选择 -

选项1 - 自定义下拉元素

当您使用自定义HTML时,您将无法设置所选属性。因此,您需要对您的方法充满创意。 在组件内部,您可以将默认值prop设置为组件创建时的数据属性。您可能希望以不同方式执行此操作,而是使用watcher。我已将其添加到下面的示例中。

export default {
  ...
  data() {
    return {
      selected: '',
    };
  },
  created() {
    this.selected = this.default;
  },
  methods: {
    // This would be fired on change of your dropdown.
    // You'll have to pass the `option` as a param here,
    // So that you can send  that data back somehow
    myChangeMethod(option) {
      this.$emit('input', option);
    },
  },
  watch: {
    default() {
      this.selected = this.default;
    },
  },
};

$emit会将数据传递回父组件,而父组件将不会被修改。如果您使用的是标准select元素,则无需执行此操作。

选项2 - 标准select

<template>
  <select
    v-if="options.length > 1"
    v-model="value"
    @change="myChangeMethod"
  >
    <option
      v-for="(option, index) of options"
      :key="option.name"
      :value="option"
      :selected="option === default"
    >{{ option.name }}</option>
  </select> 
</template>

<script>
export default {
  ...
  data() {
    return {
      value: '',
    };
  },
  methods: {
    // This would be fired on change of your dropdown
    myChangeMethod() {
      this.$emit('input', this.value);
    },
  },
};
</script>

这种方法绝对是最简单的,意味着您需要使用默认的select元素。

答案 3 :(得分:2)

您可以使用以下模式:

  1. 接受1输入道具
  2. 在数据中包含另一个变量
  3. 在创建时,将传入的道具白化为数据变量
  4. 使用观察者,观察传入道具的变化
  5. 在组件内部进行更改时,请发送更改
  6. 演示:

    'use strict';
    Vue.component('prop-test', {
      template: "#prop-test-template",
      props: {
        value: { // value is the default prop used by v-model
          required: true,
          type: String,
        },
      },
      data() {
        return {
          dataObject: undefined,
          // For testing purposes:
          receiveData: true,
          sendData: true,
        };
      },
      created() {
        this.dataObject = this.value;
      },
      watch: {
        value() {
          // `If` is only here for testing purposes
          if(this.receiveData)
          this.dataObject = this.value;
        },
        dataObject() {
          // `If` is only here for testing purposes
          if(this.sendData)
          this.$emit('input', this.dataObject);
        },
      },
    });
    
    var app = new Vue({
      el: '#app',
      data: {
        test: 'c',
      },
    });
    <script src="https://unpkg.com/vue@2.0.1/dist/vue.js"></script>
    <script type="text/x-template" id="prop-test-template">
      <fieldset>
        <select v-model="dataObject">
          <option value="a">a</option>
          <option value="b">b</option>
          <option value="c">c</option>
          <option value="d">d</option>
          <option value="e">e</option>
          <option value="f">f</option>
          <option value="g">g</option>
          <option value="h">h</option>
          <option value="i">i</option>
          <option value="j">j</option>
        </select>
        <!-- For testing purposed only: -->
        <br>
        <label>
          <input type="checkbox" v-model="receiveData">
          Receive updates
        </label>
        <br>
        <label>
          <input type="checkbox" v-model="sendData">
          Send updates
        </label>
        <!--/ For testing purposed only: -->
      </fieldset>
    </script>
    <div id="app">
      <prop-test v-model="test"></prop-test>
      <prop-test v-model="test"></prop-test>
      <prop-test v-model="test"></prop-test>
    </div>

    请注意,此演示有一项功能,您可以关闭每个选择框的事件传播,以便您可以测试这些值是否在本地正确更新,这当然不需要生产。

答案 4 :(得分:2)

Vue的理念是:“支持,事件向上”。它甚至在文档中说明了这一点:Composing Components

  

组件旨在一起使用,最常见的是   父子关系:组件A可以使用它自己的组件B.   模板。他们不可避免地需要彼此沟通:   父母可能需要将数据传递给孩子,孩子可能需要   告知父母孩子身上发生的事情。然而,   保持父母和孩子一样非常重要   通过明确定义的界面尽可能地分离。这确保了   每个组件的代码都可以相对编写和推理   隔离,从而使它们更易于维护并且可能更容易   重用。

     

在Vue中,父子组件关系可以概括为   支持,事件向上。父母将数据传递给孩子   道具,孩子通过事件向父母发送消息。让我们   看看他们下一步的工作方式。

不要尝试修改子组件中的值。告诉父组件有关某事的内容,如果父母关心,它可以对此做些什么。让孩子改变事物给孩子带来了太多责任。