Avue.js创建表格树菜单(vue组件通信---子传父(自定义事件$emit(eventName,data)))

关注Avue表单设计器的使用: 【Avue表单设计器的使用技巧】

关注Avue企业级开发应用官方源代码: 官方源代码

话说代码示例: 

   (1) 父菜单表格: 自定义

   

<!--父表格菜单模板 -->
<template>
  <basic-container>
    <div class="avue-crud"> <!-- 申明样式为avue-crud-->
      <el-form :inline="true"> <!-- el-form表单标签-->
        <el-form-item> <!-- 定义表格的每一项表单项: -->
          <el-button v-if="permissions.sys_menu_add" icon="el-icon-plus" type="primary"
                     @click="addOrUpdateHandle(false)">
            添加
          </el-button>  <!-- 表单项 按钮-->
        </el-form-item>
      </el-form> <!-- 表单元素结束-->

      <el-table <!--定义avue-crud中的表格元素:该表格元素为树状表格 -->
        border
        v-loading="loading"
        :data="menuList"  // data属性
        row-key="id"
        :tree-props="{children: 'children', hasChildren: 'hasChildrens'}"> // tree-props配置属性,children与hasChildrens
        <el-table-column prop="name" label="菜单名称" :show-overflow-tooltip="true" width="180"></el-table-column> // 定义表格的列
        <el-table-column prop="icon" label="图标" align="center" width="100">
          <template slot-scope="scope">
            <i :class="scope.row.icon"/>
          </template>
        </el-table-column>
        <el-table-column prop="sort" label="排序" width="60"></el-table-column>
        <el-table-column prop="path" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
        <el-table-column prop="type" label="类型" width="80" align="center">
          <template slot-scope="scope">
            <el-tag type="success" v-if="scope.row.type === '0'">菜单</el-tag>
            <el-tag type="info" v-if="scope.row.type === '1'">按钮</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="keepAlive" label="缓冲" width="80" align="center">
          <template slot-scope="scope">
            <el-tag type="info" v-if="scope.row.keepAlive === '0'">关闭</el-tag>
            <el-tag type="success" v-if="scope.row.keepAlive === '1'">开启</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="permission" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
        <!-- 定义表格的操作列 -->
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> 
          <template slot-scope="scope">
            <el-button
              type="text"
              icon="el-icon-plus"
              @click="addOrUpdateHandle(false,scope.row.id)"
              v-if="permissions.sys_menu_add">添加
            </el-button>
            <el-button type="text"
                       icon="el-icon-edit"
                       @click="addOrUpdateHandle(true,scope.row.id)"
                       v-if="permissions.sys_menu_edit">修改
            </el-button>
            <el-button type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
              v-if="permissions.sys_menu_del">删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 添加与修改的弹窗表格组件,addOrUpdateVisible该值控制该表格组件的显
 隐,refreshDataList刷新数据列表方法时,执行getList 方法-->
      <table-form v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getList"></table-form>
    </div>
  </basic-container>
</template>

