组件调用

  1. <template>
  2. <!-- 行模式 -->
  3. <el-form inline>
  4. <el-form-item label="inline 默认:">
  5. <select-tree :options="options" v-model="selected" />
  6. </el-form-item>
  7. <el-form-item label="inline 定义宽度:">
  8. <select-tree width="200" :options="options" v-model="selected" />
  9. </el-form-item>
  10. </el-form>
  11. <!-- 块模式 -->
  12. <el-form>
  13. <el-form-item label="自适应:">
  14. <select-tree v-model="selected" :options="options" :props="defaultProps" />
  15. </el-form-item>
  16. </el-form>
  17. </template>
  18.  
  19. <script>
  20. import SelectTree from '@/components/widget/SelectTree.vue';
  21.  
  22. export default {
  23. name: 'about',
  24. components: {
  25. SelectTree,
  26. },
  27. data() {
  28. return {
  29. // 默认选中值
  30. selected: 'A',
  31. // 数据默认字段
  32. defaultProps: {
  33. parent: 'parentId', // 父级唯一标识
  34. value: 'id', // 唯一标识
  35. label: 'label', // 标签显示
  36. children: 'children', // 子级
  37. },
  38. // 数据列表
  39. options: [
  40. {
  41. parentId: '0',
  42. id: 'A',
  43. label: 'label-A',
  44. children: [
  45. {
  46. parentId: 'A',
  47. id: 'A-1',
  48. label: 'label-A-1',
  49. },
  50. ],
  51. },
  52. {
  53. parentId: '0',
  54. value: 'B',
  55. label: 'label-B',
  56. children: [],
  57. },
  58. ],
  59. };
  60. },
  61. };
  62. </script>

