vue的自定義樹形列表組件(及數據格式轉換)


 
  • 組件定義

子組件:

<template>
<div>
<!-- <h5>{{temp.tital}}</h5> -->
<el-button class="filter-item" style="margin-left: 1px;" size="small" type="primary" >{{temp.tital}}</el-button>
<el-input
size="small"
placeholder="輸入關鍵字過濾分類"
v-model="filterText">
</el-input>
 

 

<el-tree
class="filter-tree"
:data="treeData"
:props="defaultProps"
:node-key="id"
default-expand-all
:filter-node-method="filterNode"
ref="tree2"
@node-click="sendData"
>
</el-tree>
</div>
</template>

 

<script>
export default {
watch: {
filterText(val) {
this.$refs.tree2.filter(val);
}
},

 

methods: {
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
setTreeData(datass){//接收父組件的參數
this.temp.tital = datass.tital
this.treeData = datass;
},
sendData(obj, node, data){//向父組件發送參數
this.$emit("sendTreeData", obj)//"sendTreeData"這是父組件引用時定義的
 

 

}
},

 

data() {
return {
temp:{
tital:"哈哈哈"
},
filterText: '',
data2: [{// 這是tree型數據格式
id: 1,
label: '一級 1',
children: [{
id: 4,
label: '二級 1-1',
children: [{
id: 9,
label: '三級 1-1-1'
}, {
id: 10,
label: '三級 1-1-2'
}]
}]
}, {
id: 2,
label: '一級 2',
children: [{
id: 5,
label: '二級 2-1'
}, {
id: 6,
label: '二級 2-2'
}]
}, {
id: 3,
label: '一級 3',
children: [{
id: 7,
label: '二級 3-1'
}, {
id: 8,
label: '二級 3-2'
}]
}],
treeData:[],
defaultProps: {
children: 'children',
label: 'name'

 

}
};
}
};
</script>
 
父組件調用子組件
<Mytreetable ref="mytreedata" v-model="temp.icon" @sendTreeData="sendTreeObj" />
 
import Mytreetable from '@/components/MyTreeTable/index'
 
