赞
踩
1、自定义树节点前展开收起图标
2、可对节点数据进行模糊查询
3、右击第一级节点可以进行同级节点增加
4、双击节点或点击修改节点 都可以对节点获取焦点并进行修改,回车修改成功
5、可对节点进行拖拽,实现节点移动功能
6、右击节点可进行增删改
- <div class="tree-container">
- <el-input placeholder="输入关键字进行过滤" v-model="filterText" class="search">
- </el-input>
- <el-tree :data="treeData" node-key="id" default-expand-all @node-click="handleLeftclick"
- @node-drag-start="handleDragStart" @node-drag-enter="handleDragEnter" @node-drag-leave="handleDragLeave"
- @node-drag-over="handleDragOver" @node-drag-end="handleDragEnd" @node-drop="handleDrop"
- @node-contextmenu="rightClick" :filter-node-method="filterNode" draggable :allow-drop="allowDrop"
- :allow-drag="allowDrag" ref="tree" class="tree-line">
- <span class="slot-t-node" slot-scope="{ node, data }" @dblclick="editNode(data)">
- <span v-show="!data.isEdit">
- <span :class="[data.id >= 99 ? 'slot-t-node--label' : '']">
- <i v-if="data.type == 'catalog'" class="el-icon-folder" />
- <i v-if="data.type == 'menu'" class="el-icon-tickets" />
- <i v-if="data.type == 'submenu'" class="el-icon-document" />
- <span> {{ node.label }}</span>
- </span>
- </span>
- <span v-show="data.isEdit">
- <el-input class="slot-t-input" size="mini" autofocus v-model="data.label" :ref="'slotTreeInput' + data.id"
- @blur.stop="NodeBlur(node, data)" @keydown.native.enter="NodeBlur(node, data)"></el-input>
- </span>
- </span>
- </el-tree>
- <div class="box-menu" v-show="menuVisible" :style="{ left: menu_left + 'px', top: menu_top + 'px' }">
- <div @click="addSameLevelNode(0)" v-show="firstLevel">
- <i class="el-icon-circle-plus-outline"></i> 同级增加
- </div>
- <div class="add" @click="addChildNode()">
- <i class="el-icon-circle-plus-outline"></i> 子级增加
- </div>
- <div class="delete" @click="deleteNode()">
- <i class="el-icon-remove-outline"></i> 删除节点
- </div>
- <div class="edit" @click="editNode()">
- <i class="el-icon-edit"></i> 修改节点
- </div>
- </div>
- </div>
- <style scoped lang="less">
- .el-tree>.is-leaf {
- color: transparent;
- }
- .tree-container /deep/ .el-tree-node__expand-icon.expanded {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
- .tree-container /deep/ .el-tree-node__expand-icon.expanded {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
- .tree-container /deep/ .el-icon-caret-right:before {
- background: url("../../assets/node-collapse.png") no-repeat;
- content: '';
- display: block;
- width: 12px;
- height: 12px;
- font-size: 12px;
- background-size: 10px;
- }
- /*
- //有子节点 且已展开*/
- .tree-container /deep/ .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
- background: url("../../assets/node-expand.png") no-repeat;
- content: '';
- display: block;
- width: 12px;
- height: 12px;
- font-size: 12px;
- background-size: 10px;
- }
-
- /* //没有子节点*/
- .tree-container /deep/ .el-tree-node__expand-icon.is-leaf::before {
- background: transparent no-repeat 0 3px;
- content: '';
- display: block;
- width: 12px;
- height: 12px;
- font-size: 12px;
- background-size: 10px;
- }
- /* 点击节点时的选中颜色 */
- .tree-container /deep/.el-tree-node.is-current>.el-tree-node__content {
- color: #3D5ECC !important;
- }
- .tree-container /deep/ .el-tree-node__expand-icon {
- margin-left: 15px;
- // padding: 0px;
- }
- .tree-container /deep/ .el-tree-node__expand-icon.is-leaf {
- margin-left: 0px;
- }
- .tree-container /deep/ .el-tree-node {
- position: relative;
- padding-left: 16px;
- }
- .tree-container /deep/ .el-tree-node__children {
- padding-left: 16px;
- }
- .tree-container /deep/ .el-tree>.el-tree-node:before {
- border-left: none;
- }
- .tree-container /deep/ .el-tree>.el-tree-node:after {
- border-top: none;
- }
- .tree-container /deep/ .el-tree>.el-tree-node:before {
- border-left: none;
- }
- .tree-container /deep/ .el-tree>.el-tree-node:after {
- border-top: none;
- }
- .tree-container /deep/ .el-tree-node:before {
- content: "";
- left: 10px;
- position: absolute;
- right: auto;
- border-width: 1px;
- }
- .tree-container /deep/ .el-tree-node:after {
- content: "";
- left: 10px;
- position: absolute;
- right: auto;
- border-width: 1px;
- }
- .tree-container /deep/ .el-tree-node:before {
- border-left: 1px dashed #ccc;
- bottom: 0px;
- height: 100%;
- top: -19px;
- width: 1px;
- }
- .tree-container /deep/ .el-tree-node:after {
- border-top: 1px dashed #ccc;
- height: 25px;
- top: 20px;
- width: 20px;
- }
- .el-tree-node :last-child:before {
- height: 40px;
- }
- .tree-container {
- margin: 10px;
- }
- .tree-container /deep/ .el-tree .el-tree-node {
- position: relative;
- }
- .tree-container /deep/ .el-tree-node .el-tree-node__content {
- height: 34px;
- padding-left: 0px !important;
- border: none;
- }
- .tree-container /deep/ .el-tree-node .el-tree-node__content::before {
- border-left: 1px dashed #ccc;
- height: 100%;
- top: 0;
- width: 1px;
- margin-left: 1px;
- margin-top: 0px;
- z-index: 8;
- }
- .tree-container /deep/ .el-tree-node .el-tree-node__children .el-tree-node__content::before {
- border-left: 0px dashed #ccc;
- height: 100%;
- top: 0;
- width: 1px;
- margin-left: 1px;
- margin-top: 0px;
- z-index: 8;
- }
- .tree-container /deep/ .el-tree-node .el-tree-node__content::after {
- border-top: 1px dashed #ccc;
- height: 1px;
- top: 18px;
- width: 13px;
- margin-left: 1px;
- z-index: 8;
- }
- .tree-container /deep/ .el-tree-node .el-tree-node__children .el-tree-node__content::after {
- border-top: 0px dashed #ccc;
- }
- .tree-container .el-tree-node .el-tree-node__content::before,
- .tree-container .el-tree-node .el-tree-node__content::after {
- content: "";
- position: absolute;
- right: auto;
- }
-
- .el-tree {
- width: 20%;
- margin-top: 10px;
- }
-
- .search {
- width: 20%;
- cursor: pointer;
- }
- .box-menu {
- width: 150px;
- position: absolute;
- z-index: 1000;
- background-color: #fff;
- box-shadow: 0px 0px 10px #ccc, 0px 0px 20px #ccc, 0px 0px 30px #ccc;
- padding: 10px;
-
- div {
- cursor: pointer;
- line-height: 30px;
- }
-
- div:active {
- color: blue;
- }
- }
- </style>
- NodeBlur(Node, data) {
- console.log(Node, data)
- if (data.label.length === 0) {
- this.$message.error('菜单名不可为空!')
- return false
- } else {
- if (data.isEdit) {
- this.$set(data, 'isEdit', false)
- console.log(data.isEdit)
- }
- this.$nextTick(() => {
- this.$refs['slotTreeInput' + data.id].$refs.input.focus()
- })
- }
- },
- // 查询
- filterNode(value, data) {
- if (!value) return true
- return data.label.indexOf(value) !== -1
- },
-
-
-
- watch: {
- filterText(val) {
- this.$refs.tree.filter(val)
- }
- },
- allowDrop(draggingNode, dropNode, type) {
- if (dropNode.data.label === '二级 3-1') {
- return type !== 'inner'
- } else {
- return true
- }
- },
- allowDrag(draggingNode) {
- return draggingNode.data.label.indexOf('三级 3-2-2') === -1
- },
-
-
- handleDragStart(node, ev) {
- console.log('drag start', node)
- },
- handleDragEnter(draggingNode, dropNode, ev) {
- console.log('tree drag enter: ', dropNode.label)
- },
- handleDragLeave(draggingNode, dropNode, ev) {
- console.log('tree drag leave: ', dropNode.label)
- },
- handleDragOver(draggingNode, dropNode, ev) {
- console.log('tree drag over: ', dropNode.label)
- },
- handleDragEnd(draggingNode, dropNode, dropType, ev) {
- console.log('tree drag end: ', dropNode && dropNode.label, dropType)
- },
- handleDrop(draggingNode, dropNode, dropType, ev) {
- console.log('tree drop: ', dropNode.label, dropType)
- },
- // 鼠标右击事件
- rightClick(event, object, Node, element) {
- console.log(event, object)
- this.currentData = object
- this.currentNode = Node
- if (Node.level === 1) {
- this.firstLevel = true
- } else {
- this.firstLevel = false
- }
- this.menuVisible = true
- document.addEventListener('click', this.foo)
- // 将菜单显示在鼠标点击旁边定位
- this.menu_left = event.clientX -140;
- this.menu_top = event.clientY - 40;
-
- },
- // 鼠标左击事件
- handleLeftclick(data, node) {
- this.foo()
- },
- // 取消鼠标监听事件 菜单栏
- foo() {
- this.menuVisible = false
- // 要及时关掉监听,不关掉的是一个坑,不信你试试,虽然前台显示的时候没有啥毛病,加一个alert你就知道了
- document.removeEventListener('click', this.foo)
- },
- // 增加同级节点事件
- addSameLevelNode() {
- let id = Math.ceil(Math.random() * 100)
- var data = { id: id, label: '新增节点' }
- this.$refs.tree.append(data, this.currentNode.parent)
- },
- // 增加子级节点事件
- addChildNode() {
- console.log(this.currentData)
- console.log(this.currentNode)
- if (this.currentNode.level >= 3) {
- this.$message.error('最多只支持三级!')
- return false
- }
- let id = Math.ceil(Math.random() * 100)
- var data = { id: id, label: '新增节点' }
- this.$refs.tree.append(data, this.currentNode)
- },
- // 删除节点
- deleteNode() {
- this.$refs.tree.remove(this.currentNode)
- },
- // 编辑节点
- editNode(data) {
- console.log(data)
- this.currentData = data ? data : this.currentData
- if (!this.currentData.isEdit) {
- this.$set(this.currentData, 'isEdit', true)
- }
- // 获取焦点
- this.$nextTick(() => {
- this.$refs['slotTreeInput' + this.currentData.id].focus()
- })
- },
- <template>
- <div class="tree-container">
- <el-input placeholder="输入关键字进行过滤" v-model="filterText" class="search">
- </el-input>
- <el-tree :data="treeData" node-key="id" default-expand-all @node-click="handleLeftclick"
- @node-drag-start="handleDragStart" @node-drag-enter="handleDragEnter" @node-drag-leave="handleDragLeave"
- @node-drag-over="handleDragOver" @node-drag-end="handleDragEnd" @node-drop="handleDrop"
- @node-contextmenu="rightClick" :filter-node-method="filterNode" draggable :allow-drop="allowDrop"
- :allow-drag="allowDrag" ref="tree" class="tree-line">
- <span class="slot-t-node" slot-scope="{ node, data }" @dblclick="editNode(data)">
- <span v-show="!data.isEdit">
- <span :class="[data.id >= 99 ? 'slot-t-node--label' : '']">
- <i v-if="data.type == 'catalog'" class="el-icon-folder" />
- <i v-if="data.type == 'menu'" class="el-icon-tickets" />
- <i v-if="data.type == 'submenu'" class="el-icon-document" />
- <span> {{ node.label }}</span>
- </span>
- </span>
- <span v-show="data.isEdit">
- <el-input class="slot-t-input" size="mini" autofocus v-model="data.label" :ref="'slotTreeInput' + data.id"
- @blur.stop="NodeBlur(node, data)" @keydown.native.enter="NodeBlur(node, data)"></el-input>
- </span>
- </span>
- </el-tree>
- <!-- <el-card class="box-card" ref="card" v-show="menuVisible">
- <div @click="addSameLevelNode()" v-show="firstLevel">
- <i class="el-icon-circle-plus-outline"></i> 同级增加
- </div>
- <div class="add" @click="addChildNode()">
- <i class="el-icon-circle-plus-outline"></i> 子级增加
- </div>
- <div class="delete" @click="deleteNode()">
- <i class="el-icon-remove-outline"></i> 删除节点
- </div>
- <div class="edit" @click="editNode()">
- <i class="el-icon-edit"></i> 修改节点
- </div>
- </el-card> -->
- <div class="box-menu" v-show="menuVisible" :style="{ left: menu_left + 'px', top: menu_top + 'px' }">
- <div @click="addSameLevelNode(0)" v-show="firstLevel">
- <i class="el-icon-circle-plus-outline"></i> 同级增加
- </div>
- <div class="add" @click="addChildNode()">
- <i class="el-icon-circle-plus-outline"></i> 子级增加
- </div>
- <div class="delete" @click="deleteNode()">
- <i class="el-icon-remove-outline"></i> 删除节点
- </div>
- <div class="edit" @click="editNode()">
- <i class="el-icon-edit"></i> 修改节点
- </div>
- </div>
- </div>
- </template>
-
- <script>
- export default {
- name: 'tree',
- data() {
- return {
- eleId: '',
- isShow: false,
- currentData: '',
- currentNode: '',
- menuVisible: false,
- firstLevel: false,
- filterText: '',
- maxexpandId: 4,
- menu_left: 0,
- menu_top: 0,
- treeData: [{
- id: 1,
- label: '一级 1',
- isEdit: false,
- type: 'catalog',
- children: [{
- id: 4,
- label: '二级 1-1',
- isEdit: false,
- type: 'menu',
- children: [{
- id: 9,
- label: '三级 1-1-1',
- isEdit: false,
- type: 'submenu',
- }, {
- id: 10,
- label: '三级 1-1-2',
- isEdit: false,
- type: 'submenu',
- }]
- }]
- }, {
- id: 2,
- label: '一级 2',
- isEdit: false,
- type: 'catalog',
- children: [{
- id: 5,
- label: '二级 2-1',
- isEdit: false,
- type: 'menu',
- }, {
- id: 6,
- label: '二级 2-2',
- isEdit: false,
- type: 'menu',
- }]
- }, {
- id: 3,
- label: '一级 3',
- isEdit: false,
- type: 'catalog',
- children: [{
- id: 7,
- label: '二级 3-1',
- isEdit: false,
- type: 'menu',
- }, {
- id: 8,
- label: '二级 3-2',
- isEdit: false,
- type: 'menu',
- children: [{
- id: 11,
- label: '三级 3-2-1',
- isEdit: false,
- type: 'submenu',
- }, {
- id: 12,
- label: '三级 3-2-2',
- isEdit: false,
- type: 'submenu',
- }, {
- id: 13,
- label: '三级 3-2-3',
- isEdit: false,
- type: 'submenu',
- }]
- }]
- }],
- defaultProps: {
- children: 'children',
- label: 'label'
- }
- }
- },
- methods: {
- NodeBlur(Node, data) {
- console.log(Node, data)
- if (data.label.length === 0) {
- this.$message.error('菜单名不可为空!')
- return false
- } else {
- if (data.isEdit) {
- this.$set(data, 'isEdit', false)
- console.log(data.isEdit)
- }
- this.$nextTick(() => {
- this.$refs['slotTreeInput' + data.id].$refs.input.focus()
- })
- }
- },
- // 查询
- filterNode(value, data) {
- if (!value) return true
- return data.label.indexOf(value) !== -1
- },
-
- allowDrop(draggingNode, dropNode, type) {
- if (dropNode.data.label === '二级 3-1') {
- return type !== 'inner'
- } else {
- return true
- }
- },
- allowDrag(draggingNode) {
- return draggingNode.data.label.indexOf('三级 3-2-2') === -1
- },
- // 鼠标右击事件
- rightClick(event, object, Node, element) {
- console.log(event, object)
- this.currentData = object
- this.currentNode = Node
- if (Node.level === 1) {
- this.firstLevel = true
- } else {
- this.firstLevel = false
- }
- this.menuVisible = true
- document.addEventListener('click', this.foo)
- // 将菜单显示在鼠标点击旁边定位
- this.menu_left = event.clientX -140;
- this.menu_top = event.clientY - 40;
-
- },
- // 鼠标左击事件
- handleLeftclick(data, node) {
- this.foo()
- },
- // 取消鼠标监听事件 菜单栏
- foo() {
- this.menuVisible = false
- // 要及时关掉监听,不关掉的是一个坑,不信你试试,虽然前台显示的时候没有啥毛病,加一个alert你就知道了
- document.removeEventListener('click', this.foo)
- },
- // 增加同级节点事件
- addSameLevelNode() {
- let id = Math.ceil(Math.random() * 100)
- var data = { id: id, label: '新增节点' }
- this.$refs.tree.append(data, this.currentNode.parent)
- },
- // 增加子级节点事件
- addChildNode() {
- console.log(this.currentData)
- console.log(this.currentNode)
- if (this.currentNode.level >= 3) {
- this.$message.error('最多只支持三级!')
- return false
- }
- let id = Math.ceil(Math.random() * 100)
- var data = { id: id, label: '新增节点' }
- this.$refs.tree.append(data, this.currentNode)
- },
- // 删除节点
- deleteNode() {
- this.$refs.tree.remove(this.currentNode)
- },
- // 编辑节点
- editNode(data) {
- console.log(data)
- this.currentData = data ? data : this.currentData
- if (!this.currentData.isEdit) {
- this.$set(this.currentData, 'isEdit', true)
- }
- // 获取焦点
- this.$nextTick(() => {
- this.$refs['slotTreeInput' + this.currentData.id].focus()
- })
- },
- handleDragStart(node, ev) {
- console.log('drag start', node)
- },
- handleDragEnter(draggingNode, dropNode, ev) {
- console.log('tree drag enter: ', dropNode.label)
- },
- handleDragLeave(draggingNode, dropNode, ev) {
- console.log('tree drag leave: ', dropNode.label)
- },
- handleDragOver(draggingNode, dropNode, ev) {
- console.log('tree drag over: ', dropNode.label)
- },
- handleDragEnd(draggingNode, dropNode, dropType, ev) {
- console.log('tree drag end: ', dropNode && dropNode.label, dropType)
- },
- handleDrop(draggingNode, dropNode, dropType, ev) {
- console.log('tree drop: ', dropNode.label, dropType)
- },
- },
- watch: {
- filterText(val) {
- this.$refs.tree.filter(val)
- }
- },
- mounted() {
- }
- }
- </script>
- <style scoped lang="less">
- .el-tree>.is-leaf {
- color: transparent;
- }
-
- .tree-container /deep/ .el-tree-node__expand-icon.expanded {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
-
- .tree-container /deep/ .el-tree-node__expand-icon.expanded {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
-
-
- .tree-container /deep/ .el-icon-caret-right:before {
- background: url("../../assets/node-collapse.png") no-repeat;
- content: '';
- display: block;
- width: 12px;
- height: 12px;
- font-size: 12px;
- background-size: 10px;
- }
-
- /*
- //有子节点 且已展开*/
- .tree-container /deep/ .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
- background: url("../../assets/node-expand.png") no-repeat;
- content: '';
- display: block;
- width: 12px;
- height: 12px;
- font-size: 12px;
- background-size: 10px;
- }
-
- /* //没有子节点*/
- .tree-container /deep/ .el-tree-node__expand-icon.is-leaf::before {
- background: transparent no-repeat 0 3px;
- content: '';
- display: block;
- width: 12px;
- height: 12px;
- font-size: 12px;
- background-size: 10px;
- }
-
- /* 点击节点时的选中颜色 */
- .tree-container /deep/.el-tree-node.is-current>.el-tree-node__content {
- color: #3D5ECC !important;
- }
-
- .tree-container /deep/ .el-tree-node__expand-icon {
- margin-left: 15px;
- }
-
- .tree-container /deep/ .el-tree-node__expand-icon.is-leaf {
- margin-left: 0px;
- }
-
- .tree-container /deep/ .el-tree-node {
- position: relative;
- padding-left: 16px;
- }
-
- .tree-container /deep/ .el-tree-node__children {
- padding-left: 16px;
- }
-
- .tree-container /deep/ .el-tree>.el-tree-node:before {
- border-left: none;
- }
-
- .tree-container /deep/ .el-tree>.el-tree-node:after {
- border-top: none;
- }
-
- .tree-container /deep/ .el-tree>.el-tree-node:before {
- border-left: none;
- }
-
- .tree-container /deep/ .el-tree>.el-tree-node:after {
- border-top: none;
- }
-
- .tree-container /deep/ .el-tree-node:before {
- content: "";
- left: 10px;
- position: absolute;
- right: auto;
- border-width: 1px;
- }
-
- .tree-container /deep/ .el-tree-node:after {
- content: "";
- left: 10px;
- position: absolute;
- right: auto;
- border-width: 1px;
- }
-
- .tree-container /deep/ .el-tree-node:before {
- border-left: 1px dashed #ccc;
- bottom: 0px;
- height: 100%;
- top: -19px;
- width: 1px;
- }
-
- .tree-container /deep/ .el-tree-node:after {
- border-top: 1px dashed #ccc;
- height: 25px;
- top: 20px;
- width: 20px;
- }
-
- .el-tree-node :last-child:before {
- height: 40px;
- }
-
- .tree-container {
- margin: 10px;
- }
-
- .tree-container /deep/ .el-tree .el-tree-node {
- position: relative;
- }
-
- .tree-container /deep/ .el-tree-node .el-tree-node__content {
- height: 34px;
- padding-left: 0px !important;
- border: none;
- }
-
- .tree-container /deep/ .el-tree-node .el-tree-node__content::before {
- border-left: 1px dashed #ccc;
- height: 100%;
- top: 0;
- width: 1px;
- margin-left: 1px;
- margin-top: 0px;
- z-index: 8;
- }
-
- .tree-container /deep/ .el-tree-node .el-tree-node__children .el-tree-node__content::before {
- border-left: 0px dashed #ccc;
- height: 100%;
- top: 0;
- width: 1px;
- margin-left: 1px;
- margin-top: 0px;
- z-index: 8;
- }
-
- .tree-container /deep/ .el-tree-node .el-tree-node__content::after {
- border-top: 1px dashed #ccc;
- height: 1px;
- top: 18px;
- width: 13px;
- margin-left: 1px;
- z-index: 8;
- }
-
- .tree-container /deep/ .el-tree-node .el-tree-node__children .el-tree-node__content::after {
- border-top: 0px dashed #ccc;
- }
-
- .tree-container .el-tree-node .el-tree-node__content::before,
- .tree-container .el-tree-node .el-tree-node__content::after {
- content: "";
- position: absolute;
- right: auto;
- }
-
- .el-tree {
- width: 20%;
- margin-top: 10px;
- }
-
- .search {
- width: 20%;
- }
-
- .item {
- padding: 18px 0;
- }
-
- .search {
- cursor: pointer;
- }
-
- .box-menu {
- width: 150px;
- position: absolute;
- z-index: 1000;
- background-color: #fff;
- box-shadow: 0px 0px 10px #ccc, 0px 0px 20px #ccc, 0px 0px 30px #ccc;
- padding: 10px;
-
- div {
- cursor: pointer;
- line-height: 30px;
- }
-
- div:active {
- color: blue;
- }
- }
- </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。