简体   繁体   English

自定义 Vue 组件上的 v-model 不会更改输入值

[英]v-model on custom Vue component not changing value on input

I'm trying to create a customCombobox component that works like a normal v-combobox with one addition - after user presses tab key, it will select the first option automatically (if there are any).我正在尝试创建一个customCombobox组件,该组件的工作原理与普通的v-combobox类似,但用户按下tab键后,它会自动将 select 设置为第一个选项(如果有的话)。

What I've done so far looks good but v-model on this field doesn't work (it's always null ).到目前为止我所做的看起来不错,但这个领域v-model不起作用(它总是null )。

<template>
  <v-combobox ref="combobox" :rules="rules"
              @keydown.tab.prevent="selectFirst"
              :value="innerValue" :label="label"
              :items="items"

  >

  </v-combobox>
</template>
<script>
module.exports = {
  props: ['value', 'label', 'items', 'rules'],
  data() {
    return {
      innerValue:null,
    }
  },
  watch:{
    value(_new){
       this.innerValue = _new
      this.$emit('input',[_new])
      this.$emit('change')
    }
  },
  methods: {
    selectFirst() {
      var combobox = this.$refs.combobox
      var filteredItems = combobox.filteredItems
      if (filteredItems.length){
          this.innerValue = filteredItems[0]
      }
    }
  },
  computed: {

  }
}
</script>

Do you know why?你知道为什么吗?

You can use a computed setter in the custom component to handle the v-model from the parent and pass it down to its own child v-combobox :您可以在自定义组件中使用计算的 setter 来处理来自父级的v-model并将其传递给它自己的子v-combobox

Custom component:自定义组件:

<v-combobox v-model="selected" v-bind="$attrs"></v-combobox>
computed: {
  selected: {
    get() {
      return this.value;
    },
    set(val) {
      this.$emit('input', val);
    }
  }
}

Using v-bind="$attrs" also passes down all of the props from the parent.使用v-bind="$attrs"还会传递来自父级的所有道具。 Here's a demo:这是一个演示:

 Vue.component('comp', { props: ['value'], template: ` <v-combobox v-model="selected" v-bind="$attrs"></v-combobox> `, computed: { selected: { get() { return this.value; }, set(val) { this.$emit('input', val); } } } }) new Vue({ el: '#app', vuetify: new Vuetify(), data() { return { selected: 'Vue', label: 'This is my label', rules: ['These are my rules'], items: ['Programming', 'Design', 'Vue', 'Vuetify'] } } })
 #app { padding: 48px; }
 <div id="app"> <v-app id="inspire"> Selected in parent: {{ selected }} <comp v-model="selected":label="label":items="items"></comp> </v-app> </div> <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM