Element-ui樹形控件el-tree自定義增刪改和局部刷新及懶加載操作
需求: vue-cli項目樹形控件:一級節(jié)點為本地節(jié)點,默認展開一級節(jié)點,增刪改后局部刷新數(shù)據(jù)。

增加節(jié)點,點擊確定后局部刷新,渲染新數(shù)據(jù)。

源碼
element組件樣式
<el-tree
class="treeitems"
:data="data"
node-key="id"
:props="defaultProps"
:load="loadNode"
lazy
:default-expanded-keys="[0]"
@node-click="handleNodeClick"
draggable
:allow-drop="allowDrop"
:allow-drag="allowDrag"
@node-drop="handleDrop"
ref="tree"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<span>
<i @click="() => append(node,data)" class="el-icon-plus"></i><!--增加分組-->
<!-- 根節(jié)點不需要刪除和重命名 -->
<i v-if="data.id !== 0" @click="() => deletes(node,data)" class="el-icon-delete"></i><!--刪除分組-->
<i v-if="data.id !== 0" @click="() => rename(node,data)" class="el-icon-edit"></i><!--重命名分組-->
</span>
</span>
</el-tree>
data數(shù)據(jù)
data() {
return {
filterText: '',
data: [{
id:0,
label: '中國',
}],
children: [{
id:1,
label: '北京',
children: [{
id:11,
label: '通州'
}]
},
{
id:2,
label: '上海',
leaf: true,
},
{
id:3,
label: '山西',
children:[{
id: 13,
label: '太原'
},{
id: 14,
label: '陽泉'
}]
},{
id:4,
label: '黑龍江',
children: [{
id:12,
label: '哈爾濱'
}]
}],
defaultProps: {
children: 'children',
label: 'label',
isLeaf: 'leaf'
}
};
點擊增加節(jié)點彈出彈窗
這里也用的是element的彈窗,直接在methods里寫:
//點重命名事件
append(node,data) {
console.log(node,data,'增加')
this.$prompt('節(jié)點名字', '增加節(jié)點', {
confirmButtonText: '確定',
cancelButtonText: '取消',
inputPattern: /^[\u4e00-\u9fa5]{0,}$/,//匹配全中文
inputErrorMessage: '請輸入中文'//不符合正則匹配的提示語句
}).then(({ value }) => {
//可以在這里發(fā)請求,http是我模擬的一個虛假的封裝好的axios請求,()可寫請求參數(shù)
http().then((data)=>{
this.$message({
type: 'success',
message: '修改成功'
});
//請求成功需局部刷新該節(jié)點,調用方法,把節(jié)點信息node傳入
this.partialRefresh(node)
})
//請求失敗
.catch(()=>{
this.$message({
type: 'info',
message: '修改失敗'
});
})
}).catch(() => {
this.$message({
type: 'info',
message: '取消修改'
});
});
},
//實現(xiàn)局部刷新,在點擊彈窗處調用的
partialRefreshpartialRefresh(node){
//設置loaded為false;模擬一次節(jié)點展開事件,加載重命名后的新數(shù)據(jù);
node.loaded = false;
node.expand();
//新建子節(jié)點是刷新一次本節(jié)點的展開請求,而重命名和刪除則需要刷新父級節(jié)點的的展開事件,
//可以設置node.parent.loaded = false;node.parent.expand();
},
懶加載

該處可直接設置有無節(jié)點,如果后端返回有無節(jié)點的表示就可用,若無可舍棄。(data中寫,我在本地模擬數(shù)據(jù)上海字段中加了leaf: true,上海節(jié)點就默認沒有節(jié)點了)
//懶加載
loadNode(node, resolve){
if (node.level === 0) {
//本地的數(shù)據(jù),一個承載中國字樣的數(shù)組;
return resolve(this.data);
}
else if(node.level === 1){
//現(xiàn)在為模擬數(shù)據(jù);
//有真實數(shù)據(jù),在resolve中放置請求回來的數(shù)據(jù)即可。
//else同樣也是。我這里是區(qū)分了兩種請求方式。
return resolve(this.children)
}
else{
return resolve([])
}
},
拖拽節(jié)點
//拖拽==>拖拽時判定目標節(jié)點能否被放置
allowDrop(draggingNode, dropNode, type){
//參數(shù):被拖拽節(jié)點,要拖拽到的位置
//因為根目錄是我本地寫死的,不能有同級,所以我設置凡是拖拽到的level===1都存放到根節(jié)點的下面;
if(dropNode.level===1){
return type == 'inner';
}
else {
return true;
}
},
//拖拽==>判斷節(jié)點能否被拖拽
allowDrag(draggingNode){
//第一級節(jié)點不允許拖拽
return draggingNode.level !== 1;
},
需求改了,同級節(jié)點拖拽,拖拽完成后將排序結果返回后端:
//拖拽==>拖拽時判定目標節(jié)點能否被放置
//后更改為只能同級拖拽
allowDrop(draggingNode, dropNode, type) {
if (draggingNode.level === dropNode.level) {
if (draggingNode.data.parentId === dropNode.data.parentId) {
return type === 'prev' || type === 'next'
}
} else {
// 不同級不允許拖拽
return false
}
},
//拖拽==>判斷節(jié)點能否被拖拽
allowDrag(draggingNode) {
return draggingNode.level !== 1;
},
//拖拽成功完成時觸發(fā)的事件,在這里可以將節(jié)點拖拽后的順序返給后端
handleDrop(node,data,type,event){
let arr=[];
//data為拖拽后節(jié)點信息,找到它的父級,在從父級找子集
let child = data.parent.childNodes;
for(var key in child){
arr.push({id:child[key].data.id})
}
//轉為JSON字符串發(fā)請求帶走信息
idSort(JSON.stringify(arr))
}
補充知識:vue+element tree ----增加修改刪除上下移動
<template>
<div>
<div class="exam_structure">
<el-input
placeholder="輸入關鍵字進行過濾"
v-model="filterText">
</el-input>
<el-button type="primary" size="small" class="add_new_question" @click="add_new_question"><i></i>添加父節(jié)點</el-button>
</div>
<div class="question_info_lists">
<el-tree ref="tree" :key="tree_key" :data="treeData" node-key="id" :render-content="renderContent"
:expand-on-click-node="false" :default-expanded-keys="defaultExpand" show-checkbox
:filter-node-method="filterNode"></el-tree>
<el-row class="add_question" v-show="add_question_flag">
<el-col :span="12">
<el-input v-model="new_question_name" placeholder="請輸入大題名稱"></el-input>
</el-col>
<el-col :span="12">
<el-button size="mini" class="btn_sure" @click.stop="add_question_sure">確定</el-button>
<el-button size="mini" class="btn_cancel" @click.stop="add_question_cancel">取消</el-button>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
export default {
name: "tree1",
watch: {
filterText(val) {
this.$refs.tree.filter(val);
}
},
methods: {
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
// 添加新大題
add_new_question() {
this.add_question_flag = true
},
add_question_sure() { //確定
const nodeObj = {id: '', label: this.new_question_name, isEdit: false, children: []}
this.treeData.push(nodeObj)
this.add_question_flag = false
},
add_question_cancel() { //取消
this.add_question_flag = false
this.new_question_name = ''
},
// 增加
append(store, node, data) {
var maxid = '20'
//新增數(shù)據(jù)
const nodeapp = {id: ++maxid, label: '增加節(jié)點', isEdit: false, children: []}
data.children.push(nodeapp)
if (!node.expanded) {
node.expanded = true
}
const parent = node.parent
const children = parent.data
const cIndex = children.findIndex(d => d.id === data.id)
const tempChildrenNodex2 = children[cIndex] //拿到被添加的上一級
console.log(tempChildrenNodex2.children[cIndex - 1])
},
// 修改
nodeEdit(ev, store, data) {
data.isEdit = true
this.$nextTick(() => {
const $input = ev.target.parentNode.parentNode.querySelector('input') || ev.target.parentElement.parentElement.querySelector('input')
!$input ? '' : $input.focus()
})
},
edit_sure(ev, data) {
const $input = ev.target.parentNode.parentNode.querySelector('input') || ev.target.parentElement.parentElement.querySelector('input')
if (!$input) {
return false
} else {
data.label = $input.value
data.isEdit = false
}
},
// 節(jié)點刪除
nodeDelete(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex(d => d.id === data.id)
children.splice(index, 1)
},
// 節(jié)點上移
nodeUp(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const cIndex = children.findIndex(d => d.id === data.id)
if (parent.level === 0 && cIndex === 0) {
return
} else if (parent.level !== 0 && cIndex === 0) { //不同父節(jié)點中移動
alert('不同父節(jié)點中移動')
// const parent2 = parent.parent
// const children2 = parent2.data.children || parent2.data
// const pIndex2 = parseInt(children2.findIndex(p => p.id === parent.data.id), 10) - 1
// if (pIndex2 < 0) return
// children2[pIndex2].children.push(data)
// children.splice(cIndex, 1)
// this.defaultExpand[0] = children2[pIndex2].id
} else if ((parent.level === 0 && cIndex !== 0) || (parent.level !== 0 && cIndex !== 0)) {
const tempChildrenNodex1 = children[cIndex - 1]
const tempChildrenNodex2 = children[cIndex]
this.$set(children, cIndex - 1, tempChildrenNodex2)
this.$set(children, cIndex, tempChildrenNodex1)
this.defaultExpand[0] = data.id
}
this.tree_key++
},
// 節(jié)點下移
nodeDown(store, node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const cIndex = children.findIndex(d => d.id === data.id)
const cLength = children.length - 1 // 最邊上的節(jié)點
const allLevel = store.data.length - 1 // 樹的深度
if (parent.level === allLevel && cIndex === cLength) { // 最最末的節(jié)點
return
} else if (parent.level !== allLevel && cIndex === cLength) { //父節(jié)點不同
alert('不能移動')
// const parent2 = parent.parent
// const children2 = parent2.data.children || parent2.data
// const pIndex2 = parseInt((children2.findIndex(p => p.id === parent.data.id)), 10)
// if (pIndex2 === allLevel) return
// children2[pIndex2 + 1].children.push(data)
// children.splice(cIndex, 1)
// this.defaultExpand[0] = children2[pIndex2 + 1].id
} else if ((parent.level === allLevel && cIndex !== cLength) || (parent.level !== allLevel && cIndex !== cLength)) { // 父節(jié)點相同
const tempChildrenNodex1 = children[cIndex + 1]
const tempChildrenNodex2 = children[cIndex]
this.$set(children, cIndex + 1, tempChildrenNodex2)
this.$set(children, cIndex, tempChildrenNodex1)
this.defaultExpand[0] = data.id
}
this.tree_key++
},
showOrEdit(data) {
if (data.isEdit) {
return <input type="text" value={data.label} on-blur={ev => this.edit_sure(ev, data)}/>
} else {
return <span className="node_labe">{data.label}</span>
}
},
// 結構樹操作group node,
renderContent(h, {node, data, store}) {
return (
<span>
<span class="el-icon-document">
{this.showOrEdit(data)}
</span>
<div class="tree_node_op" style=" float: right">
<i class="el-icon-edit" on-click={(ev) => this.nodeEdit(ev, store, data)}></i>
<i class="el-icon-delete" on-click={() => this.nodeDelete(node, data)}></i>
<i class="el-icon-upload2" on-click={() => this.nodeUp(node, data)}></i>
<i class="el-icon-download" on-click={() => this.nodeDown(store, node, data)}></i>
<i class="el-icon-plus" on-click={() => this.append(store, node, data)}></i>
</div>
</span>)
}
}
, data() {
return {
filterText: '',
treeData: [{
id: 1,
label: '一級 1',
isEdit: false,
children: [{
id: 4,
label: '二級 1-1',
isEdit: false,
children: [{id: 9, label: '三級 1-1-1', isEdit: false, children: []}, {
id: 10,
label: '三級 1-1-2',
isEdit: false,
children: []
}, {
id: 11,
label: '三級 1-1-3',
isEdit: false,
children: []
}]
},
{
id: 12,
label: '二級 1-2',
isEdit: false,
children: []
},
{
id: 13,
label: '二級 1-3',
isEdit: false,
children: []
}]
},
{
id: 2,
label: '一級 2',
isEdit: false,
children: [{id: 5, label: '二級 2-1', isEdit: false, children: []}, {
id: 6,
label: '二級 2-2',
isEdit: false,
children: []
}]
},
{
id: 3,
label: '一級 3',
isEdit: false,
children: [
{id: 7, label: '二級 3-1', isEdit: false, children: []},
{
id: 8,
label: '二級 3-2',
isEdit: false,
children: []
}]
}],
add_question_flag: false,
new_question_name: '',
tree_key: 0,
defaultExpand: []
}
},
}
</script>
<style scoped>
</style>

以上這篇Element-ui樹形控件el-tree自定義增刪改和局部刷新及懶加載操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Vue源碼學習defineProperty響應式數(shù)據(jù)原理實現(xiàn)
這篇文章主要為大家介紹了Vue源碼學習defineProperty響應式數(shù)據(jù)原理實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09

