2

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

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

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

<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>
4

1 回答 1

4

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

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>

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

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

更糟糕的是,存储在该状态中的值不是简化后的 id,而是来自options. 因此,如果最初没有任何options东西,它就会陷入正确的混乱状态,并且很难将其从混乱中恢复出来。

加载updateValue完毕后,我已经调用了它。options我还使用了道具get-option-label,而不是label避免在加载数据时显示数字。

另一种方法是仅在可用时创建,因为如果它们在首次创建v-selectoptions都存在,则它可以正常工作。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内容,而是创建一个新的。还有其他方法可以实现这一点,但 akey可能是最干净的。

于 2019-07-10T22:16:52.370 回答