Vue3+ElementPlus+Koa2 全栈开发后台系统=>用户管理增删改查,接口对接,关于getCurrentInstance的坑⑧

本文详细介绍了在Vue3中如何构建一个用户管理组件,包括用户查询表单、动态表格展示、数据筛选、新增用户、编辑用户和删除用户功能。使用了Element Plus库,利用reactive和ref创建响应式数据,并通过getCurrentInstance访问Vue实例。同时,文章还提到了在Vue3中处理分页、表格操作和接口调用的实现细节,以及在处理用户编辑时避免数据污染的方法。

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

本项目项目仓库地址:https://gitee.com/notlaughingzzm/vue3_elementPlus_admin.git

1.User.vue组件构建

在这里插入图片描述

<template>
  <div class="user-manage">
    <div class="query-form">
      <el-form ref="form" :inline="true" :model="user">
        <el-form-item label="用户ID" prop="userId">
          <el-input  placeholder="请输入用户ID" />
        </el-form-item>
        <el-form-item label="用户名称" prop="userName">
          <el-input  placeholder="请输入用户名称" />
        </el-form-item>
        <el-form-item label="状态" prop="state">
          <el-select >
            <el-option :value="0" label="所有"></el-option>
            <el-option :value="1" label="在职"></el-option>
            <el-option :value="2" label="离职"></el-option>
            <el-option :value="3" label="试用期"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery">查询</el-button>
          <el-button @click="handleReset('form')">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="base-table">
      <div class="action">
        <el-button type="primary" @click="handleCreate">新增</el-button>
        <el-button type="danger" @click="handlePatchDel">批量删除</el-button>
      </div>
      <el-table :data="userList" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" />
        <el-table-column
          v-for="item in columns"
          :key="item.prop"
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          :formatter="item.formatter"
        >
        </el-table-column>
        <el-table-column label="操作" width="150">
          <template #default="scope">
            <el-button @click="handleEdit(scope.row)" size="mini"
              >编辑</el-button
            >
            <el-button type="danger" size="mini" @click="handleDel(scope.row)"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>
    </div>
    
  </div>
</template>
<script>
/**
 * reactive和ref是vue3提供的创建响应式数据的方法,而vue2响应式数据是通过data()这个内置方法进行创建。
 * reactive和ref区别简要:
 * 1) reactive创建的对象和vue2中的data()基本可以等价
 * 2) ref创建的对象,需要通过<变量名>.value访问
 * 3) 鉴于上述的差别,reactive一般用于创建对象类型数据,ref一般用于创建基础类型数据
 *
 * vue3的setup方法中无法使用在main.js中挂载的全局属性,这是因为在setup中无法使用this关键字,this指向undefined
 * 如何访问到全局属性:使用getCurrentInstance方法获取当前Vue组件实例,解构出ctx,这个ctx就等同于vue2中的this
 */
import { getCurrentInstance, onMounted, reactive, ref, toRaw } from "vue";
import utils from "./../utils/utils";

export default {
  name: "user",
  setup(){
    //   获取Composition API 上下文对象
    const { ctx,proxy } = getCurrentInstance();
    // 初始化用户表单对象
    const user = reactive({
      state:1,
    });
    // 初始化用户列表数据
    const userList = ref([])
    // 初始化分页对象
    const pager = reactive({
      pageNum:1,
      pageSize:10
    })
    // 定义动态表格-格式
    const columns = reactive([ 
      {
        label: "用户ID",
        prop: "userId",
      },
      {
        label: "用户名",
        prop: "userName",
      },
      {
        label: "用户邮箱",
        prop: "userEmail",
      },
      {
        label: "用户角色",
        prop: "role",
        formatter(row, column, value) {
          return {
            0: "管理员",
            1: "普通用户",
          }[value];
        },
      },
      {
        label: "用户状态",
        prop: "state",
        formatter(row, column, value) {
          return {
            1: "在职",
            2: "离职",
            3: "试用期",
          }[value];
        },
      },
      {
        label: "注册时间",
        prop: "createTime",
        width: 180,
        formatter: (row, column, value) => {
          return utils.formateDate(new Date(value));
        },
      },
      {
        label: "最后登录时间",
        prop: "lastLoginTime",
        width: 180,
        formatter: (row, column, value) => {
          return utils.formateDate(new Date(value));
        },
      },
    ]);

    // 初始化接口调用 
    onMounted(()=>{
      getUserList()
    })
    // 获取用户列表
    const getUserList = async () =>{
      let params = { ...user, ...pager };
      const {list,page} = await proxy.$api.getUserList(params)
      userList.value = list
      pager.total = page.total
    }
    return {
      user,
      userList,
      columns,
      pager,
      getUserList
    }
  },

};
</script>

