vuetify學習第二天之v-combobox
目錄
文章目錄
內容
0、簡介
vuetify暫時未提供級聯組件,我們可以結合element-ui或者iview等ui組件庫的下拉部分,以及vuetify的v-combobox輸入框部分,實現漂亮的自定義級聯組件。
這裏使用iview的cascader組件和vuetify的combobox組件。
- 效果圖:
- 頁面源代碼:
<template>
<cas :data="options" @on-change="handleChange" :loadData="loadOption" transfer>
<v-combobox
:label="label"
chips
clearable
v-model="selected"
multiple
>
<template v-slot:selection="{ item }">
<v-chip
@click.stop
v-if="multiple"
close
@click:close="remove(item)"
small
outlined
color="green"
>{{ item.label }} </v-chip>
<v-chip @click.stop v-else small>{{ item.__label }}</v-chip>
</template>
</v-combobox>
</cas>
</template>
<script>
import { Cascader } from "iview";
export default {
name: "vCascader",
components: {
cas: Cascader
},
props: {
value: {},
label: {
type: String
},
url: {
type: String
},
itemText: {
type: String,
default: "name"
},
itemValue: {
type: String,
default: "id"
},
children: {
type: String,
default: "children"
},
multiple: {
type: Boolean,
default: false
},
showAllLevels: {
type: Boolean,
default: false
},
required: {
type: Boolean,
default: false
},
rules: {
type: Array
}
},
data() {
return {
options: [],
selected: [],
defaultRules: []
};
},
methods: {
handleChange(value, selectedData) {
console.log("start: ", this.selected);
// 獲取最後一級
const option = selectedData[selectedData.length - 1];
// 如果是多選,則默認只保存最後一級選項
if (this.multiple) {
// 將最後一級保存到selected中
if (this.selected.findIndex(o => o.value === option.value) < 0) {
this.selected.push(option);
}
// 返回已選中的值
console.log("end: ", this.selected);
this.$emit("input", this.transfer(this.selected));
} else {
// 單選,則需要判斷是否需要顯示所有級別
if (this.showAllLevels) {
// 顯示所有級別,將各級別label進行拼接
this.selected = [option.__label];
// 返回id數組
this.$emit("input", this.transfer(selectedData));
} else {
// 只顯示最後一級
this.selected = [option.label];
// 返回
this.$emit("input", this.transfer([option])[0]);
}
}
},
loadOption(item, callback) {
// 延遲加載次級選項
item.loading = true;
this.loadData(item.value)
.then(data => {
item.children = data;
item.loading = false;
callback();
})
.catch(() => {
item.loading = false;
callback();
});
},
loadData(pid) {
// 從指定的url地址加載數據,並格式化
return new Promise(resolve => {
this.axios
.get(this.url, {
params: {
pid: pid
}
})
.then(resp => {
const data = [];
for (let d of resp.data) {
const node = {
value: d[this.itemValue],
label: d[this.itemText]
};
if (d.isParent) {
node["children"] = [];
node["loading"] = false;
}
data.push(node);
}
resolve(data);
});
});
},
remove(item) {
this.selected = this.selected.filter(o => o.value !== item.value);
this.$emit("input", this.transfer(this.selected));
},
transfer(arr) {
return arr.map(({ label, value }) => {
const obj = {};
obj[this.itemText] = label;
obj[this.itemValue] = value;
return obj;
});
},
validate() {
if (this.required) {
this.$refs.form.validate();
}
}
},
created() {
this.loadData(0).then(data => {
this.options = data;
});
if (this.required) {
this.defaultRules.push(v => v.length > 0 || this.label + "不能爲空");
}
if (this.rules) {
this.rules.forEach(r => this.defaultRules.push(r));
}
},
watch: {
value: {
deep: true,
handler(val) {
if (!val) {
this.selected = [];
return;
}
if (val && this.showAllLevels && !this.multiple) {
this.selected = [val.map(o => o[this.itemText]).join("/")];
} else if (this.multiple && val) {
this.selected = val.map(o => {
return {
label: o[this.itemText],
value: o[this.itemValue]
};
});
} else {
this.selected = [val[this.itemText]];
}
}
}
}
};
</script>
<style scoped>
.ivu-cascader-menu-item {
font-size: 14px;
}
</style>
1、iview之cascader組件
- 官網地址:https://www.iviewui.com/components/cascader-en
- 缺點:選中展示爲文字,很單調。
1.1、簡介
級聯選擇框常用來從有明顯分級結果的數據集和中選取數據,比如省/市/縣,公司結構,商城分類等等。
1.2、常用屬性
- 頁面源代碼:
<template>
<cas :data="options" @on-change="handleChange" :loadData="loadOption" transfer></cas>
<template>
<script>
...
data() {
return {
options: []
...
}
...
methods: {
handleChange(val, selectData){...} // 選擇改變觸發
loadOption(val){...} // 次級數據延遲加載
...
}
...
名稱 | 默認值 | 描述 | 詳解 |
---|---|---|---|
data | [] | 需要渲染的數據數組 | 1.2.1.1 |
value | [] | 選中的數據 | 1.2.1.2 |
load-data | - | 延遲加載函數 | 1.2.1.2 |
1.2.1、詳細描述
1.2.1.1、data
- 示例:
常規形式:
data:[
{// 一級下拉框
text: '', // 每一項展示的內容
value: , // 每一項對應的key
children: [ // 二級下拉框
text: '',
value: ,
children: [...]
]
}
...
]
示例:
data: [
{
text: '手機',
value: 76,
children: [
{
text: '手機通訊',
value: 100,
children: [
text: '手機',
value: 260
]
}
]
}
...
]
- 詳解
名稱 | 類型 | 默認值 | 描述 |
---|---|---|---|
text | string | ‘’ | 每一項的顯示的內容 |
value | key | 每一項的唯一標誌 | |
children | array | [] | 子級下拉框數據 |
tips : value爲每一項的唯一標誌,建議用數據庫返回的每一項的id值。
1.2.1.2、value
- 示例:
示例數據:
[76, 100, 260]
itips : value 中存儲的爲選擇條目對應的vulue值的集合。
1.2.1.3 、load-data
- 示例:
// val 爲點擊條目對應的value值
loadData(val) {...} // load-data綁定的函數爲延遲處理函數,用來延遲加載次級數據。觸發時機:點擊上級條目的時候觸發。
1.3、常用事件
1.3.1、on-change
- 示例:
// onChange爲on-change綁定的處理函數
onChange(val, selectedData){...}
- 參數詳解
名稱 | 類型 | 默認值 | 描述 |
---|---|---|---|
val | array | [] | 選中條目對應value值集合 |
selectedData | array | [] | 選中條目對應對象集合 |
tips :val與selectedData都爲一維數組,只記錄選中的條目。
2、vuetify之chip組件
2.1、簡介
v-chip組件用來展示碎片化的信息,常被鑲嵌於插槽中。
- 頁面源代碼:
<template v-slot:selection="{ item }">
<v-chip
@click.stop
v-if="multiple"
close
@click:close="remove(item)"
small
outlined
color="green"
>{{ item.label }} </v-chip>
<v-chip @click.stop v-else small>{{ item.__label }}</v-chip>
</template>
2.2、常用屬性
名稱 | 默認值 | 描述 | 詳解 |
---|---|---|---|
close | false | 是否添加關閉圖標 | |
color | undefined | 顏色 | 1.2.1.2 |
outlined | false | 是否顯示幽靈樣式 | 1.2.1.2 |
small | false | 是否大小變小 | 1.2.1.2 |
tips : v-chip組件相對很簡單,不在做過多介紹,此處作爲插槽內容嵌入cascader,用來替換原顯示的文字,使cascader看起來更舒服。
2.3、常用事件
1.3.1、click:close
- 示例:
@click:close="remove(item)"
// remove爲click:close綁定的處理函數,用來刪除選中的某一項
remove(item){...}
- 參數詳解
名稱 | 類型 | 默認值 | 描述 |
---|---|---|---|
item | string/array | ‘’/[] | 要刪除的項 |
tips :只有屬性定義了close ,click:close纔有意思,用來點擊v-chip圖標上小叉號,刪除該項。
3、vuetify之combobox組件
- 官網地址:https://vuetifyjs.com/en/components/combobox
- 缺點:不能夠實現級聯選擇,只能實現簡單的下拉選擇。
3.1、簡介
v-combobox爲帶有自動完成功能,允許用戶展示項目中不存在的值。
3.2、常用屬性
- 頁面源代碼:
<v-combobox
:items="items"
:label="label"
chips
clearable
v-model="selected"
multiple
></v-combobox>
...
名稱 | 默認值 | 描述 | 詳解 |
---|---|---|---|
items | [] | 需要渲染的數據數組 | 3.2.1.1 |
value | ‘’/[] | 選中的數據 | 3.2.1.2 |
label ’‘ | 該下拉框提示標籤 | 延遲加載函數 | 3.2.1.3 |
clearable | false | 是否可清除 | 3.2.1.4 |
chips | false | 是否展示爲chip | 3.2.1.5 |
multiple | false | 是否可多選 | 3.2.1.6 |
3.2.1、詳細描述
3.2.1.1、items
- 示例:
示例:
data: [
{
text: '手機',
value: 76,
},
{
text: '電腦',
value: 100
}
...
]
- 詳解
名稱 | 類型 | 默認值 | 描述 |
---|---|---|---|
text | string/number/object | 每一項的顯示的內容 | |
value | string/number/object | 每一項的唯一標誌 |
tips :v-combobox作爲下拉框,顯示內容比較簡單。
3.2.1.2、value與iview組件類似
- 示例:
示例數據:
[76, 100, 260]
或者
67
itips : value是單相數值還是數組有 multiple決定,數據類型由items中數據決定。multiple爲true,value爲數組;multiple爲false,value值爲單值。
3.2.1.3 、label
- 作用同input的label
3.2.1.4、clearable
- 是否可清楚,既input框後帶X號標記,點擊可一次清空input框。
3.2.1.5、multipl 多選
3.3、常用事件與插槽
- 參考官網和iview,這裏不在詳述。
4、自定義v-cascader組件
因爲iview下拉框和vuetify下拉框各自有缺點和優點,剛好實現互補,這裏就結合2者自定義實現本文開始展示的級聯插件。
4.1、簡單解析
- iview部分爲下拉框部分結構、樣式和行爲,vuetify爲輸入框部分結構、樣式和行爲
- 橋樑: 通過監聽i-cascader的value值的變化,改變v-conbobox的value的變化,實現整體的下拉框選擇和輸入框展示更新。
- 渲染數據爲請求後,稍加修改爲符合展示的數據
- v-combobox 允許展示渲染數據沒有的項
- data中props數組爲自定義屬性名稱、類型及默認值,詳細參考vue自定義組件。
後記: 剛開始學習vuetify ui組件,如有錯誤之處歡迎指正,共同進步,本人QQ:806797785