Vue移动端树形控件实现(递归组件)
写在前面因项目中需要用到树形控件,第三方的组件也不满足项目的使用需求,就自己造了一个车轮子,用Vue递归组件的方式实现,代码简单易懂,直接复制即可使用。效果图子组件代码<template><ul v-if="data.length"><li v-for="(item, i) in data" :key="i" @click.stop="sel...
·
写在前面
因项目中需要用到树形控件,第三方的组件也不满足项目的使用需求,就自己造了一个车轮子,用Vue递归组件的方式实现,代码简单易懂,直接复制即可使用。
效果图
子组件代码
<template>
<ul v-if="data.length">
<li v-for="(item, i) in data" :key="i" @click.stop="selectItem(item)" v-show="expandFlag">
<div class="item">
<!-- 展开的图标 -->
<i class='expandIcon'
@click.stop="expandItem(item, i)"
:class="[
expandArr.includes(i) ? 'reduce' : 'add',
item.children && item.children.length ? '' : 'disabled'
]">
</i>
<!-- 选项名 -->
<h1>{{item[labelKey]}}</h1>
<!-- 选择的图标 -->
<i class='selectIcon'
:class="[
value[valueKey] == item[valueKey] ? 'checked' : 'noChecked',
item[disabledKey] ? 'disabled' : ''
]">
</i>
</div>
<list-menu
v-if='item.children'
@input='input'
:data='item.children'
:valueKey='valueKey'
:labelKey='labelKey'
:disabledKey='disabledKey'
:value="value"
:toastText='toastText'
:expandFlag='expandArr.includes(i)'
/>
</li>
</ul>
</template>
<script>
export default {
// 组件名必写
name: 'ListMenu',
props: {
// 选中的值的属性名,必传
valueKey: String,
// 在页面要展示的选项属性名,必传
labelKey: String,
// 不可选的唯一标识,如item[disabledKey]未true则不可选择,非必传
disabledKey: String,
// 选中的值,必传
value: Object,
// 控制展开,不需要传
expandFlag: {
type: Boolean,
default: true
},
// 总数据,必传
data: Array,
// 不可选提示文字,非必传
toastText: String
},
data () {
return {
// 当前级组件已展开的项
expandArr: []
}
},
methods: {
// 子组件逐级传递选中项
input (item) {
this.$emit('input', item)
},
// 选择
selectItem (item) {
// industryDeptType为1表示时不可选择该工会
if (this.disabledKey && item[this.disabledKey]) {
if (this.toastText) {
alert(this.toastText)
}
return
}
this.$emit('input', item)
},
// 展开
expandItem (item, i) {
if (item.children && item.children.length) {
let index = this.expandArr.indexOf(i)
if (index > -1) {
this.expandArr.splice(index, 1)
} else {
this.expandArr.push(i)
}
}
}
}
}
</script>
<style lang="less" scoped>
ul{
width: 100%;
color: #2a2a2a;
font-size: 26/75rem;
overflow: hidden;
background: #fff;
border-bottom: .8px solid #e1e1e1;
li{
.item{
padding: 14/75rem 24/75rem;
display: flex;
align-items: center;
width: 100%;
.expandIcon{
height:34/75rem;
width:34/75rem;
border: 1.5px solid;
border-radius: 50%;
position:relative;
&:after{
position: absolute;
top: 50%;
left: 50%;
font-size: 34/75rem;
transform: translate(-50%, -50%);
}
&.add{
border-color: #2a2a2a;
&:after{
color: #2a2a2a;
content: '+';
}
}
&.reduce{
border-color: #ff6633;
&:after{
color: #ff6633;
content: '-';
}
}
&.disabled{
border-color: #ddd;
&:after{
color: #ddd;
}
}
}
.selectIcon{
height:34/75rem;
width:34/75rem;
border: 1.5px solid;
border-radius: 50%;
position:relative;
&:after{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
&.checked{
border-color: #ff6633;
background: #ff6633;;
&:after{
font-size: 24/75rem;
color: #fff;
content: '✓';
}
}
&.noChecked{
border-color: #ff6633;
}
&.disabled{
border-color: #ddd;
}
}
h1{
margin-right: 6/75rem;
padding: 0 16/75rem;
position: relative;
top: 2/75rem;
height: 60/75rem;
line-height: 60/75rem;
font-size:30/75rem;
flex: 1;
white-space: nowrap;
color: #2a2a2a;
// .one-line;
overflow-x: auto;
}
}
&:not(:first-child){
border-top: .8px solid #e1e1e1;
}
>ul{
border-bottom: 0;
padding-left: 60/75rem;
li{
.item{
padding-left: 12/75rem;
}
border-top: .8px solid #e1e1e1;
}
}
}
}
</style>
父组件调用代码
<template>
<div class="lists">
<list-menu
:data='lists'
v-model="selectVal"
value-key='treeId'
label-key='name'
disabled-key='disabled'
toastText='该选项不可选择'
/>
<article>
<p>选中的选项名:<span>{{selectVal.name || '未选择'}}</span></p>
<p>选中的选项值:<span>{{selectVal.treeId || '未选择'}}</span></p>
</article>
</div>
</template>
<script>
// 引入组件
import ListMenu from './ListMenu'
export default {
components: {
ListMenu
},
data () {
return {
selectVal: {},
lists: []
}
},
created () {
this.getTreeList()
},
methods: {
getTreeList () {
// 模拟数据
this.lists.push({
treeId: 1,
name: '第一级',
disabled: 0,
children: [{
treeId: 2,
name: '第二级(disadbed为true不可选)',
disabled: 1,
children: [
{
treeId: '3_1',
name: '第三级(1)',
disabled: 0
},
{
treeId: '3_2',
name: '第三级(2)',
disabled: 0,
children: [{
treeId: 4,
name: '第四级',
disabled: 0,
children: [{
treeId: 5,
name: '第五级',
disabled: 0,
children: [{
treeId: 6,
name: '第六级',
disabled: 0
}]
}]
}]
}
]
}]
})
}
}
}
</script>
<style lang="less" scoped>
.lists{
article{
margin: 30/75rem;
line-height: 1.5;
font-size: 30/75rem;
span{
color: #ff6633;
}
}
}
</style>
觉得有用就给我点个赞吧,蟹蟹,(●ˇ∀ˇ●)
更多推荐
已为社区贡献3条内容
所有评论(0)