最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue實(shí)現(xiàn)的樹形結(jié)構(gòu)加多選框示例

 更新時(shí)間:2019年02月02日 11:07:52   作者:前端林三哥  
這篇文章主要介紹了vue實(shí)現(xiàn)的樹形結(jié)構(gòu)加多選框,結(jié)合實(shí)例形式分析了在之前遞歸組件實(shí)現(xiàn)vue樹形結(jié)構(gòu)的基礎(chǔ)之上再加上多選框功能相關(guān)操作技巧,需要的朋友可以參考下

本文實(shí)例講述了vue實(shí)現(xiàn)的樹形結(jié)構(gòu)加多選框。分享給大家供大家參考,具體如下:

前面說了如何用遞歸組件來寫vue樹形結(jié)構(gòu),寫了樹形結(jié)構(gòu)還要在前面加多選框,然后往數(shù)組里push選項(xiàng),并在左邊顯示出來,然后左邊進(jìn)行拖拽排序,拖拽排序上一篇文章我已經(jīng)介紹過了,在這我就不介紹了,如何用阿里巴巴矢量圖標(biāo)庫我也有相關(guān)文章,也不介紹了,本節(jié)主要介紹vue樹形結(jié)構(gòu)加多選框,并實(shí)現(xiàn)一定的邏輯,比如全選,單選,全選和單選之間的聯(lián)動(dòng)

先看下目錄結(jié)構(gòu)

下面我直接貼下代碼

首先是pages文件夾中tree.vue頁面中引用組件

下面是tree.vue的代碼

<template>
  <div class = "loginModuel">
    <Tree :menus = "menus" :depth = "depth" @selectItem = "selectItem" :actId = "actId" @checkItem = "checkItem"></Tree>
  </div>
</template>
<script src = "./index.js"></script>
<style lang = "scss" scoped src = "./index.scss"></style>

然后是tree.vue引入的index.js的代碼

import Tree from '../../components/tree/tree';
import axios from 'axios';
export default{
  data(){
    return{
      msg:"這是登錄頁面",
      depth:0,
      menus:[],
      actId:"",
    }
  },
  components:{
    Tree
  },
  methods:{
    //用ajax獲取數(shù)據(jù)
    getData(){
      return axios.get('/static/json/data.json');
    },
    // 調(diào)用ajax函數(shù)
    async getTree(){
      var last = await this.getData();
      if(last.data.code == 1){
        this.menus = last.data.data;
        //在每一項(xiàng)中添加selectArr和show
        this.addShow(this.menus);
      }
    },
    //遞歸函數(shù)在每一項(xiàng)中添加selectArr和show
    addShow(arr){
      for(var i = 0; i < arr.length;i++){
        this.$set(arr[i],"show",true);
        this.$set(arr[i],"selectArr",[]);
        if(arr[i].userList && arr[i].userList.length > 0){
          this.addShow(arr[i].userList)
        }
      }
    },
    //點(diǎn)擊箭頭使樹展開收縮
    selectItem(data){
      if(data.userList && data.userList.length > 0){
        //如果此項(xiàng)下有userList且length大于0,則切換展開與折疊狀態(tài)
        data.show = !data.show;
      }else{
        //如果此項(xiàng)下沒有userList或length等于0,則將選中的id賦值給actId
        this.actId = data.id;
      }
    },
    //進(jìn)行多選勾選
    checkItem(data){
      if(data.selectArr.length > 0){
        //如果這一項(xiàng)的selectArr有值,說明是被勾選狀態(tài),要把selectArr清空,清空勾選
        data.selectArr = [];
        //如果此選項(xiàng)清空勾選后,如果下面有userList的話,那么也同時(shí)要清空
        if(data.userList && data.userList.length > 0){
          this.clearChild(data.userList);
        }
        //如果此選項(xiàng)清空勾選后,要把所有的父元素,也全部清空勾選,因?yàn)樗还催x了,所有父元素的狀態(tài)不可能還處于勾選狀態(tài),不管它勾選不勾選,我們都要清除一遍,以防萬一
        this.clearFather(this.menus,data);
      }else{//如果這一項(xiàng)的selectArr為[],說明是未被勾選狀態(tài),在selectArr里加id值,添加勾選
        data.selectArr.push(data.id);
        //如果此選項(xiàng)清空勾選后,如果下面有userList的話,那么也同時(shí)勾選下面所有的孩子
        if(data.userList && data.userList.length > 0){
          this.addChild(data.userList);
        }
        //如果此選項(xiàng)勾選后,要判斷所有的上級(jí)元素是不是應(yīng)該全部打勾
        this.selectFather(this.menus,data);
      }
    },
    //定義函數(shù)清空所有孩子的勾選
    clearChild(arr){
      for(var i = 0; i < arr.length;i++){
        arr[i].selectArr = [];
        if(arr[i].userList && arr[i].userList.length > 0){
          this.clearChild(arr[i].userList);
        }
      }
    },
    //定義函數(shù)添加所有孩子的勾選
    addChild(arr){
      for(var i = 0; i < arr.length;i++){
        arr[i].selectArr.push(arr[i].id);
        if(arr[i].userList && arr[i].userList.length > 0){
          this.addChild(arr[i].userList);
        }
      }
    },
    //定義函數(shù)一層一層的往上尋找父元素的userList
    clearFather(father,data){
      for(var i = 0; i < father.length;i++){
        if(father[i].id == data.id){
          //找到data所在的userList為father,然后再通過這個(gè)userList找到擁有這個(gè)userList的父元素
          this.clearRealFather(this.menus,father);
        }else if(father[i].userList && father[i].userList.length > 0){
          this.clearFather(father[i].userList,data);
        }
      }
    },
    //定義函數(shù)根據(jù)找到的上層父元素的userList來尋找父元素,并將他們清除勾選
    clearRealFather(menus,arr){
      for(var i = 0; i < menus.length;i++){
        if(menus[i].userList == arr){
          //找到這個(gè)擁有userList的父元素后,將此selectArr清空
          menus[i].selectArr = [];
          //找到這個(gè)擁有userList的父元素后,再調(diào)用clearFather,再進(jìn)行向上尋找父元素,知道沒有父元素為止
          this.clearFather(this.menus,menus[i]);
        }else if(menus[i].userList && menus[i].userList.length > 0){
          this.clearRealFather(menus[i].userList,arr);
        }
      }
    },
    //定義函數(shù)一層一層的往上尋找父元素的userList
    selectFather(father,data){
      for(var i = 0; i < father.length;i++){
        if(father[i].id == data.id){
          var arr = [];
          for(var j = 0; j < father.length;j++){
            if(father[j].selectArr.length > 0){
              arr.push(father[i]);
            }
          }
          //判斷此數(shù)組中是不是所有的selectArr都有值,如果有值,就執(zhí)行selectRealFather,將上層父元素也勾選
          if(arr.length == father.length){
            this.selectRealFather(this.menus,father);
          }
        }else if(father[i].userList && father[i].userList.length > 0){
          this.selectFather(father[i].userList,data);
        }
      }
    },
    //定義函數(shù)根據(jù)找到的上層父元素的userList來尋找父元素,并將他們清除勾選
    selectRealFather(menus,arr){
      for(var i = 0; i < menus.length;i++){
        if(menus[i].userList == arr){
          //找到這個(gè)擁有userList的父元素后,給selectArr賦值,使其勾選
          menus[i].selectArr.push(menus[i].id);
          //找到這個(gè)擁有userList的父元素后,再調(diào)用clearFather,再進(jìn)行向上尋找父元素,知道沒有父元素為止
          this.clearFather(this.menus,menus[i]);
        }else if(menus[i].userList && menus[i].userList.length > 0){
          this.selectRealFather(menus[i].userList,arr);
        }
      }
    }
  },
  mounted(){
    this.getTree();
  }
}

然后是樹形組件components文件夾中tree.vue的代碼

1.tree.vue