<script>
  import {delObj, fetchMenuTree} from '@/api/admin/menu' // 需要的数据API接口
  import TableForm from './menu-form'  // 子组件,(添加与修改)弹窗
  import {mapGetters} from 'vuex' 

  export default { // export导出语法
    name: "Menu",
    components: {TableForm}, // 申明子组件
    data() { // 组件需要的各数据配置项
      return {
        addOrUpdateVisible: false,
        // 遮罩层
        loading: true,
        // 菜单表格树数据
        menuList: [], 
        // 菜单树选项
        menuOptions: [],
      };
    },
    created() {
      this.getList();  // vue实例化时,执行getList()方法,初始化相关数据
    },
    computed: {
      ...mapGetters(['permissions']), 
    },
    methods: {
      addOrUpdateHandle(isEdit, id) { // 打开添加或者修改弹窗时,执行该方法
        this.addOrUpdateVisible = true // 设置子组件显示
        this.$nextTick(() => { // andOrUpdate为子组件的索引名称,父组件通过this.$refs调用组/件addOrUpdate的方法init(isEdit,id)
          this.$refs.addOrUpdate.init(isEdit, id) // 父组件调用子组件的方法,初始化子组件相关数据
        })
      },
      getList() { // 初始化父组件相关数据
        this.loading = true;
        fetchMenuTree(false, -1, this.$store.state.user.userInfo.tenantId).then(response => {
          this.menuList = response.data.data
          this.loading = false;
        });
      },
     // 执行删除的处理逻辑
      handleDelete(row) {
        this.$confirm('是否确认删除名称为"' + row.name + '"的数据项?', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(function () {
          return delObj(row.id);
        }).then(() => {
          this.getList();
          this.$message.success('删除成功')
        }).catch(()=>{})  // catch(()=>{})  为避免点击取消按钮时,confirm报错
      }
    }
  };
</script>

(2)子弹窗: 添加与修改弹窗

<style>
       .customWidth{  <!-- 自定义弹窗的宽度 -->
        width:30%;
    }
</style>
<template>
  <!-- 添加或修改菜单对话框 el-dialog模板类型 -->
  <el-dialog :title="!form.menuId ? '新增' : '修改'"
             :visible.sync="visible" customClass="customWidth">
    <el-form ref="dataForm" :model="form" :rules="rules" label-width="80px"><!--表单的元素-->
      <el-row> <!-- el-row行元素,自成行-->
        <el-col :span="12"> <!-- 行中列  el-col-->
          <el-form-item label="菜单类型" prop="type"> <!-- 列中包含的表单项 -->
            <el-radio-group v-model="form.type" size="small">
              <el-radio-button label="0">菜单</el-radio-button>
              <el-radio-button label="1">按钮</el-radio-button>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="上级菜单">
            <treeselect v-model="form.parentId"
                        :options="menuOptions"
                        :normalizer="normalizer"
                        :show-count="true"
                        placeholder="选择上级菜单"
            />
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item label="图标" prop="icon" v-if="form.type === '0'">
        <avue-icon-select v-model="form.icon" :icon-list="iconList"></avue-icon-select>
      </el-form-item>
      <el-form-item label="名称" prop="name">
        <el-input v-model="form.name" placeholder="请输入菜单名称"/>
      </el-form-item>
      <el-form-item label="路由地址" prop="path" v-if="form.type !== '1'">
        <el-input v-model="form.path" placeholder="请输入路由地址"/>
      </el-form-item>
      <el-form-item label="权限标识" prop="permission" v-if="form.type === '1'">
        <el-input v-model="form.permission" placeholder="请权限标识" maxlength="50"/>
      </el-form-item>
     <!-- el-row 行元素-->
      <el-row>
        <el-col :span="12">
          <el-form-item label="排序" prop="sort">
            <el-input-number v-model="form.sort" controls-position="right" :min="0"/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="路由缓冲" prop="keepAlive" v-if="form.type !== '1'">
            <el-radio-group v-model="form.keepAlive">
              <el-radio-button label="0">否</el-radio-button>
              <el-radio-button label="1">是</el-radio-button>
            </el-radio-group>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
<!-- 弹窗底部插槽footer-->
    <div slot="footer" class="dialog-footer">
      <el-button type="primary" @click="dataFormSubmit">确 定</el-button>
      <el-button @click="visible = false">取 消</el-button>
    </div>
  </el-dialog>
</template>

<script>
  import {addObj, fetchMenuTree, getObj, putObj} from '@/api/admin/menu' // 引入相关接口API
  import Treeselect from "@riophae/vue-treeselect"
  import iconList from '@/const/iconList'
  import TableForm from './'
  import "@riophae/vue-treeselect/dist/vue-treeselect.css"

  export default {
    name: "Menu",
    components: {Treeselect, TableForm}, // 引入两个组件
    data() {
      return {
        // 遮罩层
        loading: true,
        // 菜单树选项
        menuOptions: [],
        // 是否显示弹出层
        visible: false,
        // 图标
        iconList: iconList,
        form: { // 表单绑定的字段属性
          name: undefined,
          path: undefined,
          icon: undefined,
          permission: undefined,
          type: '0',
          keepAlive: '0',
          sort: 999,
          tenantId:this.$store.state.user.userInfo.tenantId
        },
        // 表单校验
        rules: {
          name: [
            {required: true, message: "菜单名称不能为空", trigger: "blur"}
          ],
          sort: [
            {required: true, message: "菜单顺序不能为空", trigger: "blur"}
          ],
          path: [
            {required: true, message: "路由地址不能为空", trigger: "blur"}
          ],
          keepAlive: [
            {required: true, message: "路由缓冲不能为空", trigger: "blur"}
          ],
          permission: [
            {required: true, message: "权限标识不能为空", trigger: "blur"}
          ]
        }
      };
    },
    methods: {
      init(isEdit, id) {
        if (id != null) {
          this.form.parentId = id;
        }
        this.visible = true
        this.getTreeselect();
        this.$nextTick(() => { // 使用this.nextTick()方法作用,等待dom加载以后再来获取dom对象
          this.$refs['dataForm'].resetFields()
          if (isEdit) {
            getObj(id).then(response => {
              this.form = response.data.data
            })
          }
        })
      },
      // 表单提交
      dataFormSubmit() {
        this.$refs['dataForm'].validate((valid) => {
          if (valid) {
            if (this.form.parentId === undefined) {
              this.form.parentId = -1
            }

            if (this.form.menuId) {
              putObj(this.form).then(data => {
                this.$message.success('修改成功')
                this.visible = false
								this.form.menuId = ""
                this.$emit('refreshDataList')
              });
            } else {
              addObj(this.form).then(data => {
                this.$message.success('添加成功')
                this.visible = false
                this.$emit('refreshDataList')  // 子组件调用父组件刷新表格数据
              })
            }
          }
        })
      },
      /** 查询菜单下拉树结构 */
      getTreeselect() {
        fetchMenuTree(false,-1,this.$store.state.user.userInfo.tenantId).then(response => {
          this.menuOptions = [];
          const menu = {id: -1, name: '根菜单', children: []};  //定义常量
          menu.children = response.data.data;  // 为常量的children原始赋值
          this.menuOptions.push(menu);
        });
      },
      /** 转换菜单数据结构 */
      normalizer(node) {
        if (node.children && !node.children.length) {
          delete node.children;
        }
        return {
          id: node.id,
          label: node.name,
          children: node.children
        };
      }
    }
  };
</script>

效果如下:  

   

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值