SelectTree.vue

  1. <!-- 树状选择器 -->
  2. <template>
  3. <el-popover
  4. ref="popover"
  5. placement="bottom-start"
  6. trigger="click"
  7. @show="onShowPopover"
  8. @hide="onHidePopover">
  9. <el-tree
  10. ref="tree"
  11. class="select-tree"
  12. highlight-current
  13. :style="`min-width: ${treeWidth}`"
  14. :data="data"
  15. :props="props"
  16. :expand-on-click-node="false"
  17. :filter-node-method="filterNode"
  18. :default-expand-all="false"
  19. @node-click="onClickNode">
  20. </el-tree>
  21. <el-input
  22. slot="reference"
  23. ref="input"
  24. v-model="labelModel"
  25. clearable
  26. :style="`width: ${width}px`"
  27. :class="{ 'rotate': showStatus }"
  28. suffix-icon="el-icon-arrow-down"
  29. :placeholder="placeholder">
  30. </el-input>
  31. </el-popover>
  32. </template>
  33.  
  34. <script>
  35. export default {
  36. name: 'Pagination',
  37. props: {
  38. // 接收绑定参数
  39. value: String,
  40. // 输入框宽度
  41. width: String,
  42. // 选项数据
  43. options: {
  44. type: Array,
  45. required: true,
  46. },
  47. // 输入框占位符
  48. placeholder: {
  49. type: String,
  50. required: false,
  51. default: '请选择',
  52. },
  53. // 树节点配置选项
  54. props: {
  55. type: Object,
  56. required: false,
  57. default: () => ({
  58. parent: 'parentId',
  59. value: 'rowGuid',
  60. label: 'areaName',
  61. children: 'children',
  62. }),
  63. },
  64. },
  65. // 设置绑定参数
  66. model: {
  67. prop: 'value',
  68. event: 'selected',
  69. },
  70. computed: {
  71. // 是否为树状结构数据
  72. dataType() {
  73. const jsonStr = JSON.stringify(this.options);
  74. return jsonStr.indexOf(this.props.children) !== -1;
  75. },
  76. // 若非树状结构,则转化为树状结构数据
  77. data() {
  78. return this.dataType ? this.options : this.switchTree();
  79. },
  80. },
  81. watch: {
  82. labelModel(val) {
  83. if (!val) {
  84. this.valueModel = '';
  85. }
  86. this.$refs.tree.filter(val);
  87. },
  88. value(val) {
  89. this.labelModel = this.queryTree(this.data, val);
  90. },
  91. },
  92. data() {
  93. return {
  94. // 树状菜单显示状态
  95. showStatus: false,
  96. // 菜单宽度
  97. treeWidth: 'auto',
  98. // 输入框显示值
  99. labelModel: '',
  100. // 实际请求传值
  101. valueModel: '0',
  102. };
  103. },
  104. created() {
  105. // 检测输入框原有值并显示对应 label
  106. if (this.value) {
  107. this.labelModel = this.queryTree(this.data, this.value);
  108. }
  109. // 获取输入框宽度同步至树状菜单宽度
  110. this.$nextTick(() => {
  111. this.treeWidth = `${(this.width || this.$refs.input.$refs.input.clientWidth) - 24}px`;
  112. });
  113. },
  114. methods: {
  115. // 单击节点
  116. onClickNode(node) {
  117. this.labelModel = node[this.props.label];
  118. this.valueModel = node[this.props.value];
  119. this.onCloseTree();
  120. },
  121. // 偏平数组转化为树状层级结构
  122. switchTree() {
  123. return this.cleanChildren(this.buildTree(this.options, '0'));
  124. },
  125. // 隐藏树状菜单
  126. onCloseTree() {
  127. this.$refs.popover.showPopper = false;
  128. },
  129. // 显示时触发
  130. onShowPopover() {
  131. this.showStatus = true;
  132. this.$refs.tree.filter(false);
  133. },
  134. // 隐藏时触发
  135. onHidePopover() {
  136. this.showStatus = false;
  137. this.$emit('selected', this.valueModel);
  138. },
  139. // 树节点过滤方法
  140. filterNode(query, data) {
  141. if (!query) return true;
  142. return data[this.props.label].indexOf(query) !== -1;
  143. },
  144. // 搜索树状数据中的 ID
  145. queryTree(tree, id) {
  146. let stark = [];
  147. stark = stark.concat(tree);
  148. while (stark.length) {
  149. const temp = stark.shift();
  150. if (temp[this.props.children]) {
  151. stark = stark.concat(temp[this.props.children]);
  152. }
  153. if (temp[this.props.value] === id) {
  154. return temp[this.props.label];
  155. }
  156. }
  157. return '';
  158. },
  159. // 将一维的扁平数组转换为多层级对象
  160. buildTree(data, id = '0') {
  161. const fa = (parentId) => {
  162. const temp = [];
  163. for (let i = 0; i < data.length; i++) {
  164. const n = data[i];
  165. if (n[this.props.parent] === parentId) {
  166. n.children = fa(n.rowGuid);
  167. temp.push(n);
  168. }
  169. }
  170. return temp;
  171. };
  172. return fa(id);
  173. },
  174. // 清除空 children项
  175. cleanChildren(data) {
  176. const fa = (list) => {
  177. list.map((e) => {
  178. if (e.children.length) {
  179. fa(e.children);
  180. } else {
  181. delete e.children;
  182. }
  183. return e;
  184. });
  185. return list;
  186. };
  187. return fa(data);
  188. },
  189. },
  190. };
  191. </script>
  192.  
  193. <style>
  194. .el-input.el-input--suffix {
  195. cursor: pointer;
  196. overflow: hidden;
  197. }
  198. .el-input.el-input--suffix.rotate .el-input__suffix {
  199. transform: rotate(180deg);
  200. }
  201. .select-tree {
  202. max-height: 350px;
  203. overflow-y: scroll;
  204. }
  205. /* 菜单滚动条 */
  206. .select-tree::-webkit-scrollbar {
  207. z-index: 11;
  208. width: 6px;
  209. }
  210. .select-tree::-webkit-scrollbar-track,
  211. .select-tree::-webkit-scrollbar-corner {
  212. background: #fff;
  213. }
  214. .select-tree::-webkit-scrollbar-thumb {
  215. border-radius: 5px;
  216. width: 6px;
  217. background: #b4bccc;
  218. }
  219. .select-tree::-webkit-scrollbar-track-piece {
  220. background: #fff;
  221. width: 6px;
  222. }
  223. </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. Loadrunner自带协议分析工具:Protocol Advisor

    录制脚本之前,选对协议很关键,否则错误的协议会导致Virtual User Generator 录制不到脚本,或录制的脚本不完整,有些应用可能需要选择多个协议才能完整的记录 客户端与服务器端的请求. ...

  2. 这几天添加ccbi 出现的问题

    父类是一个ccbi...在父类的onNodeLoaded 里面添加子类的ccbi ... 出现了父类为空的情况...获取不到时间轴..动画为空... 需要在父类的onEnter里面写添加子类的ccbi ...

  3. Use the SVN command-line tool

    欢迎关注我的社交账号: 博客园地址: http://www.cnblogs.com/jiangxinnju/p/4781259.html GitHub地址: https://github.com/ji ...

  4. maven 介绍(二)

    本文内容主要摘自:http://www.konghao.org/index 内部视频 三.仓库 仓库:本地仓库:远程仓库:私有仓库(nexus) 1. nexus 的安装: 1). 下载并且解压缩 2 ...

  5. 基于Python的接口测试框架实例

    文章来源:http://www.jb51.net/article/96481.htm 下面小编就为大家带来一篇基于Python的接口测试框架实例.小编觉得挺不错的,现在就分享给大家,也给大家做个参考. ...

  6. LNMP环境简单教程

    一:LNMP可以进行简单优化,主要2方面.NGINX和PHP进程数,分别是以下2个文件: 1. /usr/local/nginx/conf/nginx.conf2. /usr/local/php/et ...

  7. 为什么iterator,foreach遍历时不能进行remove操作?除了一种情况可以这样(特殊情况)?

    Exception in thread "main" java.util.ConcurrentModificationException 并发修改异常引发的思考! 1 foreac ...

  8. Web前端学习笔记之JavaScript、jQuery、AJAX、JSON的区别

    官网的英文解释: javascript和jQuery有点关系,js是一种脚本语言,主要用于客户端,现在主要用于实现一些网页效果. jquery是js的一个库,你可以认为是对js的补充,提供了很多方便易 ...

  9. Python3.x:BeautifulSoup()解析网页内容出现乱码

    Python3.x:BeautifulSoup()解析网页内容出现乱码 问题: start_html = requests.get(all_url, headers=Hostreferer) Beau ...

  10. 照着官网来安装openstack pike之nova安装

    nova组件安装分为控制节点和计算节点,还是先从控制节点安装 1.前提条件,数据库为nova创建库和账户密码来连接数据库 # mysql -u root -p MariaDB [(none)]> ...