<template>
  <ul class = "treeMoudel">
    <li v-for = "(item,index) in menus" :key = "index">
      <!-- 遍歷menus,如果傳過來的depth等于0,就添加topNode的class,如果不等于0,就添加noTopNode的class -->
      <div :class = "{'itemTree':true,'topNode':depth == 0,'noTopNode':depth != 0,'active':actId == item.id}">
        <!-- 判斷如果含有name字段就顯示name字段 -->
        <span :style = "transform" v-if = "item.name" :class = "{'topSpan':depth == 0,'noTopSpan':depth != 0}">
          <!-- 如果item有孩子且item.show為false,那么圖標(biāo)為折疊圖標(biāo) -->
          <i class = "el-icon-caret-right" v-if = "item.userList && item.userList.length > 0 && !item.show" @click = "selectItem(item)"></i>
          <!-- 如果item有孩子且item.show為true,那么圖標(biāo)為展開圖標(biāo) -->
          <i class = "el-icon-caret-bottom" v-if = "item.userList && item.userList.length > 0 && item.show" @click = "selectItem(item)"></i>
          <i class = "selectBox" @click = "checkItem(item)">
            <!-- 如果item的selectArr.length是大于0的,也就是里面有值的話就是勾選狀態(tài),否則就是不勾選狀態(tài) -->
            <i :class = "{'checkName iconfont':true, 'gouxuan5':item.selectArr.length > 0}" ></i>
          </i>
          {{item.name}}
        </span>
        <!-- 判斷如果含有username字段就顯示username字段 -->
        <span :style = "transform" v-if = "item.username" :class = "{'topSpan':depth == 0,'noTopSpan':depth != 0}">
          <!-- 如果item有孩子且item.show為false,那么圖標(biāo)為折疊圖標(biāo) -->
          <i class = "el-icon-caret-right" v-if = "item.userList && item.userList.length > 0 && !item.show" @click = "selectItem(item)"></i>
          <!-- 如果item有孩子且item.show為true,那么圖標(biāo)為展開圖標(biāo) -->
          <i class = "el-icon-caret-bottom" v-if = "item.userList && item.userList.length > 0 && item.show" @click = "selectItem(item)"></i>
          <i class = "selectBox" @click = "checkItem(item)">
            <!-- 如果item的selectArr.length是大于0的,也就是里面有值的話就是勾選狀態(tài),否則就是不勾選狀態(tài) -->
            <i :class = "{'checkUsername iconfont':true, 'gouxuan5':item.selectArr.length > 0}"></i>
          </i>
          {{item.username}}
        </span>
      </div>
      <el-collapse-transition>
        <!-- 遞歸組件就是自己調(diào)用自己,這里是在自己的組件內(nèi)再次調(diào)用自己,但是務(wù)必要和pages中的tree頁面中使用的一模一樣才可以,否則樹不會(huì)生效 -->
        <Tree v-if = "item.userList && item.userList.length > 0 && item.show" :menus = "item.userList" :depth = "depth+4" @selectItem = "selectItem" :actId = "actId" @checkItem = "checkItem"></Tree>
      </el-collapse-transition>
    </li>
  </ul>
</template>
<script src = "./index.js"></script>
<style src = "./index.scss" lang = "scss" scoped></style>

2.tree.vue中引入的index.js

export default{
  name:"Tree",
  props:["menus","depth","actId"],
  data(){
    return{
      msg:"這是二級(jí)菜單樹",
    }
  },
  methods:{
    // 將selectItem方法暴露出去
    selectItem(item){
      this.$emit("selectItem",item);
    },
    // 將checkItem方法暴露出去
    checkItem(item){
      this.$emit("checkItem",item);
    }
  },
  computed:{
    //通過傳過來的depth計(jì)算下級(jí)目錄的偏移量,這里我用的transform
    transform(){
      return 'transform:translateX(' + this.depth*10 + 'px)';
    }
  }
}

3.tree.vue中引入的index.scss

.treeMoudel{
  li{
    .itemTree{
      width: 100%;
      padding-left:30px;
      position: relative;
      &:hover{
        background:#2B9EEE;
        color:#fff;
      }
      .selectBox{
        display: inline-block;
        width: 16px;
        height:16px;
        border:1px solid #ccc;
        border-radius: 3px;
        position: relative;
        background: #fff;
        top:2px;
        .checkName{
          position: absolute;
          top:-16px;
          left:0px;
          color:#333;
        }
        .checkUsername{
          position: absolute;
          top:-12px;
          left:0px;
          color:#333;
        }
      }
      span{
        display: inline-block;
        position: absolute;
        font-size:14px;
      }
      .topSpan{
        font-size:16px;
      }
      .noTopSpan{
        font-size:14px;
      }
    }
    .topNode{
      height:55px;
      line-height: 55px;
      font-size:16px;
      cursor: pointer;
    }
    .active{
      background:#2B9EEE;
      color:#fff;
    }
    .noTopNode{
      height:45px;
      line-height:45px;
      &:hover{
        background:#2B9EEE;
        cursor: pointer;
        color:#fff;
      }
    }
  }
}

看一下模擬數(shù)據(jù)的data.json長(zhǎng)什么樣子吧

{
  "code":1,
  "data":[
    {
      "id":"1.2",
      "name":"技術(shù)部",
      "userList":[
        {
          "id":"788d",
          "username":"html",
          "role":"主管"
        },
        {
          "id":"sda",
          "username":"vue",
          "role":"普通"
        }
      ]
    },
    {
      "id":"1.3",
      "name":"策劃部",
      "userList":[
        {
          "id":"dsf",
          "username":"jack",
          "role":"主管"
        },
        {
          "id":"asdf",
          "username":"rose",
          "role":"普通"
        }
      ]
    }
  ]
}

