组件调用

 <template>
<!-- 行模式 -->
<el-form inline>
<el-form-item label="inline 默认:">
<select-tree :options="options" v-model="selected" />
</el-form-item>
<el-form-item label="inline 定义宽度:">
<select-tree width="200" :options="options" v-model="selected" />
</el-form-item>
</el-form>
<!-- 块模式 -->
<el-form>
<el-form-item label="自适应:">
<select-tree v-model="selected" :options="options" :props="defaultProps" />
</el-form-item>
</el-form>
</template> <script>
import SelectTree from '@/components/widget/SelectTree.vue'; export default {
name: 'about',
components: {
SelectTree,
},
data() {
return {
// 默认选中值
selected: 'A',
// 数据默认字段
defaultProps: {
parent: 'parentId', // 父级唯一标识
value: 'id', // 唯一标识
label: 'label', // 标签显示
children: 'children', // 子级
},
// 数据列表
options: [
{
parentId: '0',
id: 'A',
label: 'label-A',
children: [
{
parentId: 'A',
id: 'A-1',
label: 'label-A-1',
},
],
},
{
parentId: '0',
value: 'B',
label: 'label-B',
children: [],
},
],
};
},
};
</script>

SelectTree.vue

 <!-- 树状选择器 -->
<template>
<el-popover
ref="popover"
placement="bottom-start"
trigger="click"
@show="onShowPopover"
@hide="onHidePopover">
<el-tree
ref="tree"
class="select-tree"
highlight-current
:style="`min-width: ${treeWidth}`"
:data="data"
:props="props"
:expand-on-click-node="false"
:filter-node-method="filterNode"
:default-expand-all="false"
@node-click="onClickNode">
</el-tree>
<el-input
slot="reference"
ref="input"
v-model="labelModel"
clearable
:style="`width: ${width}px`"
:class="{ 'rotate': showStatus }"
suffix-icon="el-icon-arrow-down"
:placeholder="placeholder">
</el-input>
</el-popover>
</template> <script>
export default {
name: 'Pagination',
props: {
// 接收绑定参数
value: String,
// 输入框宽度
width: String,
// 选项数据
options: {
type: Array,
required: true,
},
// 输入框占位符
placeholder: {
type: String,
required: false,
default: '请选择',
},
// 树节点配置选项
props: {
type: Object,
required: false,
default: () => ({
parent: 'parentId',
value: 'rowGuid',
label: 'areaName',
children: 'children',
}),
},
},
// 设置绑定参数
model: {
prop: 'value',
event: 'selected',
},
computed: {
// 是否为树状结构数据
dataType() {
const jsonStr = JSON.stringify(this.options);
return jsonStr.indexOf(this.props.children) !== -1;
},
// 若非树状结构,则转化为树状结构数据
data() {
return this.dataType ? this.options : this.switchTree();
},
},
watch: {
labelModel(val) {
if (!val) {
this.valueModel = '';
}
this.$refs.tree.filter(val);
},
value(val) {
this.labelModel = this.queryTree(this.data, val);
},
},
data() {
return {
// 树状菜单显示状态
showStatus: false,
// 菜单宽度
treeWidth: 'auto',
// 输入框显示值
labelModel: '',
// 实际请求传值
valueModel: '0',
};
},
created() {
// 检测输入框原有值并显示对应 label
if (this.value) {
this.labelModel = this.queryTree(this.data, this.value);
}
// 获取输入框宽度同步至树状菜单宽度
this.$nextTick(() => {
this.treeWidth = `${(this.width || this.$refs.input.$refs.input.clientWidth) - 24}px`;
});
},
methods: {
// 单击节点
onClickNode(node) {
this.labelModel = node[this.props.label];
this.valueModel = node[this.props.value];
this.onCloseTree();
},
// 偏平数组转化为树状层级结构
switchTree() {
return this.cleanChildren(this.buildTree(this.options, '0'));
},
// 隐藏树状菜单
onCloseTree() {
this.$refs.popover.showPopper = false;
},
// 显示时触发
onShowPopover() {
this.showStatus = true;
this.$refs.tree.filter(false);
},
// 隐藏时触发
onHidePopover() {
this.showStatus = false;
this.$emit('selected', this.valueModel);
},
// 树节点过滤方法
filterNode(query, data) {
if (!query) return true;
return data[this.props.label].indexOf(query) !== -1;
},
// 搜索树状数据中的 ID
queryTree(tree, id) {
let stark = [];
stark = stark.concat(tree);
while (stark.length) {
const temp = stark.shift();
if (temp[this.props.children]) {
stark = stark.concat(temp[this.props.children]);
}
if (temp[this.props.value] === id) {
return temp[this.props.label];
}
}
return '';
},
// 将一维的扁平数组转换为多层级对象
buildTree(data, id = '0') {
const fa = (parentId) => {
const temp = [];
for (let i = 0; i < data.length; i++) {
const n = data[i];
if (n[this.props.parent] === parentId) {
n.children = fa(n.rowGuid);
temp.push(n);
}
}
return temp;
};
return fa(id);
},
// 清除空 children项
cleanChildren(data) {
const fa = (list) => {
list.map((e) => {
if (e.children.length) {
fa(e.children);
} else {
delete e.children;
}
return e;
});
return list;
};
return fa(data);
},
},
};
</script> <style>
.el-input.el-input--suffix {
cursor: pointer;
overflow: hidden;
}
.el-input.el-input--suffix.rotate .el-input__suffix {
transform: rotate(180deg);
}
.select-tree {
max-height: 350px;
overflow-y: scroll;
}
/* 菜单滚动条 */
.select-tree::-webkit-scrollbar {
z-index: 11;
width: 6px;
}
.select-tree::-webkit-scrollbar-track,
.select-tree::-webkit-scrollbar-corner {
background: #fff;
}
.select-tree::-webkit-scrollbar-thumb {
border-radius: 5px;
width: 6px;
background: #b4bccc;
}
.select-tree::-webkit-scrollbar-track-piece {
background: #fff;
width: 6px;
}
</style>

Element-UI 实现下拉树的更多相关文章

  1. vue+element下拉树选择器

    项目需求:输入框点击弹出树形下拉结构,可多选或者单选. 解决方案:1.使用layui formSelect多选插件 2.基于vue+elementui 下拉框和树形控件组合成树形下拉结构 <el ...

  2. zTree开发下拉树

    最近,因为工作需要一个树形下拉框的组件,经过查资料一般有两种的实现方法.其一,就是使用zTree实现:其二,就是使用easyUI实现.因为公司的前端不是使用easyUI设计的,故这里我选择了zTree ...

  3. 开源框架.netCore DncZeus学习(五)下拉树的实现

    千里之行,始于足下,先从一个小功能研究起,在菜单管理页面有一个下拉树,先研究下它怎么实现的 1.先找到menu.vue页面 惯性思维先搜索请选择三个字,原来是动态生成的 再向上找DropDown组件, ...

  4. vue 模拟下拉树

    // 使用vue 做表格部分其他部分暂不修改 var app = new Vue({ el: "#freightTbl", watch: { //监听表格数据的变化[使用 watc ...

  5. vue-Treeselect实现组织机构(员工)下拉树的功能

    知识点:前端使用vuetree的组件库,调用后台查询组织机构,包括人员的接口 实现下拉树的功能 查考: vue-treeselect官网:https://vue-treeselect.js.org/ ...

  6. Extjs下拉树代码测试总结

    http://blog.csdn.net/kunoy/article/details/8067801 首先主要代码源自网络,对那些无私的奉献者表示感谢! 笔者对这些代码做了二次修改,并总结如下: Ex ...

  7. EXTJS下拉树ComboBoxTree参数提交及回显方法

    http://blog.csdn.net/wjlht/article/details/6085245 使用extjs可以构造出下拉数,但是不方便向form提交参数,在此,笔者想到一个办法,很方便Com ...

  8. layui扩展组件,下拉树多选

      项目介绍 项目中需要用到下拉树多选功能,找到两个相关组件moretop-layui-select-ext和wujiawei0926-treeselect,但是moretop-layui-selec ...

  9. EasyUI-combotree 下拉树 数据回显时默认选中

    组合树(combotree)把选择控件和下拉树结合起来.它与组合框(combobox)相似,不同的是把列表替换成树组件.组合树(combotree)支持带有用于多选的树状态复选框的树. 依赖 comb ...

  10. elementUI下拉树组件封装

    使用组件:Popover 弹出框.Tree 树形控件 和 input 输入框 用法: 1.新建一个.vue文件,粘贴以下组件封装的代码(完全可以使用) 2.在页面需要使用下拉树的地方调用即可. (1) ...

随机推荐

  1. log4j的配置和使用

    日志记录 在应用程序中添加日志记录总的来说基于三个目的: 监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作: 跟踪代码运行时轨迹,作为日后审计的依据:担当集成开发环境中的调试器 ...

  2. Pythonic 的代码编写方法

    1.模块导入 你是不是经常对调用模块时输入一长串模块索引感到头疼?说实在的,数量少的时候或许还可以勉强忍受,一旦程序规模上去了,这也是一项不容小觑的工程 #Bad import urllib.requ ...

  3. hdu2825Wireless Password

    地址:http://acm.hdu.edu.cn/showproblem.php?pid=2825 题目: Wireless Password Time Limit: 2000/1000 MS (Ja ...

  4. Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) D - Dynamic Problem Scoring

    地址:http://codeforces.com/contest/807/problem/D 题目: D. Dynamic Problem Scoring time limit per test 2 ...

  5. POJ - 3308 Paratroopers (最小点权覆盖)

    题意:N*M个格点,K个位置会有敌人.每行每列都有一门炮,能打掉这一行(列)上所有的敌人.每门炮都有其使用价值.总花费是所有使用炮的权值的乘积.求最小的总花费. 若每门炮的权值都是1,就是求最小点覆盖 ...

  6. 开源一款android 偷拍 app【静拍】豌豆荚、flyme商店已经上线

    首先先花3秒时间,预览下下app的大概是做啥的,解决啥痛点的:) app: 本地下载地址 需求点: 1:音量键可以拍照 2:没有快门声.闪光灯 3:锁屏下.或者是在其他程序界面都可以拍照 思路: 1: ...

  7. JavaWeb 如何在web.xml中配置多个servlet

    15:34:42 <servlet> <description></description> <display-name>ListMusicServle ...

  8. ARKit 研究笔记一

    软件需求:Xcode9.x .blender 硬件需求:iphone 6s + 系统:iOS 11 + 技能储备: ARKit .SceneKit(苹果提供的3d游戏库) 或 SpriteKit(苹果 ...

  9. 制作RPM包

    RPM包制作过程 1.1 前期工作 1)创建打包用的目录rpmbuild/{BUILD,SPECS,RPMS, SOURCES,SRPMS} 建议使用普通用户,在用户家目录中创建 2)确定好制作的对象 ...

  10. 20145109 实验四 Andoid开发基础

    安装Android 打开 默认程序中有helloworld 按下下图红框中的键: 遇到问题: 方法:修改build.gradle