element下拉樹封裝el-select el-tree

image

1.組件調(diào)用代碼

<template>
  <div id="app">
    <h1>{{`基于Element-UI組件改造的樹形選擇器`}}:</h1>
    <!-- 調(diào)用樹形下拉框組件 -->
    <!-- 下拉樹 -->
    <selectbutton
      :props="props"
      :options="optionData"
      :value="valueId"
      :clearable="isClearable"
      :accordion="isAccordion"
      @getValue="getValue($event)"
      height="200"
    ></selectbutton>
    ID為:{{valueId}}
  </div>
</template>

調(diào)用組件的數(shù)據(jù)

<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>

2.組件封裝

<template>
  <el-select :value="valueTitle" :clearable="clearable" @clear="clearHandle"  ref="treeSelect">
    <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 "檢索關鍵字"}
    }
  },
  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)       // 設置默認選中
        this.defaultExpandedKey = [this.valueId]      // 設置默認展開
      } 
      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 = []
      if(!node.children || !node.children.length) { //補錄選擇完選項不能收起
        this.$refs.treeSelect.blur()
      }
    },
    // 清除選中
    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>

3.樣式修改

<!-- 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>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,120評論 1 32
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,478評論 0 17
  • 直接將代碼貼上來了 html: js: 做一下說明,代碼中因為已知寬高,所以我直接寫的 540和260,即寬高的一...
    2c4b9a3449a9閱讀 3,034評論 0 1
  • 你說我畫 活動用時:10分鐘 步驟如下: 1、請一位學員上臺,給他衣服在培訓前準備好的簡單的圖畫 2、給其他學員發(fā)...
    陸游學苑閱讀 3,347評論 0 1
  • 2去廈門,并無是頭腦發(fā)熱時做出的決定。而是預謀已久,和太多人約了太多次,只是大學之后,天南海北,各處一方。總聚不到...
    孟柳遠閱讀 303評論 0 0