Vue+ElementUI树形控件整合下拉功能菜单
(tree+dropdown+input)
这篇博客主要介绍树形控件的两个⼩⼩的功能:
下拉菜单
输⼊过滤框
以CSS样式为主,也会涉及到Vue组件和element组件的使⽤。
对于没有层级的数据,我们可以使⽤表格或卡⽚来展⽰。要展⽰或建⽴层级关系,就⼀定会⽤到树形组件了。
使⽤Vue + Element UI,构建出最基本的树如下图所⽰:
现在我们就要在这个基础上进⾏改造,使页⾯更加符合我们的交互场景。
⼀、下拉菜单
将下拉菜单嵌到树节点中,使操作更加简便、紧凑。
效果演⽰
效果如图:
图⽰1:悬浮在树节点状态
图⽰2:点击三个点图标状态
图⽰3:选中并选择菜单
如上,当⿏标悬浮在树节点上时,出现竖着的三个⼩点,点击时弹出下拉菜单,显⽰可以对树节点进⾏的操作。
实现步骤
1、使⽤插槽(slot) + ⼦组件
⽗组件(含有树形控件)模板代码
<el-tree :data="resourceTree" :ref="tree" node-key="id"  size="small"
:highlight-current="true" :check-on-click-node="true" >
<span class="custom-tree-node" slot-scope="{ node, data }">
<div class="custom-tree-node-wrapper">
<span class="custom-tree-node-label">
{{ node.label }}
</span>
<span class="operate-btns">
<dot-dropdown  :events="dropMenuEvents" :data="{node,data}" @addNode="addNode" />
</span>
</div>
</span>
</el-tree>
2、 DotDropdown 下拉框代码
很多树形结构都会使⽤该下拉框,所以定义组件,⽅便复⽤。
<template>
<el-dropdown trigger="click" class="custom-tree-menu" size="small">
<i class="el-icon-more rotate " />
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for='(item,index) in events' :key="index" :divided="index >0" @click.native="clickMenu(item)">
{{item.label}}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
props: {
events: {
type: Array,
default: function() {
return [
{
label: '新建同级',
funcName: 'addNode'
},
{
label: '编辑',
funcName: 'editNode'
},
{
label: '删除',
funcName: 'deleteNode'
}
]
}
},
// 注⼊数据
data: {
type: Object
}
},
methods: {
clickMenu(item) {
this.$emit(item.funcName, this.data)
div下拉菜单}
}
}
模板代码很简单,是⼀个点击触发的下拉菜单组件(trigger="click"),菜单循环props中传⼊的events属性,data为从⽗组件拿到的数据,定义了菜单和菜单的事件(⽅法名称),当点击菜单(@click.native)时,触发:
this.$emit(item.funcName, this.data)
容易看出,数据和实现⽅法都是⽗组件的,该⼦组件只做了转发。
3、⽗组件使⽤⼦组件
引⼊和注册⼦组件,并定义好对应的⽅法即可。下⾯给出使⽤⽰例:
<span class="operate-btns">
<dot-dropdown v-if="pe === 1" :events="dropMenuEvents" :data="{node,data}"/>
<dot-dropdown v-if="pe === 2" :events="sysDropMenuEvents" :data="{node,data}" @addNode="addResource" />
</span>
根据数据节点的类型,注⼊不同的events属性,显⽰不同的下拉框菜单。(常⽤场景:根节点不可删除、不可编辑,只能新增⼦级,叶⼦节点可以新增同级和⼦级)。
在⽗组件中的data中定义:
sysDropMenuEvents: [{ label: '新增资源', funcName: 'addNode' }],
dropMenuEvents: [
{ label: '新建同级', funcName: 'addPeerNode' },
{ label: '新建⼦级', funcName: 'addNode' },
{ label: '分配操作', funcName: 'distributeAction' },
{ label: '编辑', funcName: 'editNode' },
{ label: '删除', funcName: 'removeNode' }
]
⽗组件编写实际功能⽅法:
// 打开新增资源弹窗
addResource({ node, data }) {
...
}
⽗组件注⼊data时,将树节点插槽中的node和data都注⼊了进去(:data="{node,data}"),在使⽤时也可以⽤过同样的⼤括号+属性名的⽅式拿到对应的属性,这⾥体现了ES6解构赋值的特性。
4、⽗组件样式
⽗组件中,树节点的样式:
.el-tree-node__content {
position: relative;
.operate-btns {
position: absolute;
right: 2px;
display: none;
}
// ⿏标悬停时,展⽰
&:hover,
:focus-within {
.operate-btns {
display: inline;
}
}
}
}
⼦绝对,⽗相对,使操作按钮靠贴边显⽰
⽆状态时不显⽰,hover或内部元素被激活时显⽰(:hover :focus-within)
5、⼦组件样式
旋转图标
原本的图标使⽤的是element UI提供的<i class="el-icon-more" />,是横着的点点点↓
图标有点⼩,颜⾊也不喜欢。改下字体让它变⼤⼀点。这⾥注意需要修改的是元素的before伪类: .el-icon-more:before {
content: "\E794";
color: #c0c4cc;
font-size: 20px;
}
加⼀个transform将它旋转90°,悬停时⿏标样式为pointer:
.rotate {
cursor: pointer;
margin-left: 5px;
transform: rotate(90deg);
}
点击时,增加圆形半透明的灰⾊背景:
.rotate:focus {
width: 20px;
height: 20px;
border-radius: 4em;
background-color: rgba(130, 132, 138, 0.2);
}
⾄此,下拉全部完成。
除了⽤在树节点中,也可以⽤在表格中。
输⼊过滤框
el-tree提供了过滤⽅法,使⽤:filter-node-method="filterNode"属性即可。这⾥主要分享样式:
效果:
模板代码:
<div class="filter-input">
<el-input placeholder="输⼊资源名称进⾏过滤" v-model="filterText" size="small" prefix-icon="el-icon-search">
</el-input>
</div>
去掉输⼊框上、左右边框和圆⾓,并两侧留出10px边距
.el-input__inner,.el-input-group__prepend{
width: calc(100% - 20px);
margin:0 10px;
height: 40px;
border-top:none;
border-width: 0 0 1px;
border-radius:0;
}
调整搜索图标⼤⼩、颜⾊和粗细,并稍微调整位置:
.el-input__prefix{
.el-input__icon{
margin-right: 15px;
display: inline-block;
}
font-size:18px;
}
此时点击输⼊框,只有下边变蓝⾊,希望图标的样式也随之更改。
只有input被触发了focus事件,icon感知不到,:focus伪类不满⾜需求了。我们可以使⽤:focus-within伪类,加在icon和input共同的⽗类上。
.el-input:focus-within{
.el-icon-search:before {
color: #3c6eff;
font-weight: bold;
}
}
⾄此完成。
总结
没写前端之前以为前端只是展⽰从后端拿到的数据,但现在觉得,前端作为⾯向⽤户的直接门⾯,承担了绝⼤部分交互体验优化的任务。合理的布局和样式能避免⽤户的⽆效操作,体验的优化是⼀个漫
长⽽细致的过程,可能需要仔细打磨,才能做出好⽤的产品。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。