视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Vue.js递归组件实现组织架构树和选人功能
2020-11-27 21:54:09 责编:小采
文档


1. api构建部门和员工信息接口,vuex全局存放部门list和员工list数据信息。

api:

export default {
 getEmployeeList () {
 return {
 returncode: 0,
 message: '',
 result: [
 {
 id: 1,
 employeeName: '吴',
 departmentId: 44
 },
 {
 id: 2,
 employeeName: '鹿晗',
 departmentId: 45
 },
 {
 id: 3,
 employeeName: '孙红雷',
 departmentId: 44
 },
 {
 id: 4,
 employeeName: '周杰伦',
 departmentId: 45
 },
 {
 id: 5,
 employeeName: '张国荣',
 departmentId: 45
 },
 {
 id: 6,
 employeeName: '陈百强',
 departmentId: 45
 },
 {
 id: 7,
 employeeName: '谭咏麟',
 departmentId: 41
 },
 {
 id: 8,
 employeeName: '谷村新司',
 departmentId: 45
 },
 {
 id: 9,
 employeeName: '中岛美雪',
 departmentId: 46
 },
 {
 id: 10,
 employeeName: '周润发',
 departmentId: 47
 },
 {
 id: 14,
 employeeName: '周慧敏',
 departmentId: 58
 },
 {
 id: 13,
 employeeName: '张学友',
 departmentId: 58
 }
 ]
 }
 },
 getDepartmentList () {
 return {
 returncode: 0,
 message: '',
 result: [
 {
 id: 40,
 name: '研发一部',
 parentId: 37,
 sequence: 2
 },
 {
 id: 41,
 name: '研发二部',
 parentId: 37,
 sequence: 4
 },
 {
 id: 43,
 name: '市场',
 parentId: 0,
 sequence: 6
 },
 {
 id: 44,
 name: '销售',
 parentId: 0,
 sequence: 4
 },
 {
 id: 45,
 name: '财务',
 parentId: 0,
 sequence: 5
 },
 {
 id: 46,
 name: '研发三部',
 parentId: 37,
 sequence: 1
 },
 {
 id: 47,
 name: '研发四部',
 parentId: 37,
 sequence: 3
 },
 {
 id: 37,
 name: '研发',
 parentId: 0,
 sequence: 5
 },
 {
 id: 58,
 name: '研发一部',
 parentId: 57,
 sequence: 1
 },
 {
 id: 59,
 name: '测试',
 parentId: 0,
 sequence: 5
 },
 {
 id: 60,
 name: '测试一部',
 parentId: 59,
 sequence: 1
 },
 {
 id: 61,
 name: '测试二部',
 parentId: 59,
 sequence: 2
 },
 {
 id: 62,
 name: '研发二部',
 parentId: 57,
 sequence: 2
 }
 ]
 }
 }
}

store:

import dataApi from '@/api/data.api.js'
const state = {
 employeeList: [],
 departmentList: []
}

const getters = {
 employeeList: state => state.employeeList,
 departmentList: state => state.departmentList
}

const mutations = {
 SetEmployeeList (state, { employeeList }) {
 state.employeeList = employeeList
 },
 SetDepartmentList (state, { departmentList }) {
 state.departmentList = departmentList
 }
}

const actions = {
 getEmployeeList ({ commit }) {
 let employeeResult = dataApi.getEmployeeList()
 if (employeeResult.returncode === 0) {
 commit('SetEmployeeList', { employeeList: employeeResult.result })
 }
 },
 getDepartmentList ({ commit }) {
 let departmentResult = dataApi.getDepartmentList()
 if (departmentResult.returncode === 0) {
 commit('SetDepartmentList', { departmentList: departmentResult.result })
 }
 }
}

export default {
 state,
 getters,
 mutations,
 actions,
 namespaced: true
}

2. vue.$set为员工对象增加响应式属性checked控制是否选中,methods中创建选中方法如下:

selectEmployee () {
 var self = this
 if (self.employee.checked === undefined) {
 this.$set(self.employee, 'checked', true)
 } else {
 self.employee.checked = !self.employee.checked
 }
 }

3. computed计算属性监控文本框输入字段searchKey的变化实现左侧员工列表实时检索功能。

searchEmployeeList () {
 var self = this
 if (self.searchKey.trim() === '') {
 console.log(self.employeeList)
 return self.employeeList.filter(item => item.checked === undefined || !item.checked)
 } else {
 return self.employeeList.filter(item => (item.employeeName.indexOf(self.searchKey.trim()) !== -1) && (item.checked === undefined || !item.checked))
 }
 }

4. 构建组织结构树的部门组件,部门下可能存在子部门和员工,所以组件内部再调用部门组件和员工组件,以达到循环递归的效果。

<template>
 <li @click.stop="expandTree()">
 <a :class="lvl|level">
 <span class="expand-tree-icon">
 <i class="fa fa-caret-right" :class="{'active':department.expand}"></i>
 </span>
 <span>
 <i class="lcfont lc-department-o"></i>
 </span>
 <span class="title">
 <span>{{department.name}}</span>
 <span class="title-desc">({{allChildEmployeeList.length}}人 )</span>
 <i class="lcfont lc-add" @click.stop="selectDepartmentEmployees()" title="添加整个部门成员"></i>
 </span>
 </a>
 <ul v-show="department.expand">
 <child-employee
 v-for="(employee,index) in childEmployeeList"
 :employee="employee"
 :lvl="lvl+1"
 :key="index"
 ></child-employee>
 <child-department
 v-for="(department,index) in childDepartmentList"
 :department="department"
 :employeeList="employeeList"
 :departmentList="departmentList"
 :lvl="lvl+1"
 :key="index"
 ></child-department>
 </ul>
 </li>
</template>

5. 结构树之员工组件

<template>
 <li v-on:click.stop="selectEmployee()">
 <a class="member-item" v-bind:class="lvl|level" href="javascript:;" rel="external nofollow" >
 <div class="lc-avatar flex-se1" name="true" size="30">
 <div class="lc-avatar-30" :title="employee.employeeName">
 <span class="lc-avatar-def" style="background-color: rgb(112, 118, 142);">
 <div>{{employee.employeeName}}</div>
 </span>
 <div class="lc-avatar-name">{{employee.employeeName}}</div>
 </div>
 </div>
 <i class="lcfont" v-bind:class="{'lc-check':employee.checked}"></i>
 </a>
 </li>
</template>

6. 和上面员工的选中原理类似,控制部门节点的展开和合并也通过$set方法扩展一个响应式的expand属性。

expandTree () {
 var self = this
 if (self.department.expand === undefined) {
 self.$set(self.department, 'expand', true)
 } else {
 self.department.expand = !self.department.expand
 }
 }

下载本文
显示全文
专题