权限树组件封装

这篇博客介绍了如何使用Vue组件RoleTree来实现功能权限的选择和回显。在编辑模式下,通过调用RoleApi获取角色详情并加载权限列表,利用el-tree组件展示并设置勾选状态。在节点被点击时,通过checkTree方法更新选中值,并将结果回传。此组件适用于角色管理中的权限分配场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

调用


import RoleTree from './RoleTree'
<el-form-item label="功能权限" prop="funcId">
	<RoleTree :type="pageType" :row="rowObj" @callBack="funcChange" :key="key" />
</el-form-item>
funcChange(row) {
	this.ruleForm.funcId = row.toString()
	this.$refs.ruleForm.validateField("funcId")
},

代码


<template>
	<!-- 角色管理权限树组件 -->
	<div class="rowTree">
		<el-tree
			ref="treeEdit"
			style="margin-top: 10px"
			:data="data"
			show-checkbox
			:check-strictly="true"
			:destroy-on-close="true"
			node-key="id"
			:props="defaultProps"
			@check="editClickTree"
		>
			<!--  -->

			<!-- :default-expanded-keys="[2, 3]"
                :default-checked-keys="[5]" -->
		</el-tree>
	</div>
</template>
 
<script>
import RoleApi from '@/api/account/roleAccount' //API
export default {
	name: 'RoleTree',
	data() {
		return {
			id: '',
			data: [],
			mySoleId: '',

			selection: [],
			funcIdData: [],
			currentRow: {},
			queryParams: {
				page_number: 1,
				page_size: 10,
				name: ''
			},
			data: [],
			total: null,
			defaultProps: {
				children: 'funcs',
				label: 'name',
			},
			listLoading: false,
			pageType: '' //操作类型
		}
	},
	// inject: ['row', 'type'],
	mounted() {
		this.pageType = this.$parent.$parent.$parent.type
		this.id = this.$parent.$parent.$parent.row == {} ? '' : this.$parent.$parent.$parent.row.id
		if (this.pageType === 'edit') {
			this.loadData(this.id)
		} else {
			this.functionsList()
		}
	},
	methods: {
		// 获取详情
		loadData(id) {
			let _this = this
			RoleApi.detail({ id: id }).then((res) => {
				if (res.roleId == null && res.id == 3) {
					res.roleId = 3
				}
				if (res.roleId == null && res.id == 2) {
					res.roleId = 2
				}
				this.functionsList(res.roleId)
				this.currentRow.id = res.roleId
				this.funcIdData = res.idList
				this.mySoleId = res.id

				// 回显
				setTimeout(() => {
					res.idList.forEach((i, n) => {
						let node = _this.$refs.treeEdit.getNode(i)
						if (node) {
							_this.$refs.treeEdit.setChecked(node, true)
						}
					})
				}, 500)
			})
		},
		// 查询权限列表
		functionsList(id) {
			// const roleId = getUser().roleId; // 之前用登录时候返回的roleId请求权限列表(之前roleId也没取过来,等于没传),后来改成用选择的所属角色的id请求权限列表
			RoleApi.fun({ roleId: 1 }).then((response) => {
				const arr = response.list
				if (this.pageType === 'edit') {
					const arr = response.list.concat()
					for (let i = 0; i < arr.length; i++) {
						let children = arr[i].funcs
						if (children !== undefined && children !== null) {
							for (let j = 0; j < children.length; j++) {
								// children[j].disabled = true
								let twoChildren = children[j].funcs
								if (twoChildren !== undefined && twoChildren !== null) {
									for (let k = 0; k < twoChildren.length; k++) {
										// twoChildren[k].disabled = true
									}
								}
							}
						}
						// arr[i].disabled = true
					}
				}

				this.data = arr
			})
		},

		// el-tree点击事件获取值
		editClickTree(data, node) {
			this.funcIdData = this.checkTree(data, node, 'treeEdit')
			this.$emit('callBack', this.funcIdData) //回传选中值
		},
		checkTree(data, node, treeName) {
			const arr = []
			let allNodes = this.$refs[treeName].getNode(data)
			if (allNodes) {
				allNodes.parent &&
					this.setParentChecked(allNodes.parent, allNodes.checked, treeName)
			}
			let checkedNodes = this.$refs[treeName].getCheckedNodes()
			if (checkedNodes.length > 0) {
				for (let i = 0; i < checkedNodes.length; i++) {
					arr.push(checkedNodes[i].id)
				}
			}
			return arr
		},
		setParentChecked(parent, check, treeName) {
			if (!check) {
				return
			}
			this.$refs[treeName].setChecked(parent, check)
			if (parent && parent.parent) {
				this.setParentChecked(parent.parent, check, treeName)
			}
		}
	},
	created() {}
}
</script>
<style lang="scss" scoped>
.rowTree {
	height: auto;
	max-height: 200px;
	width: 100%;
	overflow: auto;
}
</style>
<think>好的,用户想了解组件封装,我需要先明确组件封装的定义和核心概念。首先,组件封装是软件开发中的一种设计思想,常见于前端框架如React、Vue,也适用于其他编程场景。我应该从基本概念入手,解释封装的目的和好处。 接下来,要拆解组件封装的三个主要特点:高内聚、低耦合、接口明确。高内聚指的是组件内部功能集中,独立完成特定任务;低耦合强调减少与其他组件的依赖;接口明确则涉及如何暴露必要的属性和事件。需要举例说明,比如按钮组件的属性和事件,这样用户更容易理解。 然后,要讨论封装的优势,比如可维护性、复用性、协作效率。这部分需要用实际例子支撑,比如修改封装好的组件不会影响其他地方,或者不同项目复用组件库。用户可能关心实际应用中的好处,所以这些点很重要。 应用场景部分,可以提到UI组件、业务模块、功能模块等,覆盖不同层次的使用情况。比如UI组件如日期选择器,业务组件如购物车,功能如路由守卫。这帮助用户了解封装在不同情况下的适用性。 注意事项方面,需要平衡封装粒度,避免过度封装或不足。另外,文档和类型定义的必要性,特别是团队协作时的重要性。可能用户在实际操作中会遇到这些问题,提前指出可以帮他们避免常见错误。 最后,对比面向对象编程的封装,说明组件封装更侧重UI和功能组合,而OOP是数据和行为。这有助于用户区分概念,理解组件封装的独特之处。 在整理结构时,确保每个部分有清晰的标题,用列表和例子让内容更易懂。同时,检查LaTeX格式是否正确,行内公式用$...$,独立公式用$$...$$,但当前内容可能不需要复杂公式,所以重点放在文字描述和举例上。确保使用中文,语言口语化,避免技术术语堆砌,让不同层次的读者都能理解。 可能用户是开发者,尤其是前端开发的新手,想了解如何组织和设计组件结构。他们可能面临组件复用和维护的问题,需要知道封装的最佳实践。因此,回答要实用,提供可操作的指导,比如如何设计接口,注意事项中的平衡粒度等。同时,用户可能希望了解封装带来的长期好处,如提升开发效率,降低维护成本,这些都需要明确传达。 总结时,要强调组件封装的重要性,并建议根据项目需求调整,鼓励实践。这样用户能有一个全面的认识,并知道如何应用在自己的项目中。检查是否有遗漏点,比如测试、版本控制等,但可能超出当前问题范围,保持聚焦在封装本身即可。</think>### 组件封装介绍 #### 1. **定义与核心思想** **组件封装**是软件开发中的一种设计模式,通过将功能、数据和UI逻辑组合成独立的可复用单元,隐藏内部实现细节,仅暴露必要的接口。其核心思想是: - **高内聚**:组件内部紧密关联,专注于单一职责 - **低耦合**:减少对其他组件的依赖 - **接口明确**:通过属性(props)、事件(events)等方式定义交互规则 --- #### 2. **核心特点** | 特点 | 说明 | 示例 | |-------------|-----------------------------------|-----------------------------| | **隔离性** | 内部状态/样式不影响外部 | 按钮组件的`disabled`状态仅内部管理 | | **复用性** | 通过参数配置适应不同场景 | 表格组件通过`columns`定义列 | | **可维护性**| 修改内部实现无需影响调用方 | 优化日期选择器算法不需修改使用它的页面 | --- #### 3. **实现方式** - **属性传递** ```jsx <Modal visible={isOpen} onClose={() => setOpen(false)} title="提示" /> ``` - **插槽机制**(Vue的`<slot>`/React的`children`) - **事件通信** ```javascript // 子组件触发 this.$emit('submit', formData) // 父组件监听 <Form @submit="handleSubmit"/> ``` --- #### 4. **优势分析** - **开发效率**:复用现有组件减少重复编码 - **错误隔离**:组件边界天然形成错误屏障 - **协作优化**:不同开发者可并行开发不同组件 - **测试友好**:独立单元更易编写测试用例 --- #### 5. **典型应用场景** - **UI组件**:按钮/输入框/弹窗等基础元素 - **业务组件**:购物车/支付流程等业务模块 - **功能模块**:路由守卫/权限验证等逻辑封装 --- #### 6. **封装原则** 1. **单一职责原则**:每个组件只解决一个问题 2. **受控/非受控**:明确状态管理边界(如输入框的值是否由父组件控制) 3. **版本兼容**:修改组件时保持接口向后兼容 4. **文档配套**:提供类型定义(TypeScript)和使用示例 --- #### 7. **注意事项** - **避免过度封装**:简单元素(如纯展示文本)无需组件化 - **性能权衡**:组件层级过深可能影响渲染效率 - **命名规范**:采用`kebab-case`(Vue)或`PascalCase`(React) --- #### 8. **演进方向** - **微前端架构**:将组件升级为独立部署的微应用 - **跨平台封装**:通过抽象层实现iOS/Android/Web通用组件 - **可视化搭建**:封装为可拖拽配置的低代码模块 通过合理运用组件封装,可以有效提升代码质量(如降低圈复杂度$C = E - N + 2P$)和团队协作效率,是现代前端工程化的重要实践。实际开发中需根据项目规模权衡封装粒度,推荐结合[Storybook](https://storybook.js.org/)等工具进行组件驱动开发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值