VueSelect如何使用对象的属性设置初始值

时间:2019-07-09 05:27:03

标签: vuejs2 vue-select

我正在使用VueSelect进行地址选择。 国家,州,城市共有3个选择组件。

使用v-model时,通过使用reduce prop获得指定值而不是选项对象的效果很好。 这里我的问题是不能通过键值设置默认值。

我希望它通过id设置默认值,例如html select。 但它按原样显示键值,不受标签值的约束。
希望您能从我的解释中理解。
期望像v-选择vuetify。 vuetify example

<template>
  <div class="col-sm-6 ">
    <v-select
        v-model="address.country_id"
        :options="countryOptions"
        :reduce="country => country.id"
        label="name"
        @input="resetStateAndCity"
        :resetOnOptionsChange="true"
    />
  </div>

  <div class="col-sm-6">
    <v-select
        v-model="address.state_id"
        :options="stateOptions"
        :reduce="state => state.id"
        label="name"
        @input="resetCity"
        :resetOnOptionsChange="true"
    />
  </div>

  <div class="col-sm-6">
    <v-select
        v-model="address.city_id"
        :options="cityOptions"
        :reduce="city => city.id"
        label="name"
        :resetOnOptionsChange="true"
    />
  </div>
</template>
<script>
  import VSelect from 'vue-select'

  export default {
    components: {
      VSelect
    },
    data: function () {
      return {
        address: {
          city_id: null,
          state_id: null,
          country_id: null
        },
        countryOptions: [],
        stateOptions: [],
        cityOptions: []
      }
    },
    mounted() {
      this.$axios.get('/countries.json')
        .then(response => {
          this.countryOptions = response.data
        })
    },
    methods: {
      resetStateAndCity() {
        if (!this.address.country_id) return
        this.$axios.get(`/countries/${this.address.country_id}/states.json`)
          .then(response => {
            this.stateOptions = response.data
          })
        this.address.state_id = null
        this.address.city_id = null
        this.cityOptions = []
      },
      resetCity() {
        if (!this.address.country_id || !this.address.state_id) return
        this.address.city_id = null
        this.$axios.get(`/countries/${this.address.country_id}/states/${this.address.state_id}/cities.json`)
          .then(response => {
            this.cityOptions = response.data
          })
      }
    }
  }
</script>

1 个答案:

答案 0 :(得分:0)

我在下面概述了两种不同的方法。总的来说,我认为我更喜欢第二种方法,但这可能取决于您的情况,最适合您。

new Vue({
  el: '#app',

  components: {
    'v-select': VueSelect.VueSelect
  },

  data: function() {
    return {
      input: {
        user_id: 2
      },
      users: []
    }
  },
  
  methods: {
    getOptionLabel (option) {
      return (option && option.name) || ''
    }
  },
  
  created () {
    setTimeout(() => {
      this.users = [
        {
          id: 1,
          name: "John",
          last: "Doe"
        },
        {
          id: 2,
          name: "Harry",
          last: "Potter"
        },
        {
          id: 3,
          name: "George",
          last: "Bush"
        }
      ]
      
      const currentUser = this.users.find(user => user.id === this.input.user_id)
      
      this.$refs.select.updateValue(currentUser)
    }, 1000)
  }
})
<link rel="stylesheet" href="https://unpkg.com/vue-select@3.1.0/dist/vue-select.css">
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vue-select@3.1.0/dist/vue-select.js"></script>
<div id="app">
  <v-select
    ref="select"
    v-model="input.user_id"
    :options="users"
    :reduce="user => user.id"
    :get-option-label="getOptionLabel"
  ></v-select>
</div>

一个主要障碍是,当使用reduce时,Vue Select使用内部状态来跟踪当前选择的值。参见:

https://github.com/sagalbot/vue-select/blob/master/src/components/Select.vue#L833

更糟糕的是,在该状态下存储的值不是简化ID,而是options中的整个对象。因此,如果一开始没有options,它就陷入了一个混乱的局面,并且很难把它从混乱中拉出来。

在加载updateValue之后,我曾调用options给它一个踢。我还使用了道具get-option-label而不是label来避免在加载数据时显示数字。

另一种替代方法是仅在v-select可用时创建options,因为如果它们在首次创建时就全部存在,则可以正常工作。在等待数据时,可以将伪v-select用作占位符。看起来像这样:

new Vue({
  el: '#app',

  components: {
    'v-select': VueSelect.VueSelect
  },

  data: function() {
    return {
      input: {
        user_id: 2
      },
      users: []
    }
  },
  
  created () {
    setTimeout(() => {
      this.users = [
        {
          id: 1,
          name: "John",
          last: "Doe"
        },
        {
          id: 2,
          name: "Harry",
          last: "Potter"
        },
        {
          id: 3,
          name: "George",
          last: "Bush"
        }
      ]
    }, 1000)
  }
})
<link rel="stylesheet" href="https://unpkg.com/vue-select@3.1.0/dist/vue-select.css">
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vue-select@3.1.0/dist/vue-select.js"></script>
<div id="app">
  <v-select
    v-if="users.length === 0"
    key="dummy"
    disabled
    placeholder="Loading..."
  ></v-select>
  <v-select
    v-else
    v-model="input.user_id"
    :options="users"
    :reduce="user => user.id"
    label="name"
  ></v-select>
</div>

此处使用key很重要,因为它可以确保Vue不会重复使用相同的v-select,而是创建一个新的key。还有其他方法可以实现,但是ORMExecuteQuery("from customer"); 可能是最干净的。