export default {
name: 'ComplexTable',
components: { Mytreetable },
 
//向子組件傳遞數據
this.$refs.mytreedata.setTreeData(treesss);
 
  • 以下內容為普通扁平化格式轉換成樹形對象的方法
  • 其中list的格式為
  • [
    {
    "id": 100,
    "pId": 0,
    "name": "科技",
    "title": "科技",
    "checked": false,
    "open": false,
    "nocheck": false
    },
    {
    "id": 101,
    "pId": 100,
    "name": "深圳總公司",
    "title": "深圳總公司",
    "checked": false,
    "open": false,
    "nocheck": false
    },
    {
    "id": 102,
    "pId": 100,
    "name": "長沙分公司",
    "title": "長沙分公司",
    "checked": false,
    "open": false,
    "nocheck": false
    },
    {
    "id": 103,
    "pId": 101,
    "name": "研發部門",
    "title": "研發部門",
    "checked": false,
    "open": false,
    "nocheck": false
    },
    {
    "id": 104,
    "pId": 101,
    "name": "市場部門",
    "title": "市場部門",
    "checked": false,
    "open": false,
    "nocheck": false
    },
    {
    "id": 105,
    "pId": 101,
    "name": "測試部門",
    "title": "測試部門",
    "checked": false,
    "open": false,
    "nocheck": false
    },
    {
    "id": 106,
    "pId": 101,
    "name": "財務部門",
    "title": "財務部門",
    "checked": false,
    "open": false,
    "nocheck": false
    },
    {
    "id": 107,
    "pId": 101,
    "name": "運維部門",
    "title": "運維部門",
    "checked": false,
    "open": false,
    "nocheck": false
    },
    {
    "id": 108,
    "pId": 102,
    "name": "市場部門",
    "title": "市場部門",
    "checked": false,
    "open": false,
    "nocheck": false
    },
    {
    "id": 109,
    "pId": 102,
    "name": "財務部門",
    "title": "財務部門",
    "checked": false,
    "open": false,
    "nocheck": false
    }
    ]

  • buildTree(list){
    let pidStr = 'pId';
    let idStr = 'id';
    let childrenStr = 'children';

    let listOjb = {}; // 用來儲存{key: obj}格式的對象
    let treeList = []; // 用來儲存最終樹形結構數據的數組

    // 將數據變換成{key: obj}格式,方便下面處理數據
    for (let i = 0; i < list.length; i++) {
    listOjb[list[i][idStr]] = list[i]
    }

    for (let j = 0; j < list.length; j++) {
    // 判斷父級是否存在
    let haveParent = listOjb[list[j][pidStr]]
    if (haveParent) {
    // 如果有沒有父級children字段,就創建一個children字段
    !haveParent[childrenStr] && (haveParent[childrenStr] = [])
    // 在父級里插入子項
    haveParent[childrenStr].push(list[j])
    } else {
    // 如果沒有父級直接插入到最外層
    treeList.push(list[j])
    }
    }
    return treeList
    },
 
 
另一種扁平化轉樹形格式的轉換方式(據說效率極高,有興趣的可以試試)
 

實現算法buildTree

算法思想:

先將數組中的每一個節點放到temp對象中(創建map)
即數組中有{id: '2-3', parent_id: '2',...}這樣一個節點,需要將他放到temp中變成 '2-3': {id: '2-3', parent_id: '2',...}這種JSON結構
直接遍歷整個temp對象,通過這句代碼   temp[temp[i].parent_id].children[temp[i].id] = temp[i];   將當前子節點與父節點建立連接。是因為我們保證了父節點一定在子節點前,那么當子節點出現的時候就直接可以用temp[temp[i].parent_id]來查找到父節點這個時候先父節點的children對象中添加一個引用即可。
/**
* 將一維的扁平數組轉換為多層級對象
* @param {[type]} list 一維數組,數組中每一個元素需包含id和parent_id兩個屬性
* @return {[type]} tree 多層級樹狀結構
*/
function buildTree(list){
let temp = {};
let tree = {};
for(let i in list){
temp[list[i].id] = list[i];
}
for(let i in temp){
if(temp[i].parent_id) {
if(!temp[temp[i].parent_id].children) {
temp[temp[i].parent_id].children = new Object();
}
temp[temp[i].parent_id].children[temp[i].id] = temp[i];
} else {
tree[temp[i].id] = temp[i];
}
}
return tree;
}
測試結果:

可以看到函數成功地構建了多級的樹狀結構

 

 

這個算法的效率是極高的,比多重for循環來的好得多。

 

 

 

 

以下是測試數據,用時只需5毫秒左右:


var menu_list = [{
id: '1',
menu_name: '設置',
menu_url: 'setting',
parent_id: 0
}, {
id: '1-1',
menu_name: '權限設置',
menu_url: 'setting.permission',
parent_id: '1'
}, {
id: '1-1-1',
menu_name: '用戶管理列表',
menu_url: 'setting.permission.user_list',
parent_id: '1-1'
}, {
id: '1-1-2',
menu_name: '用戶管理新增',
menu_url: 'setting.permission.user_add',
parent_id: '1-1'
}, {
id: '1-1-3',
menu_name: '角色管理列表',
menu_url: 'setting.permission.role_list',
parent_id: '1-1'
}, {
id: '1-1-4',
menu_name: '角色管理新增',
menu_url: 'setting.permission.role_add',
parent_id: '1-1'
}, {
id: '1-2',
menu_name: '菜單設置',
menu_url: 'setting.menu',
parent_id: '1'
}, {
id: '1-2-1',
menu_name: '菜單列表',
menu_url: 'setting.menu.menu_list',
parent_id: '1-2'
}, {
id: '1-2-2',
menu_name: '菜單添加',
menu_url: 'setting.menu.menu_add',
parent_id: '1-2'
}, {
id: '2',
menu_name: '訂單',
menu_url: 'order',
parent_id: 0
}, {
id: '2-1',
menu_name: '報單審核',
menu_url: 'order.orderreview',
parent_id: '2'
}, {
id: '2-2',
menu_name: '退款管理',
menu_url: 'order.refundmanagement',
parent_id: '2'
}, {
id: '2-3',
menu_name: '實物訂單',
menu_url: 'order.realorder',
parent_id: '2'
}, {
id: '2-1-1',
menu_name: '全部報單',
menu_url: 'order.orderreview.all',
parent_id: '2-1'
}, {
id: '2-2-1',
menu_name: '所有記錄',
menu_url: 'order.refundmanagement.all',
parent_id: '2-2'
}, {
id: '2-2-2',
menu_name: '待處理',
menu_url: 'order.refundmanagement.wait',
parent_id: '2-2'
}, {
id: '2-2-3',
menu_name: '退款原因',
menu_url: 'order.refundmanagement.result',
parent_id: '2-2'
}, {
id: '2-3-1',
menu_name: '實物訂單管理',
menu_url: 'order.realorder.list',
parent_id: '2-3'
}, {
id: '3',
menu_name: '商品',
menu_url: 'commodity',
parent_id: 0
}, {
id: '3-1',
menu_name: '分類管理',
menu_url: 'commodity.classifieldmanagement',
parent_id: '3'
}, {
id: '3-1-1',
menu_name: '管理',
menu_url: 'commodity.classifieldmanagement.management',
parent_id: '3-1'
}, {
id: '3-1-2',
menu_name: '編輯或新增',
menu_url: 'commodity.classifieldmanagement.edit',
parent_id: '3-1'
}, {
id: '3-2',
menu_name: '品牌管理',
menu_url: 'commodity.brandmanagement',
parent_id: '3'
}, {
id: '3-2-1',
menu_name: '管理',
menu_url: 'commodity.brandmanagement.management',
parent_id: '3-2'
}, {
id: '3-2-2',
menu_name: '編輯或新增',
menu_url: 'commodity.brandmanagement.edit',
parent_id: '3-2'
}, {
id: '3-3',
menu_name: '商品管理',
menu_url: 'commodity.commoditymanagement',
parent_id: '3'
}, {
id: '3-3-1',
menu_name: '管理',
menu_url: 'commodity.commoditymanagement.management',
parent_id: '3-3'
}, {
id: '3-3-2',
menu_name: '編輯或新增',
menu_url: 'commodity.commoditymanagement.edit',
parent_id: '3-3'
}, {
id: '3-4',
menu_name: '類型管理',
menu_url: 'commodity.typeManagement',
parent_id: '3'
}, {
id: '3-4-1',
menu_name: '管理',
menu_url: 'commodity.typeManagement.management',
parent_id: '3-4'
}, {
id: '3-4-2',
menu_name: '編輯或新增',
menu_url: 'commodity.typeManagement.edit',
parent_id: '3-4'
}]

 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM