做者:John Au-Yeung翻譯:瘋狂的技術宅css
原文:https://blog.logrocket.com/ex...html
未經容許嚴禁轉載前端
建立下拉菜單老是很麻煩的,特別是當咱們須要自定義樣式時,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-model
的 multiselect
組件綁定到 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.values
和 this.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
是對象的數組,帶有組標籤的屬性,在咱們的例子中爲 type
。 items
在下拉列表組中具備這些項目。
將 group-values
設置爲 items
屬性,這樣能夠將其用做組項目,把 group-label
設置爲 type
,能夠顯示爲組標題。把 label
設置爲 name
屬性,能夠將其顯示給用戶。
接下來把 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
構造函數來建立帶有 value
和 options
狀態的 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 和值。