vue 树形下拉框 多选 封装组件及应用

时间:2024-11-24 07:02:34
  • <!--
  • /**
  • * 下拉选择树形组件,下拉框展示树形结构,提供选择某节点功能,方便其他模块调用
  • * @author lgh
  • * @date 2020-09-01
  • * 调用示例:
  • * <tree-select :height="400" // 下拉框中树形高度
  • * :width="200" // 下拉框中树形宽度
  • * :data="data" // 树结构的数据
  • * :defaultProps="defaultProps" // 树结构的props
  • * multiple // 多选
  • * :rootNodeChick="true" // 是否可以选择根节点。默认 false ture 为可选。false 为不可选
  • * checkStrictly // 多选时,严格遵循父子不互相关联
  • * :nodeKey="nodeKey" // 绑定nodeKey,默认绑定'id'
  • * :checkedKeys="defaultCheckedKeys" // 传递默认选中的节点key组成的数组
  • * @popoverHide="popoverHide"> // 事件有两个参数:第一个是所有选中的节点ID,第二个是所有选中的节点数据
  • * </tree-select>
  • *
  • * import TreeSelect from "@/utils/components/";
  • * components: { TreeSelect },
  • *
  • *数据格式
  • *let obj = {
  • menuId: ,
  • menuName: ,
  • childrenList: children
  • };
  • * 清空树的选中状态。只需要将clear 从 0 累加就可以。这里是监听的数据改变状态。不为 0 则清空数据。Number类型
  • */
  • -->
  • <template>
  • <div>
  • <div class="mask" v-show="isShowSelect" @click="isShowSelect = !isShowSelect"></div>
  • <el-popover
  • placement="bottom-start"
  • :width="width"
  • trigger="manual"
  • v-model="isShowSelect"
  • @hide="popoverHide"
  • clearable
  • >
  • <el-tree
  • class="common-tree"
  • :style="style"
  • clearable
  • ref="tree"
  • :data="data"
  • :props="defaultProps"
  • :show-checkbox="multiple"
  • :node-key="nodeKey"
  • :check-strictly="checkStrictly"
  • default-expand-all
  • :expand-on-click-node="false"
  • :default-checked-keys="defaultCheckedKeys"
  • :highlight-current="true"
  • @node-click="handleNodeClick"
  • @check-change="handleCheckChange"
  • ></el-tree>
  • <el-select
  • :style="selectStyle"
  • slot="reference"
  • ref="select"
  • v-model="selectedData"
  • :multiple="multiple"
  • clearable
  • @click.native="isShowSelect = !isShowSelect"
  • class="tree-select"
  • >
  • <el-option
  • v-for="item in options"
  • :key=""
  • :label=""
  • :value=""
  • ></el-option>
  • </el-select>
  • </el-popover>
  • </div>
  • </template>
  • <script>
  • export default {
  • name: "tree-select",
  • // props: ["clear"],
  • props: {
  • // 树结构数据
  • data: {
  • type: Array,
  • default() {
  • return [];
  • }
  • },
  • // 是否可选根节点
  • rootNodeChick: Boolean,
  • // 是否清空数据
  • clear: Number,
  • defaultProps: {
  • type: Object,
  • default() {
  • return {};
  • }
  • },
  • // 配置是否可多选
  • multiple: {
  • type: Boolean,
  • default() {
  • return false;
  • }
  • },
  • nodeKey: {
  • type: String,
  • default() {
  • return "id";
  • }
  • },
  • // 显示复选框情况下,是否严格遵循父子不互相关联
  • checkStrictly: {
  • type: Boolean,
  • default() {
  • return false;
  • }
  • },
  • // 默认选中的节点key数组
  • checkedKeys: {
  • type: Array,
  • default() {
  • return [];
  • }
  • },
  • width: {
  • type: Number,
  • default() {
  • return 250;
  • }
  • },
  • height: {
  • type: Number,
  • default() {
  • return 300;
  • }
  • }
  • },
  • data() {
  • return {
  • defaultCheckedKeys: [],
  • isShowSelect: false, // 是否显示树状选择器
  • options: [],
  • selectedData: [], // 选中的节点
  • style: "width:" + + "px;" + "height:" + + "px;",
  • selectStyle: "width:" + ( + 24) + "px;",
  • checkedIds: [],
  • checkedData: []
  • };
  • },
  • mounted() {
  • if (.length > 0) {
  • if () {
  • = ;
  • = (item => {
  • var node = this.$(item);
  • return ;
  • });
  • } else {
  • var item = [0];
  • this.$(item);
  • var node = this.$(item);
  • = ;
  • }
  • }
  • },
  • methods: {
  • popoverHide() {
  • if () {
  • = this.$(); // 所有被选中的节点的 key 所组成的数组数据
  • = this.$(); // 所有被选中的节点所组成的数组数据
  • } else {
  • = this.$();
  • = this.$();
  • }
  • this.$emit("popoverHide", , );
  • },
  • // 节点被点击时的回调,返回被点击的节点数据
  • handleNodeClick(data, node) {
  • if (!) {
  • let tmpMap = {};
  • tmpMap.value = node.key;
  • = ;
  • this.options = [];
  • this.options.push(tmpMap);
  • = ;
  • = !;
  • }
  • },
  • // 节点选中状态发生变化时的回调
  • handleCheckChange() {
  • var checkedKeys = this.$(); // 所有被选中的节点的 key 所组成的数组数据
  • this.options = [];
  • if (!)
  • (item => {
  • var node = this.$(item); // 所有被选中的节点对应的node
  • let tmpMap = {};
  • if (.length == 0) {
  • tmpMap.value = node.key;
  • = ;
  • this.options.push(tmpMap);
  • }
  • });
  • else
  • this.options = (item => {
  • var node = this.$(item); // 所有被选中的节点对应的node
  • let tmpMap = {};
  • tmpMap.value = node.key;
  • = ;
  • return tmpMap;
  • });
  • = this.options.map(item => {
  • return ;
  • });
  • }
  • },
  • watch: {
  • isShowSelect(val) {
  • // 隐藏select自带的下拉框
  • this.$refs.select.blur();
  • },
  • clear: function(n, o) {
  • //箭头函数 不然会发生this改变
  • if (n != 0) {
  • = [];
  • this.$nextTick(() => {
  • this.$([]);
  • });
  • }
  • },
  • selectedData: function(newData, oldData) {
  • ();
  • if (
  • newData == undefined ||
  • newData == null ||
  • newData == [] ||
  • newData.length == 0
  • )
  • this.$([]);
  • }
  • }
  • };
  • </script>
  • <style scoped>
  • .mask {
  • width: 100%;
  • height: 100%;
  • position: fixed;
  • top: 0;
  • left: 0;
  • opacity: 0;
  • }
  • .common-tree {
  • overflow: auto;
  • }
  • </style>
  • <style>
  • .tree-select .el-select__tags .el-tag .el-tag__close {
  • display: none;
  • }
  • .tree-select .el-select__tags .el-tag .el-icon-close {
  • display: none;
  • }
  • </style>