<style lang="scss">
</style>

2. 数据就有了

在这里插入图片描述

3.封装utils.js工具函数

/**
 * 工具函数封装
 */
export default {
    formateDate(date, rule) {
        let fmt = rule || 'yyyy-MM-dd hh:mm:ss'
        if (/(y+)/.test(fmt)) {
            fmt = fmt.replace(RegExp.$1, date.getFullYear())
        }
        const o = {
            // 'y+': date.getFullYear(),
            'M+': date.getMonth() + 1,
            'd+': date.getDate(),
            'h+': date.getHours(),
            'm+': date.getMinutes(),
            's+': date.getSeconds()
        }
        for (let k in o) {
            if (new RegExp(`(${k})`).test(fmt)) {
                const val = o[k] + '';
                fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? val : ('00' + val).substr(val.length));
            }
        }
        return fmt;
    }
}

4.Vue3中关于getCurrentInstance的大坑!

  • 因为没有vue2里面的this指向,vue3只能通过getCurrentInstance调用proxy实例
const { proxy } = getCurrentInstance()  
使用proxy线上也不会出现问题

5.删除/批量删除功能实现

1.对接api

    userDel(params){
        return request({
            url: '/users/delete',
            method: 'post',
            data: params,
            mock:true
        })
    }

2.逻辑处理

// 删除
    const handleDel = async (row) =>{
      await proxy.$api.userDel({
        userIds:[row.userId], // 可单个删除,也可批量删除
      })
      proxy.$message.success('删除成功');
      getUserList();
    };
    // 批量删除
    const handlePatchDel = async () =>{
      if (checkedUserIds.value.length == 0){
        proxy.$message.error('请选择要删除的用户');
        return;
      }
      const res =  await proxy.$api.userDel({
         userIds:checkedUserIds.value, // 可单个删除,也可以批量删除
      })
      if (res.nModified > 0 ){
        proxy.$message.success('删除成功');
        getUserList();
      }else {
         proxy.$message.success('删除失败');
      }
    };
    // 表格多选
    const handleSelectionChange = (list) =>{
      let arr = [];
      list.map(item => {
        arr.push(item.userId);
      })
      checkedUserIds.value = list
    };
return {
      user,
      userList,
      columns,
      pager,
      checkedUserIds,
      getUserList,
      handleQuery,
      handleReset,
      handleCurrentChange,
      handleDel,
      handlePatchDel,
      handleSelectionChange
    }

6.新增用户功能页面

<el-dialog title="用户新增" v-model="showModal">
      <el-form
        ref="dialogForm"
        :model="userForm"
        label-width="100px"
        :rules="rules"
      >
        <el-form-item label="用户名" prop="userName">
          <el-input
            v-model="userForm.userName"
            :disabled="action == 'edit'"
            placeholder="请输入用户名称"
          />
        </el-form-item>
        <el-form-item label="邮箱" prop="userEmail">
          <el-input
            v-model="userForm.userEmail"
            :disabled="action == 'edit'"
            placeholder="请输入用户邮箱"
          >
            <template #append>@imooc.com</template>
          </el-input>
        </el-form-item>
        <el-form-item label="手机号" prop="mobile">
          <el-input v-model="userForm.mobile" placeholder="请输入手机号" />
        </el-form-item>
        <el-form-item label="岗位" prop="job">
          <el-input v-model="userForm.job" placeholder="请输入岗位" />
        </el-form-item>
        <el-form-item label="状态" prop="state">
          <el-select v-model="userForm.state">
            <el-option :value="1" label="在职"></el-option>
            <el-option :value="2" label="离职"></el-option>
            <el-option :value="3" label="试用期"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="系统角色" prop="roleList">
          <el-select
            v-model="userForm.roleList"
            placeholder="请选择用户系统角色"
            multiple
            style="width: 100%"
          >
            <el-option
              v-for="role in roleList"
              :key="role._id"
              :label="role.roleName"
              :value="role._id"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="部门" prop="deptId">
          <el-cascader
            v-model="userForm.deptId"
            placeholder="请选择所属部门"
            :options="deptList"
            :props="{ checkStrictly: true, value: '_id', label: 'deptName' }"
            clearable
            style="width: 100%"
          ></el-cascader>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="handleClose">取 消</el-button>
          <el-button type="primary" @click="handleSubmit">确 定</el-button>
        </span>
      </template>
    </el-dialog>
 // 弹框显示对象
    const showModal = ref(false);
    // 新增用户Form对象
    const userForm = reactive({
      state: 3,
    });
    // 用户新增
    const handleCreate = () => {
      action.value = "add";
      showModal.value = true;
    };
