組件:SelectTree
<template>
? <el-select :value="valueTitle" :clearable="clearable" @clear="clearHandle">
? ? <el-input
? ? ? class="selectInput"
? ? ? :placeholder="placeholder"
? ? ? v-model="filterText">
? ? </el-input>
? ? <el-option :value="valueTitle" :label="valueTitle" class="options">
? ? ? <el-tree? id="tree-option"
? ? ? ? ref="selectTree"
? ? ? ? :accordion="accordion"
? ? ? ? :data="options"
? ? ? ? :props="props"
? ? ? ? :node-key="props.value"? ?
? ? ? ? :default-expanded-keys="defaultExpandedKey"
? ? ? ? :filter-node-method="filterNode"
? ? ? ? @node-click="handleNodeClick">
? ? ? </el-tree>
? ? </el-option>
? </el-select>
</template>
<script>
export default {
? name: "el-tree-select",
? props:{
? ? /* 配置項 */
? ? props:{
? ? ? type: Object,
? ? ? default:()=>{
? ? ? ? return {
? ? ? ? ? value:'id',? ? ? ? ? ? // ID字段名
? ? ? ? ? label: 'title',? ? ? ? // 顯示名稱
? ? ? ? ? children: 'children'? ? // 子級字段名
? ? ? ? }
? ? ? }
? ? },
? ? /* 選項列表數(shù)據(jù)(樹形結(jié)構(gòu)的對象數(shù)組) */
? ? options:{
? ? ? type: Array,? ? ?
? ? ? default: ()=>{ return [] }
? ? },
? ? /* 初始值 */
? ? value:{
? ? ? type: Number,
? ? ? default: ()=>{ return null }
? ? },
? ? /* 可清空選項 */
? ? clearable:{
? ? ? type:Boolean,
? ? ? default:()=>{ return true }
? ? },
? ? /* 自動收起 */
? ? accordion:{
? ? ? type:Boolean,
? ? ? default:()=>{ return false }
? ? },
? ? placeholder:{
? ? ? type:String,
? ? ? default:()=>{return "檢索關(guān)鍵字"}
? ? }
? },
? data() {
? ? return {
? ? ? filterText: '',
? ? ? valueId:this.value,? ? // 初始值
? ? ? valueTitle:'',
? ? ? defaultExpandedKey:[]? ?
? ? }
? },
? mounted(){
? ? this.initHandle()
? },
? methods: {
? ? // 初始化值
? ? initHandle(){
? ? ? if(this.valueId){
? ? ? ? this.valueTitle = this.$refs.selectTree.getNode(this.valueId).data[this.props.label]? ? // 初始化顯示
? ? ? ? this.$refs.selectTree.setCurrentKey(this.valueId)? ? ? // 設(shè)置默認(rèn)選中
? ? ? ? this.defaultExpandedKey = [this.valueId]? ? ? // 設(shè)置默認(rèn)展開
? ? ? }
? ? ? this.initScroll()
? ? },
? ? // 初始化滾動條
? ? initScroll(){
? ? ? this.$nextTick(()=>{
? ? ? ? let scrollWrap = document.querySelectorAll('.el-scrollbar .el-select-dropdown__wrap')[0]
? ? ? ? let scrollBar = document.querySelectorAll('.el-scrollbar .el-scrollbar__bar')
? ? ? ? scrollWrap.style.cssText = 'margin: 0px; max-height: none; overflow: hidden;'
? ? ? ? scrollBar.forEach(ele => ele.style.width = 0)
? ? ? })
? ? },
? ? // 切換選項
? ? handleNodeClick(node){
? ? ? this.valueTitle = node[this.props.label]
? ? ? this.valueId = node[this.props.value]
? ? ? this.$emit('getValue',this.valueId)
? ? ? this.defaultExpandedKey = []
? ? },
? ? // 清除選中
? ? clearHandle(){
? ? ? this.valueTitle = ''
? ? ? this.valueId = null
? ? ? this.defaultExpandedKey = []
? ? ? this.clearSelected()
? ? ? this.$emit('getValue',null)
? ? },
? ? /* 清空選中樣式 */
? ? clearSelected(){
? ? ? let allNode = document.querySelectorAll('#tree-option .el-tree-node')
? ? ? allNode.forEach((element)=>element.classList.remove('is-current'))
? ? },
? ? filterNode(value, data) {
? ? ? if (!value) return true;
? ? ? return data.name.indexOf(value) !== -1;
? ? }
? },
? watch: {
? ? value(){
? ? ? this.valueId = this.value
? ? ? this.initHandle()
? ? },
? ? filterText(val) {
? ? ? this.$refs.selectTree.filter(val);
? ? }
? },
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
? .el-scrollbar .el-scrollbar__view .el-select-dropdown__item{
? ? height: auto;
? ? max-height: 274px;
? ? padding: 0;
? ? overflow: hidden;
? ? overflow-y: auto;
? }
? .el-select-dropdown__item.selected{
? ? font-weight: normal;
? }
? ul li >>>.el-tree .el-tree-node__content{
? ? height:auto;
? ? padding: 0 20px;
? }
? .el-tree-node__label{
? ? font-weight: normal;
? }
? .el-tree >>>.is-current .el-tree-node__label{
? ? color: #409EFF;
? ? font-weight: 700;
? }
? .el-tree >>>.is-current .el-tree-node__children .el-tree-node__label{
? ? color:#606266;
? ? font-weight: normal;
? }
? .selectInput{
? ? padding: 0 5px;
? ? box-sizing: border-box;
? }
</style>
調(diào)用:
<template>
? <div id="app">
? ? <h1>{{`基于Element-UI組件改造的樹形選擇器`}}:</h1>
? ? <!-- 調(diào)用樹形下拉框組件 -->
? ? <SelectTree
? ? ? :props="props"
? ? ? :options="optionData"
? ? ? :value="valueId"
? ? ? :clearable="isClearable"
? ? ? :accordion="isAccordion"
? ? ? @getValue="getValue($event)"
? ? />
? ? ID為:{{valueId}}
? </div>
</template>
<script>
import SelectTree from "./components/treeSelect.vue";
export default {
? name: "app",
? components: {
? ? SelectTree
? },
? data() {
? ? return {
? ? ? isClearable: true, // 可清空(可選)
? ? ? isAccordion: true, // 可收起(可選)
? ? ? valueId: 1, // 初始ID(可選)
? ? ? props: {
? ? ? ? // 配置項(必選)
? ? ? ? value: "id",
? ? ? ? label: "name",
? ? ? ? children: "children"
? ? ? ? // disabled:true
? ? ? },
? ? ? // 選項列表(必選)
? ? ? list: [
? ? ? ? { id: 1, parentId: 0, name: "一級菜單A", rank: 1 },
? ? ? ? { id: 2, parentId: 0, name: "一級菜單B", rank: 1 },
? ? ? ? { id: 3, parentId: 0, name: "一級菜單C", rank: 1 },
? ? ? ? { id: 4, parentId: 1, name: "二級菜單A-A", rank: 2 },
? ? ? ? { id: 5, parentId: 1, name: "二級菜單A-B", rank: 2 },
? ? ? ? { id: 6, parentId: 2, name: "二級菜單B-A", rank: 2 },
? ? ? ? { id: 7, parentId: 4, name: "三級菜單A-A-A", rank: 3 },
? ? ? ? { id: 8, parentId: 7, name: "四級菜單A-A-A-A", rank: 4 },
? ? ? ? { id: 9, parentId: 0, name: "一級菜單C", rank: 1 },
? ? ? ? { id: 10, parentId: 0, name: "一級菜單end", rank: 1 }
? ? ? ],
? ? };
? },
? computed: {
? ? /* 轉(zhuǎn)樹形數(shù)據(jù) */
? ? optionData() {
? ? ? let cloneData = JSON.parse(JSON.stringify(this.list)); // 對源數(shù)據(jù)深度克隆
? ? ? return cloneData.filter(father => {
? ? ? ? // 循環(huán)所有項,并添加children屬性
? ? ? ? let branchArr = cloneData.filter(child => father.id == child.parentId); // 返回每一項的子級數(shù)組
? ? ? ? branchArr.length > 0 ? (father.children = branchArr) : ""; //給父級添加一個children屬性,并賦值
? ? ? ? return father.parentId == 0; //返回第一層
? ? ? });
? ? }
? },
? methods: {
? ? // 取值
? ? getValue(value) {
? ? ? this.valueId = value;
? ? ? console.log(this.valueId);
? ? }
? }
};
</script>
<style>
#app {
? font-family: "Avenir", Helvetica, Arial, sans-serif;
? -webkit-font-smoothing: antialiased;
? -moz-osx-font-smoothing: grayscale;
? text-align: center;
? color: #2c3e50;
? margin-top: 60px;
}
</style>