vuetify 學習第二天之v-combobox-自定義級聯組件v-cascader封裝

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 }}&nbsp;</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組件

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 }}&nbsp;</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組件

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章