这是我参与更文挑战的第9天,活动详情查看: 更文挑战
项目中有这样一个需求,就是根据element-ui的组件el-tree改成如下的效果:
分析
大部分功能都可以使用element-ui的el-tree组件实现,唯一的就是需要自己去实现新增和修改以及删除的功能,然后再调用el-tree提供的方法来实现。其实主要就是如何新增一项,编辑。
结构
结构的定义很简单,这里直接上代码:
<el-button-group>
<el-button type="primary" icon="el-icon-minus" @click="delCategory"></el-button>
<el-button type="primary" icon="el-icon-plus" @click="addCategory"></el-button>
<el-button type="primary" icon="el-icon-edit" @click="editCategory"></el-button>
</el-button-group>
<el-tree
ref="tree"
node-key="id"
empty-text="暂无数据"
draggable
highlight-current
:expand-on-click-node="false"
@node-click="handleNodeClick"
:data="dataTree"
:props="{label:'name'}">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span v-if="!data.isInput">{{node.label}}{{node.data.label}}</span>
<span v-else><el-input v-model="currentInput" placeholder="请输入分类名称" @blur="saveCurrentInp"></el-input></span>
</span>
</el-tree>
复制代码
上面的代码中自定义显示分类的名称时使用了两个,这里一个是已有的显示,一个是为了新增的显示,通过在数据中自定义一个参数来控制是否显示输入框。
新增项
新增很好实现,不过在新增前需要做一个特殊的处理,就是当前点击的项需要保存下来。代码如下:
// 保存当前点击的分类
handleNodeClick(data,node){
this.currentData = data // 当前分类的数据
this.currentNode = node // 当前分类的节点
if(data.id != -1){
this.tmpCurrent = data // 缓存当前分类数据,主要用于新增时防止再次点击输入框当前值变化
}
}
复制代码
这里有一个地方需要注意,就是缓存分类数据的,这里新增的项默认id我都设置为-1,缓存也是为了新增或者修改时输入框失去焦点后点到了其他项导致出错
接下来就是新增了,这里的新增还是和文档中的差不多。代码如下:
// 添加分类
addCategory(){
const newChild = {id:-1,label:'',leaf: true,isInput:true}
if (!this.currentData.children) {
this.$set(this.currentData, 'children', [])
}
this.currentData.children.push(newChild)
}
复制代码
新增的项默认id为-1而且没有下级,并且输入的值为true,这样新增后就能够看到是一个输入框了,输入框有了,输入文字后需要进行保存,伪代码如下:
// 保存分类新增或者修改
saveCurrentInp(){
if(this.currentInput){
var params = {
name:this.currentInput
}
if(this.tmpCurrent.isEdit){
params.id = this.tmpCurrent.id
}else{
params.parentId = this.tmpCurrent.id
}
// 调用接口新增分类,成功后会返回分类信息,这样就可以更新新增的分类数据了,这里记得添加上保存的接口才可以哦
var newChild = {id:res.result.id,label:res.result.name,children:[],isInput:false}
this.$set(this.currentNode,'data',newChild)
this.$refs.tree.updateKeyChildren(this.currentData.isEdit?this.tmpCurrent.id:-1,newChild)
}else{
this.$message.error('请输入分类名称')
}
}
复制代码
这里处理了新增和编辑两个,新增后将输入状态改为false就可看到分类的名称了,注意的是新增和修改时他们所需的参数是不一样的
这样新增就ok了,接下来就做编辑吧
编辑项
当点击编辑按钮的时候就是要将当前数据中的可输入变为true,是否为编辑状态也设置为true即可。代码如下:
// 编辑分类
editCategory(){
if(this.currentData.id){
this.currentInput = this.currentData.name
this.$set(this.currentData,'isInput',true)
this.$set(this.currentData,'isEdit',true)
}else{
this.$message('请选择分类')
}
}
复制代码
注意更新数据时使用$set更新才能使页面有效果,不懂的可以看看vue的官方文档
这里保存就是上面新增的地方已经做好了。
删除项
删除最为简单了,没有什么要说的,直接看码:
// 删除分类
delCategory(){
this.$confirm('请确认是否要删除'+this.currentData.name+'分类!', '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 调用接口删除分类,删除成功后执行下面操作,更新数据即可
const parent = this.currentNode.parent
const children = parent.data.children || parent.data
const index = children.findIndex(d => d.id === this.currentData.id)
children.splice(index, 1)
}).catch(() => {})
}
复制代码
总结
其实没有什么难度,也就是理解了element-ui官方的例子后很简单就可以做出自己想要的效果。大家有更好的方法欢迎补充哦!