vue 可搜索树组件封装

vue 数组件封装

组件代码:

<template>
	<div class="content">
		<div class="tree-item" v-for="(item, index) in data" :key="index">
			<div
				class="item"
				:class="{
					active: choice === item.id,
				}"
				:style="{ 'padding-left': padLeft + 'px' }"
			>
				<div class="icon-box" @click="expandChange(item)">
					<div v-if="item.children">
						<a-icon
							type="right"
							:class="'icon' + item.id"
							v-if="item.expand === false"
						/>
						<a-icon
							type="down"
							:class="'icon' + item.id"
							v-if="item.expand === true"
						/>
					</div>
				</div>
				<div class="title">
					<slot name="name" :data="item">
						{{ item.name }}
					</slot>
				</div>
			</div>
			
			// 递归调用自身
			<tree
				v-if="item.children && item.expand === true"
				:data="item.children"
				:pad-left="padLeft + 10"
				:select="choice"
				:search-value="selectValue"
				@choiceChange="onChoiceChange"
				@expandChild="expandChange"
			>
				<template slot="name" slot-scope="item">
					<slot name="name" :data="item.data" />
				</template>
			</tree>
		</div>
	</div>
</template>

<script>
import Tree from './Tree.vue';

export default {
	components: { Tree },
	name: 'Tree',
	props: ['data', 'padLeft', 'select', 'searchValue'],
	data() {
		return {
			choice: this.select,
			selectValue: this.searchValue,
		};
	},
	watch: {
		select: {
			handler(newVal, oldVal) {
				this.choice = Number(newVal);
				this.$emit('choiceChange', this.choice);
			},
		},
		searchValue: {
			handler(newVal, oldVal) {
				if (newVal !== '') {
					this.selectValue = newVal;
				}
			},
		},
	},
	methods: {
		/**
		 * 选中状态,需要回传给父组件,改变父组件选中状态
		 */
		onChoice(item) {
			this.choice = item.id;
			this.$emit('choiceChange', this.choice);
		},

		/**
		 * 由子组件触发改变父组件的选中状态
		 */
		onChoiceChange(e) {
			this.choice = e;
		},

		/**
		 * 展开子组件
		 */
		expandChange(item) {
			this.$emit('expandChild', item);
		},
	},

	created() {},
};
</script>

<style lang="less" scoped>
.content {
	width: 100%;

	.tree-item {
		width: 100%;
		margin-bottom: 5px;
		.item {
			width: 100%;
			height: 40px;
			line-height: 40px;
			border-radius: 4px;
			cursor: pointer;
			display: flex;
			padding: 0 5px;
			z-index: 1;

			.icon-box {
				width: 10px;
				height: 10x;
				cursor: pointer;
				margin-right: 5px;
				color: #c5c5c5;
				font-size: 12px;
				margin-left: 3px;
			}
		}
		.title {
			width: 100%;
			white-space: nowrap;
			text-overflow: ellipsis;
			overflow: hidden;

			.treenode {
				width: 100%;
				height: 100%;
			}
		}

		.active {
			background-color: rgba(59, 145, 255, 0.08);
		}
	}
}
</style>

应用:

// 搜索
  <div class="search">
				<a-input
					ref="searchInput"
					v-model="selectInput"
					placeholder="搜索"
					@change="select('department')"
					>
					<div slot="prefix">
							<a-icon :component="icons[0]" class="search-icon" />
					</div>
					</a-input>
	</div>
	
	 <tree
			class="tree"
			:data="userDepartment"
			:pad-left="padLeft"
			:select="treeChoice"
			:search-value="selectInput"
			@expandChild="expandChange"
			@choiceChange="onChoiceChange"
			v-if="auth('managementUserList')"
			v-show="!subMenu('managementUserList')"
			>
				<template slot="name" slot-scope="item">
					<router-link
						class="link treenode"
							:title="item.data.name"
							:key="item.data.id"
							tag="div"
							:to="{
									name: 'managementUserList',
									params: { id: item.data.id },
									}"
									>
										<div
											v-if="
												item.data.name.indexOf(selectInput) === -1 ||
												selectInput === ''
											"
											class="link-name"
											@click="treeNodeChoice(item.data)"
										>
											<span>{{ item.data.name }}</span>
										</div>
										<div
											v-if="
												item.data.name.indexOf(selectInput) !== -1 &&
												selectInput !== ''
											"
											class="link-name"
											@click="treeNodeChoice(item.data)"
										>
											<div>
												{{
													item.data.name.substr(
														0,
														item.data.name.indexOf(selectInput)
													)
												}}
											</div>
											<div style="color: #f50">{{ selectInput }}</div>
											<div>
												{{
													item.data.name.substr(
														item.data.name.indexOf(selectInput) +
															selectInput.length
													)
												}}
											</div>
										</div>
										
										// 操作
										<a-dropdown :trigger="['click']">
											<a-icon class="more-icon menu-icon" type="more" />
											<a-menu slot="overlay">
												<a-menu-item
													v-operation:MANAGEMENT_USER_ADD_DEPT
													@click="addDepart(item.data)"
													>添加</a-menu-item
												>
												<a-menu-item
													v-operation:MANAGEMENT_USER_UPDATE_DEPT
													@click="addDepart(item.data, 'update')"
													>编辑</a-menu-item
												>
												<a-menu-item
													v-operation:MANAGEMENT_USER_DELETE_DEPT
													@click="departRemove(item.data)"
													>删除</a-menu-item
												>
											</a-menu>
										</a-dropdown>
									</router-link>
								</template>
							</tree>

效果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大兵的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值