至此,一個(gè)樹形組件加多選框就做好了

下面看下效果圖

ok,自此這一功能就實(shí)現(xiàn)啦,代碼講解我就不寫了,注釋里寫的清清楚楚的,看注釋就好啦!

希望本文所述對(duì)大家vue.js程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • Monaco?Editor開發(fā)SQL代碼提示編輯器實(shí)例詳解

    Monaco?Editor開發(fā)SQL代碼提示編輯器實(shí)例詳解

    這篇文章主要為大家介紹了Monaco?Editor開發(fā)SQL編輯器實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Vue實(shí)現(xiàn)PopupWindow組件詳解

    Vue實(shí)現(xiàn)PopupWindow組件詳解

    這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)PopupWindow組件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Vue3?中路由Vue?Router?的使用實(shí)例詳解

    Vue3?中路由Vue?Router?的使用實(shí)例詳解

    vue-router是vue.js官方給出的路由解決方案,能夠輕松的管理SPA項(xiàng)目中組件的切換,這篇文章主要介紹了Vue3?中路由Vue?Router?的使用,需要的朋友可以參考下
    2023-02-02
  • 一文詳解Vue Router的使用和路由守衛(wèi)

    一文詳解Vue Router的使用和路由守衛(wèi)

    Vue Router 是 Vue.js 的官方路由庫,用于在 Vue 應(yīng)用中實(shí)現(xiàn)單頁面應(yīng)用(SPA)的客戶端路由,以下是 Vue Router 的詳細(xì)介紹,包括基本概念、配置、路由導(dǎo)航以及高級(jí)用法,感興趣的小伙伴跟著小編一起來看看吧
    2024-08-08
  • vue實(shí)現(xiàn)點(diǎn)擊按鈕“查看詳情”彈窗展示詳情列表操作

    vue實(shí)現(xiàn)點(diǎn)擊按鈕“查看詳情”彈窗展示詳情列表操作

    這篇文章主要介紹了vue實(shí)現(xiàn)點(diǎn)擊按鈕“查看詳情”彈窗展示詳情列表操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 從0到1構(gòu)建vueSSR項(xiàng)目之路由的構(gòu)建

    從0到1構(gòu)建vueSSR項(xiàng)目之路由的構(gòu)建

    這篇文章主要介紹了從0到1構(gòu)建vueSSR項(xiàng)目之路由的構(gòu)建,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • Vue watch原理源碼層深入講解

    Vue watch原理源碼層深入講解

    watch 是由用戶定義的數(shù)據(jù)監(jiān)聽,當(dāng)監(jiān)聽的屬性發(fā)生改變就會(huì)觸發(fā)回調(diào),這項(xiàng)配置在業(yè)務(wù)中是很常用。在面試時(shí),也是必問知識(shí)點(diǎn),一般會(huì)用作和 computed 進(jìn)行比較。那么本文就來帶大家從源碼理解 watch 的工作流程,以及依賴收集和深度監(jiān)聽的實(shí)現(xiàn)
    2022-10-10
  • 帶你理解vue中的v-bind

    帶你理解vue中的v-bind

    如果你寫過vue,對(duì)v-bind這個(gè)指令一定不陌生。 下面小編將從源碼層面去帶大家剖析一下v-bind背后的原理,需要的小伙伴可以參考下面章的具體內(nèi)容
    2021-09-09
  • Vuerouter的beforeEach與afterEach鉤子函數(shù)的區(qū)別

    Vuerouter的beforeEach與afterEach鉤子函數(shù)的區(qū)別

    本文詳細(xì)的介紹了Vuerouter的beforeEach與afterEach鉤子函數(shù)的區(qū)別和使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-12-12
  • vue中使用console.log打印的實(shí)現(xiàn)

    vue中使用console.log打印的實(shí)現(xiàn)

    這篇文章主要介紹了vue中使用console.log打印的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04

最新評(píng)論

固阳县| 神农架林区| 那坡县| 中阳县| 达日县| 平南县| 无为县| 威远县| 怀柔区| 利津县| 玉门市| 黔东| 金华市| 石门县| 儋州市| 洱源县| 永年县| 溧阳市| 霍山县| 东丽区| 彩票| 成安县| 梓潼县| 乌恰县| 泽库县| 富川| 海晏县| 仁寿县| 右玉县| 山阴县| 开平市| 沅陵县| 丰原市| 金湖县| 紫云| 无棣县| 屯留县| 醴陵市| 青海省| 远安县| 临西县|