return {
      showModal,
      userForm,
      handleCreate,

    };

7.新增-编辑用户功能实现

  • api
,
    getRoleList(){
        return request({
            url:'/roles/allList',
            method:'get',
            data:{},
            mock:true
        })
    },
    getDeptList(){
        return request({
            url:'/dept/list',
            method:'get',
            data:{},
            mock:true
        })
    },
    userSubmit(params){
        return request({
            url:'/users/operate',
            method:'post',
            data:params,
            mock:true
        })
    },
  • 组件
// 角色列表
    const roleList = ref([]);
    // 部门列表
    const deptList = ref([]);
    // 定义用户操作行为
    const action = ref("add");
    // 定义表单校验规则
    const rules = reactive({
      userName: [
        {
          required: true,
          message: "请输入用户名称",
          trigger: "blur",
        },
      ],
      userEmail: [
        { required: true, message: "请输入用户邮箱", trigger: "blur" },
      ],
      mobile: [
        {
          pattern: /1[3-9]\d{9}/,
          message: "请输入正确的手机号格式",
          trigger: "blur",
        },
      ],
      deptId: [
        {
          required: true,
          message: "请选择部门",
          trigger: "blur",
        },
      ],
    });
// 初始化接口调用
    onMounted(() => {
      getUserList();
      getRoleList();
      getDeptList();
    });
     // 获取用户列表
    const getUserList = async () => {
      let params = { ...user, ...pager };
      const { list, page } = await proxy.$api.getUserList(params);
      userList.value = list;
      pager.total = page.total;
    };
    // 查询
    const handleQuery = () => {
      getUserList();
    };
    // 重置
    const handleReset = (form) => {
      proxy.$refs[form].resetFields();
    };
    // 用户新增
    const handleCreate = () => {
      action.value = "add";
      showModal.value = true;
    };
    // 获取角色
    const getRoleList = async () => {
      let res = await proxy.$api.getRoleList();
      roleList.value = res;
    };
    // 获取部门
    const getDeptList = async () => {
      let res = await proxy.$api.getDeptList();
      deptList.value = res;
    };
    // 用户弹窗关闭
    const handleClose = () => {
      showModal.value = false;
      handleReset("dialogForm");
    };
    // 用户提交
    const handleSubmit = () => {
      proxy.$refs.dialogForm.validate(async (valid) => {
        if (valid) {
          let params = toRaw(userForm);
          params.userEmail += "@qq.com";
          params.action = action.value;
          let res = await proxy.$api.userSubmit(params);
          if (res) {
            showModal.value = false;
            proxy.$message.success("用户创建成功");
            handleReset("dialogForm");
            getUserList();
          }
        }
      });
    };
    // 用户编辑
    const handleEdit = (row) => {
      action.value = "edit";
      showModal.value = true;
      proxy.$nextTick(() => {
        Object.assign(userForm, row);
      });
    };
     return {
      user,
      userList,
      columns,
      pager,
      checkedUserIds,
      showModal,
      userForm,
      rules,
      roleList,
      deptList,
      action,
      getUserList,
      handleQuery,
      handleReset,
      handleCurrentChange,
      handleDel,
      handlePatchDel,
      handleSelectionChange,
      handleCreate,
      getRoleList,
      getDeptList,
      handleClose,
      handleSubmit,
      handleEdit,
    };
  • 注意点

如果要去点击编辑赋值以后,再去点开新增,由于页面已经渲染完了,会把数据带过去,所以新增也会有数据
这个时候需要让 去处理

 proxy.$nextTick(() => {
        Object.assign(userForm, row);
      });

// 用户编辑 const handleEdit = (row) => { action.value = "edit"; showModal.value = true; proxy.$nextTick(() => { Object.assign(userForm, row); }); };

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不停喝水

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

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

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

打赏作者

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

抵扣说明:

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

余额充值