js树形组件Tree
1. 使用方式
-
配置信息
// 容器位置 pNode: 'body' // 每一个title的padding titlePadding: 18 // 数据源 /* [ { label: '', children:[ { label: '', children: [] } } ] */ data: [] // 格式化显示的字符串 labelFormat: item => item.label // 点击时触发 /** * 点击时触发 * @param item 当前点击的项 * @param path 路劲的数组 * @param e 当前点击事件 */ onClick: (item, path, e) => {}
-
使用实例
<template> <div class="home"> </div> </template> <script> // @ is an alias to /src const { Tree, Message } = require('@/assets/js/util') export default { name: 'Home', data () { return { tree: [ { id: '1', label: '这些年', children: [ { id: '1-1', label: '一个人' } ] }, { id: '2', label: '一个人', children: [ { id: '2-1', label: '风也走', children: [ { id: '2-1-1', label: '有过泪', children: [ { id: '2-1-1-1', label: '还记得坚持什么' }, { id: '2-1-1-2', label: '什么也记不得了' } ] } ] }, { id: '2-2', label: '雨也过', children: [ { id: '2-2-1', label: '真爱过' } ] }, { id: '2-3', label: '才会懂' } ] }, { id: '3', label: '有过痛' } ] } }, mounted () { // eslint-disable-next-line no-new new Tree({ data: this.tree, pNode: '.home', onClick (item, path, e) { if (!item.children) { console.log(path, e) Message.info(`您已选择:【${item.label}】`) } } }) }, methods: {} } </script>
-
演示效果
2. js代码
/*
树形控件
*/
const {
getDom,
createDom,
cssFromObj
} = require('./Common')
class Tree {
constructor (config) {
this.config = {
pNode: 'body',
// 每一个title的padding
titlePadding: 18,
data: [],
// 格式化显示的字符串
labelFormat: item => item.label,
// 点击时触发
/**
* 点击时触发
* @param item 当前点击的项
* @param path 路劲的数组
* @param e 当前点击事件
*/
onClick: (item, path, e) => {}
}
this.init(config)
this.render()
}
init (config) {
Object.assign(this.config, config)
this.parent = getDom(this.config.pNode)
if (!this.parent) {
throw new Error('The progress component needs a parent node, you can define by setting the "pNode" property')
}
this.treeContainer = createDom('hxl-tree-box')
}
generateTree (data, num = 0, path = []) {
const treeList = createDom('hxl-tree-list')
data.forEach(li => {
const treeItem = createDom('hxl-tree-item')
const treeItemTitle = createDom('hxl-tree-title')
treeItemTitle.style = cssFromObj({
paddingLeft: `${this.config.titlePadding * num}px`
})
treeItemTitle.innerText = this.config.labelFormat(li)
treeItem.appendChild(treeItemTitle)
treeItemTitle.onclick = (e) => {
if (e.target.classList.contains('sub-title')) {
if (e.target.classList.contains('active')) {
e.target.classList.remove('active')
e.target.nextSibling.style.display = 'none'
} else {
e.target.classList.add('active')
e.target.nextSibling.style.display = 'block'
}
}
this.config.onClick(li, [...path, li], e)
}
if (li.children) {
treeItem.classList.add('has-sub')
treeItemTitle.classList.add('sub-title')
// 创建子tree
const subTree = createDom('hxl-tree-sub-item')
subTree.appendChild(this.generateTree(li.children, num + 1, [...path, li]))
treeItem.appendChild(subTree)
}
treeList.appendChild(treeItem)
})
return treeList
}
render () {
this.treeList = this.generateTree(this.config.data)
this.treeContainer.appendChild(this.treeList)
this.parent.appendChild(this.treeContainer)
}
set data (data) {
if (Array.isArray(data)) {
this.config.data = data
} else {
throw new Error('data property must be an Array')
}
}
get data () {
return this.config.data
}
}
module.exports = {
Tree
}
css样式
.hxl-tree-box {
width: 100%;
padding-left: 10px;
}
.hxl-tree-item {
cursor: pointer;
&.has-sub {
.hxl-tree-title {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
display: flex;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
align-items: center;
&.sub-title.active {
&:before {
transform: rotate(90deg);
}
}
}
&>.hxl-tree-title.sub-title:before {
content: '';
width: 0;
height: 0;
display: inline-block;
justify-content: center;
margin-right: 5px;
border-left: 6px solid #afafaf;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
}
}
.hxl-tree-title {
&:hover {
background: #f5f7fa;
}
}
.hxl-tree-sub-item {
display: none;
transition: all 2s;
}
}
这么简单好用,还不快快用起来吗,实际使用中可根据自己的需要进行修改,有任何疑问也可以一起讨论,当然若是您有其他不同的见解与优化,也希望能够提出来,大家多多交流,互相促进~~