Vue:在自定义复选框组件中与 v-model 绑定不起作用

use*_*906 3 checkbox vue.js vuejs2 v-model

我正在尝试构建一个自定义复选框组件,其中包含使用 v-for 循环从具有选项和值的数组生成的选项。如何将 v-model 正确绑定到复选框组件以使其正确更新?

现在的问题是模型只更新到最新选中的复选框,并没有给出包含所有选中选项的数组。

Vue.component('ui-checkbox', {
	 props: {   
    label: {
      type: String,
      required: true,
    },
    index: {
      type: Number
    },
    inputValue: {
      type: String
    }
  },
  methods: {
    onChange(e) {
      this.$emit('input', e.target.value);
    },
  },
	template: `<div>
    <input 
      :id="index"
      type="checkbox"
      :value="inputValue"
      @change="onChange" />
    <label :for="index">
      {{ label }}
    </label>
  </div>`,
})

new Vue({
  el: "#app",
  data: {
    checkOptions: [
      {
        label: 'Option 1',
        value: 'value of option 1',
      },
      {
        label: 'Option 2',
        value: 'value of option 2',
      },
      {
        label: 'Option 3',
        value: 'value of option 3',
      },
      {
        label: 'Option 4',
        value: 'value of option 4',
      },
    ],
    myCheckBoxModel: []
  },
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
   <span>checked Checkboxes: {{ myCheckBoxModel }} </span>
   <ui-checkbox
     v-for="(option, index) in checkOptions"
     v-model="myCheckBoxModel"
     :key="index"
     :index="index"
     :input-value="option.value"
     :label="option.label" />    
</div>
Run Code Online (Sandbox Code Playgroud)

Mic*_*evý 8

@Lana 提出的解决方案太复杂了。根本不需要该onChange方法 - 您想要的是使用 的内置功能v-model。见下文...

Vue.component('ui-checkbox', {
  props: {
    label: {
      type: String,
      required: true,
    },
    index: {
      type: Number
    },
    inputValue: {
      type: String
    },
    value: {
      type: Array
    }
  },
  computed: {
    model: {
      get() {
        return this.value
      },
      set(value) {
        this.$emit('input', value)
      }
    },
  },
  template: `<div>
        <input 
          :id="index"
          type="checkbox"
          :value="inputValue"
          v-model="model" />
        <label :for="index">
          {{ label }}
        </label>
      </div>`,
})

new Vue({
  el: "#app",
  data: {
    checkOptions: [{
        label: 'Option 1',
        value: 'value of option 1',
      },
      {
        label: 'Option 2',
        value: 'value of option 2',
      },
      {
        label: 'Option 3',
        value: 'value of option 3',
      },
      {
        label: 'Option 4',
        value: 'value of option 4',
      },
    ],
    myCheckBoxModel: []
  }
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  model: {{ myCheckBoxModel }}
  <ui-checkbox v-for="(option, index) in checkOptions" v-model="myCheckBoxModel" :key="index" :index="index" :input-value="option.value" :label="option.label" />
</div>
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下使用v-for indexaskey是有效的,但一般不建议使用,特别是如果复选框集是动态的并且可以在渲染它们的组件的生命周期内发生变化。


Lan*_*ana 6

当你做

this.$emit('input', e.target.value);
Run Code Online (Sandbox Code Playgroud)

它像

myCheckBoxModel = e.target.value
Run Code Online (Sandbox Code Playgroud)

所以它只是分配你点击的最后一个复选框的值myCheckBoxModel。如果要将所有选中的项目保留在 中myCheckBoxModel,则需要执行以下操作:

  1. valueui-checkbox组件添加属性以访问 的当前值myCheckBoxModelValue是此目标的默认属性名称(请参阅vue 指南)。
  2. 在你的onChange方法中将当前值复制到变量中,因为value直接改变属性不好
  3. 如果您的复选框被选中,将对应的值推送到数组。如果未选中该复选框,则从数组中删除对应的值
  4. input以结果数组作为值发出事件

this.$emit('input', e.target.value);
Run Code Online (Sandbox Code Playgroud)
myCheckBoxModel = e.target.value
Run Code Online (Sandbox Code Playgroud)

我不知道您是否需要以编程方式设置复选框状态,即当您更改复选框的状态时myCheckBoxModel相应地更改。如果这样做,则需要监视组件中的value属性ui-checkbox:根据其值是否在value数组中来设置复选框的状态。created如果您想通过以下方式初始化复选框的状态,请在钩子中执行相同的操作myChexkboxModel