基于elelemnt-ui二次封装tree组件 #
实现树菜单接口 #
数据分成两部分返回,文件夹列表以及文件列表,因为二者有包含关系,需要前端根据返回的数据渲染成树形结构数据。
安装express
npm init -y npm install expressparent数据代表文件夹数据,child的数据代表文件
let express = require('express'); let app = express(); app.all('*', function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); if(req.method === 'OPTIONS'){ return res.send(); } next(); }); app.get('/getTreeList',function(req,res){ res.json({ code:0, parent:[ {name:'文件夹1',pid:0,id:1}, {name:'文件夹2',pid:0,id:2}, {name:'文件夹3',pid:0,id:3}, {name:'文件夹1-1',pid:1,id:4}, {name:'文件夹2-1',pid:2,id:5}, ], child:[ {name:'文件1',pid:1,id:10001}, {name:'文件2',pid:1,id:10002}, {name:'文件2-1',pid:2,id:10003}, {name:'文件2-2',pid:2,id:10004}, {name:'文件1-1-1',pid:4,id:10005}, {name:'文件2-1-1',pid:5,id:10006} ] }); }); app.listen(3000);
引入element-ui #
import Vue from 'vue';
// 引入组件库行
import ElementUI from 'element-ui';
// 引入组件库样式
import 'element-ui/lib/theme-chalk/index.css';
// 引入App根组件
import App from './App.vue';
// 使用插件
Vue.use(ElementUI);
export default new Vue({
el:'#app',
render:h=>h(App)
});通过axios调取接口 #
创建api.js 到出获取列表方法
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:3000';
export const getTreeList = async () =>{
return axios.get('/getTreeList');
}在组件中获取数据 #
对elememnt-ui树组件进行二次封装,封装TreeComponent组件
格式化数据-转化树列表 #
处理数据时不能对父组件传递的数据直接更改,所以操作前需要进行数据的拷贝
- 安装lodash
npm install lodash
自定义tree组件 #
文件夹添加文件夹标识,文件添加文件标识
通过render函数扩展树组件
isParent(type){
return type === 'parent';
},
renderFn(h, { node, data, store }){
let parent = this.isParent(data.type);
return (
{parent?
node.expanded?
:
:
}
{data.label}
)
},扩展操作列表 #
列表数据应该从外部传入,对文件夹和文件实现不同的操作
rootList:[
{name:'rename',text:'修改文件夹名字'},
{name:'delete',text:'删除文件夹'}
],
childList:[
{name:'rename',text:'修改文件名字'},
{name:'delete',text:'删除文件'}
]实现下拉菜单
let list = parent? this.rootList:this.childList;
{list.map(item=>(
{item.text}
))}
handleCommand(name){
if(name === 'rename'){
// 修改文件名
}else{
// 删除文件
}
}点击修改切换输入框 #
if(name === 'rename'){
this.currentId = data.id;
this.currentContent = data.label;
}
{this.currentId === data.id?
:data.label
}确认修改 #
使用.sync 同步修改后的数据
check(data){
let list = _.cloneDeep(this.data);
list = list.map(item=>{
if(item.id === data.id){
item.name = this.currentContent;
}
return item;
});
this.$emit('update:data',list);
this.currentId = '';
}取消修改 #
close(){
this.currentId = '';
}删除文件或文件夹 #
this.$confirm(`确认删除 ${data.type==='parent'?'文件夹':'文件'}吗`,"确认?",{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(()=>{
this.handleDelete(data); // 删除文件
this.$message({
type:'success',
message:'删除成功'
})
}).catch(err=>{
this.$message({
type:'info',
message:'已取消删除'
})
});
handleDelete(data){
let list = _.cloneDeep(this.data);
list = list.filter(item=> item.id !== data.id);
this.$emit('update:data',list);
this.currentId = '';
}调用接口删除文件 #
如果用户传递了delete方法,调用成功后在更新页面数据
this.delete && this.delete(data.id).then(()=>{
this.handleDelete(data);
this.$message({
type:'success',
message:'删除成功'
})
})