探索 Vue-Multiselect

做者:John Au-Yeung

翻譯:瘋狂的技術宅css

原文:https://blog.logrocket.com/ex...html

未經容許嚴禁轉載前端

Exploring Vue-Multiselect

建立下拉菜單老是很麻煩的,特別是當咱們須要自定義樣式時,select 元素的做用很是有限。若是用 Vue 來構建咱們的應用,則能夠用一些組件來幫助簡化工做。vue

在本文中,咱們將研究怎樣用 Vue-Multiselect 庫來改善下拉菜單的效果。程序員

準備工做

首先,運行如下命令來安裝 Vue-Multiselect:web

npm install vue-multiselect --save

還能夠經過 <script> 標籤添加庫,並添加與包相關聯的 CSS:面試

<script src="https://unpkg.com/vue-multiselect@2.1.0"></script>
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect@2.1.0/dist/vue-multiselect.min.css">

而後,在咱們的組件中,能夠編寫如下代碼:vuex

<template>
  <div>
    <multiselect v-model="value" :options="options"></multiselect>
    <p>{{value}}</p>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";

export default {
  components: { Multiselect },
  data() {
    return {
      value: null,
      options: ["foo", "baz", "baz"]
    };
  }
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

如今 Multiselect 組件已註冊到該組件。咱們把帶有 v-modelmultiselect 組件綁定到 value 狀態。再把 options 屬性設置爲 options,這樣可使其具備字符串數組。npm

這樣,顯示給用戶的值將會與所選值的相同,能夠從下拉菜單下方的 <p> 標籤中獲得驗證。另外要注意,咱們用 style 標籤從包中添加了樣式。segmentfault

單選對象

若是咱們想要向用戶顯展現項目,而且這些項目與要顯示的值不同,那麼就須要有一組可供選擇的對象。

例如:

<template>
  <div>
    <multiselect track-by="name" label="name" v-model="value" :options="options"></multiselect>
    <p>{{value}}</p>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";

export default {
  components: { Multiselect },
  data() {
    return {
      value: null,
      options: [
        { name: "Orange", value: "orange" },
        { name: "Apple", value: "apple" },
        { name: "Grape", value: "grape" }
      ]
    };
  }
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

咱們把 label 設置爲 name,這樣就能夠經過 name 屬性來顯示內容。如今當咱們選擇一個值時,選擇的是整個對象,而且在選擇項目時把 value 設置成了所選的對象。

添加搜索

因爲 searchable 屬性的默認設置爲 true,因此可使用搜索功能。能夠用 custom-label 屬性顯示下拉菜單的自定義文本,咱們把屬性設置爲一個函數。

能夠這樣寫:

<template>
  <div>
    <multiselect
      track-by="name"
      label="name"
      :custom-label="nameFormatter"
      v-model="value"
      :options="options"
    ></multiselect>
    <p>{{value}}</p>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";

export default {
  components: { Multiselect },
  data() {
    return {
      value: null,
      options: [
        { name: "Orange", color: "orange", value: "orange" },
        { name: "Apple", color: "red", value: "apple" },
        { name: "Grape", color: "purple", value: "grape" }
      ]
    };
  },
  methods: {
    nameFormatter({ name, color }) {
      return `${name} - ${color}`;
    }
  }
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

如今能夠在爲每一個條目顯示的 nameFormatter 中獲得返回的內容。

多選

Vue-Multiselect 還支持多種選擇。例如:

<template>
  <div>
    <multiselect track-by="name" label="name" v-model="value" :options="options" multiple></multiselect>
    <p>{{value}}</p>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";

export default {
  components: { Multiselect },
  data() {
    return {
      value: null,
      options: [
        { name: "Orange", value: "orange" },
        { name: "Apple", value: "apple" },
        { name: "Grape", value: "grape" }
      ]
    };
  }
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

能夠在 multiselect 中添加 multiple 來啓用多選。經過填充 selection 插槽來添加在選定內容時要顯示文本,以下所示:

<template>
  <div>
    <multiselect track-by="name" label="name" v-model="value" :options="options" multiple>
      <template slot="selection" slot-scope="{ values, search, isOpen }">
        <span v-if="values.length">{{ values.length }} options selected</span>
      </template>
    </multiselect>
    <p>{{value}}</p>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";

export default {
  components: { Multiselect },
  data() {
    return {
      value: null,
      options: [
        { name: "Orange", value: "orange" },
        { name: "Apple", value: "apple" },
        { name: "Grape", value: "grape" }
      ]
    };
  }
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

selection 插槽有帶選定值的 values 屬性。 isOpen 用來指示菜單是否打開,search 用來設置搜索詞。

容許輸入標籤

還可讓用戶經過 Vue-Multiselect 來添加標籤。

能夠經過下面的代碼讓用戶添加標籤:

<template>
  <div>
    <multiselect v-model="values" taggable @tag="addTag" :options="options" multiple></multiselect>
    <p>{{values}}</p>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";

export default {
  components: { Multiselect },
  data() {
    return {
      values: [],
      options: ["orange", "apple", "grape"]
    };
  },
  methods: {
    addTag(newTag) {
      this.options.push(newTag);
      this.values.push(newTag);
    }
  }
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

咱們經過添加 taggable prop 來使用戶可以輸入本身的標籤,並經過 addTag 方法來監聽 multiselect 發出的 tag 事件。它使用帶有標籤名稱的 newTag 參數。

在該方法中,咱們添加了 this.valuesthis.options,這樣能夠把新標籤添加到選項列表和所選值的列表中。

自定義選項模板

在下拉菜單能夠包含文本和圖片是 Vue-Multiselect 的一大功能。

能夠這樣寫:

<template>
  <div>
    <multiselect v-model="values" :options="options">
      <template slot="singleLabel" slot-scope="props">
        <img class="option-image" :src="props.option.img">
        <div>
          <span>{{ props.option.title }}</span>
        </div>
      </template>
      <template slot="option" slot-scope="props">
        <img class="option-image" :src="props.option.img">
        <div>
          <span>{{ props.option.title }}</span>
        </div>
      </template>
    </multiselect>
    <p>{{values}}</p>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";

export default {
  components: { Multiselect },
  data() {
    return {
      values: [],
      options: [
        {
          title: "orange",
          img:
            "https://secure.webtoolhub.com/static/resources/icons/set114/5cfa0390.png"
        },
        {
          title: "apple",
          img:
            "https://images.squarespace-cdn.com/content/v1/56ed6e3b1bbee05366b9f7a5/1464743651591-TJG1VO66UK1GI9LJ5WDO/ke17ZwdGBToddI8pDm48kHhlTY0to_qtyxq77jLiHTtZw-zPPgdn4jUwVcJE1ZvWhcwhEtWJXoshNdA9f1qD7T-j82ScS_xjTqFYGqFrT72qZ_E0ELtHpOZiWcSG1QwIMeEVreGuQ8F95X5MZTW1Jw/lodi-apple.png?format=300w"
        },
        {
          title: "grape",
          img:
            "https://icons.iconarchive.com/icons/martin-berube/food/256/grapes-icon.png"
        }
      ]
    };
  }
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

<style>
.option-image {
  width: 100px;
}
</style>

用下拉菜單項的圖像和文本填充 singleLabel 插槽。選項插槽的填充方式與填充下拉選項的方式相同。

選項組

咱們還能夠對選項進行分組,例如:

<template>
  <div>
    <multiselect
      group-values="items"
      group-label="type"
      group-select
      v-model="value"
      :options="options"
      label="name"
    ></multiselect>
    <p>{{value}}</p>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";

export default {
  components: { Multiselect },
  data() {
    return {
      value: undefined,
      options: [
        {
          type: "fruit",
          items: [{ name: "apple" }, { name: "orange" }]
        },
        {
          type: "drink",
          items: [{ name: "beer" }, { name: "wine" }]
        }
      ]
    };
  }
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

options 是對象的數組,帶有組標籤的屬性,在咱們的例子中爲 typeitems 在下拉列表組中具備這些項目。

group-values 設置爲 items 屬性,這樣能夠將其用做組項目,把 group-label 設置爲 type ,能夠顯示爲組標題。把 label 設置爲 name 屬性,能夠將其顯示給用戶。

Vuex 集成

接下來把 Vue-Multiselect 與 Vuex 集成在一塊兒,這樣就能夠把選擇的結果存在 Vuex 存儲而不是組件中。

代碼:

main.js
import Vue from "vue";
import App from "./App.vue";
import Vuex from "vuex";

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    value: "apple",
    options: ["apple", "orange", "grape"]
  },
  mutations: {
    updateValue(state, value) {
      state.value = value;
    }
  },
  actions: {
    updateValueAction({ commit }, value) {
      commit("updateValue", value);
    }
  }
});

Vue.config.productionTip = false;

new Vue({
  store,
  render: h => h(App)
}).$mount("#app");
App.vue
<template>
  <div>
    <multiselect :value="value" @input="updateValueAction" :options="options"></multiselect>
    <p>{{value}}</p>
  </div>
</template>

<script>
import Multiselect from "vue-multiselect";
import Vuex from "vuex";

const { mapActions, mapState } = Vuex;

export default {
  components: {
    Multiselect
  },
  computed: {
    ...mapState(["value", "options"])
  },
  methods: {
    ...mapActions(["updateValueAction"])
  }
};
</script>

<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>

main.js 中,咱們用 Vuex.Store 構造函數來建立帶有 valueoptions 狀態的 store。咱們有一個更新值的 mutation,updateValueAction 用於更新值的狀態,而後將 store 存儲在傳給 Vue 構造函數的對象中。

App.vue 中,咱們沒有把下拉菜單中選擇的值與 v-model 綁定在一塊兒,而是經過 mapState 映射狀態從 store 中獲取狀態。經過 mapActions 映射 store 中的 updateValueAction 來更新值。

咱們經過偵聽 input 事件來獲取項目,並調用 updateValueAction 以經過變異在 Vuex store 中更新 value 狀態。另外,咱們從 store 中設置 value 屬性的值。input 事件和 value 代替了 v-model.。

還能夠經過 mapState 方法從 Vuex 存儲的 options 狀態中設置 options

總結

Vue-Multiselect 是一個很是靈活的下拉菜單組件,能讓咱們建立包含圖片和有格式化內容的菜單項的下拉菜單。

還能夠對下拉選項進行分組,並啓用多個 selection 和 tag。它可以與 Vuex 集成在一塊兒,使咱們可以從 store 獲取並設置 options 和值。


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索