element-ui table数据表格实现与坑点记录

怎么查看项目依赖了哪些文件和版本

  1. 找到与src同级目录的package.json
  2. 再找到devDependencies查看即可

js变量不存在则给予默认值

this.total = res.total || 0; // 赋值总条数,当不存在total属性时,total属性赋为默认值0

模态框坑点

  1. 添加和修改共用一个模态框,且提交完表单后,需要重置模态框表单的字段值为空对象
  2. 否则添加模态框、修改页面、该条数据都会受到影响
  3. 需要自定义一个变量来确认是走 添加接口 还是 修改接口,此处变量使用的是modalType
  4. 修改模态框内,赋值不能直接使用 this.row = row ,这涉及到深拷贝,会影响到该条数据
  5. 添加和修改共用一个模态框,使用不当时,极有可能出现“点击编辑栏后,再点击添加栏,表单数据没被清空依旧存在等问题”,解决方案是表单回显给数据赋值的时候写到this.$nextTick里面。表单清空写在dialog关闭前面。
原因:
1 this.$refs['xxx'].resetFields()这个做法其实是重置表单到初始值,不是清空表单,当表单第一次在页面中渲染时所用的数据就是初始数据。
2 this.$refs[xxx]必须要在dialog显示之后再调用,否则会找不到这个元素报错。

接口坑点

  1. 无论请求哪个接口,都要使用 .catch((err)=>{console.log(err)}) 进行兜底捕获异常,不然页面会产生验证报错,影响体验
  2. 后端使用tp返回接口时,可能PHP内部逻辑错误,导致前台显示跨域错误

携带参数请求接口坑点

post方式携参请求

直接传参params,作为第二参数即可

// 获取用户数据列表
export const getUser = (params) => {
    return axios.post(`${url}index`, params);
}

get方式携参请求

直接传参params,需要创建一个对象{},对象名伟params,对象值为对params进行解构赋值的{...params}作为第二参数

// 获取用户数据列表
export const getUser = (params) => {
    return axios.get(`${url}index`, {
        params: { ...params }
    });
}

获取列表数据坑点

  以下几处,需要调用获取列表数据接口,获取最新数据

  1. 表单模态框添加完数据后
  2. 表单模态框修改完数据后
  3. 数据表格删除数据后

页码坑点

  以下几处,需要将页码变量重置为1

  1. 搜索栏携参搜索search方法,获取列表数据时
  2. 切换每页展示条数limit时
  3. page-sizes的起始页码必须绑定limit变量,否则会产生分页逻辑错误
  4. total、page-size、current-page、page-sizes必须在el-pagination分页组件中声明且绑定变量

否则会出现查询数据为空现象,这是因为在同等条件下,没有找到相应页码的数据
例如符合条件的数据一共只能分2页,偏偏此处没有重置页码为1,而是传递了第6页作为参数,自然就找不到了


完整代码

<template>
  <div class="manage">
    <!-- 模态框 -->
    <el-dialog
      :title="title"
      center
      :visible.sync="dialogVisible"
      :before-close="handleClose"
      width="50%"
    >
      <el-form
        :model="form"
        ref="form"
        label-width="100px"
        :inline="true"
        :rules="rules"
      >
        <el-form-item label="姓名" prop="username">
          <el-input v-model="form.username" placeholder="请输入姓名"></el-input>
        </el-form-item>
        <el-form-item label="分数" prop="score">
          <el-input v-model="form.score" placeholder="请输入分数"></el-input>
        </el-form-item>
        <el-form-item label="性别" prop="sex">
          <el-select v-model="form.sex" placeholder="请选择性别">
            <el-option label="男" value="1"></el-option>
            <el-option label="女" value="0"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="生日" prop="birthday">
          <el-col>
            <el-form-item prop="birthday">
              <el-date-picker
                type="date"
                placeholder="选择生日"
                v-model="form.birthday"
                style="width: 100%"
                value-format="yyyy-MM-dd"
              ></el-date-picker>
            </el-form-item>
          </el-col>
        </el-form-item>
        <el-form-item label="等级" prop="level">
          <el-input v-model="form.level" placeholder="请输入等级"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="submit">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 头部操作栏 -->
    <div class="manage-header">
      <el-button type="primary" @click="handleAdd">+ 新增</el-button>
      <el-button @click="multipleDel()" type="danger">多选删除</el-button>
      <el-button @click="toggleSelection()">取消选中</el-button>
      <el-form
        ref="userform"
        :model="userform"
        label-width="70px"
        :inline="true"
        class="userForm"
      >
        <el-form-item label="姓名" prop="username">
          <el-input v-model="userform.username"></el-input>
        </el-form-item>
        <el-form-item label="性别" prop="sex">
          <el-select v-model="userform.sex" placeholder="请选择性别">
            <el-option label="男" value="1"></el-option>
            <el-option label="女" value="0"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="生日" prop="birthday">
          <el-date-picker
            v-model="userform.birthday"
            type="daterange"
            align="right"
            unlink-panels
            value-format="yyyy-MM-dd"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            :picker-options="pickerOptions"
          >
          </el-date-picker>
        </el-form-item>
        <el-form-item>
          <el-button type="warning" @click="search">搜索</el-button>
          <el-button @click="resetForm">清空</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 数据表格 -->
    <div class="table">
      <el-card class="tableCard" shadow="hover">
        <el-table
          :data="list"
          ref="list"
          v-loading="loading"
          style="width: 100%"
          stripe
          border
        >
          <el-table-column type="selection" width="55"> </el-table-column>
          <el-table-column prop="id" label="ID"> </el-table-column>
          <el-table-column prop="username" label="姓名"> </el-table-column>
          <el-table-column prop="sex" label="性别">
            <template slot-scope="scope">
              <span style="margin-left: 10px">
                {{ scope.row.sex == 1 ? "男" : "女" }}
              </span>
            </template>
          </el-table-column>
          <el-table-column prop="level" label="等级"> </el-table-column>
          <el-table-column prop="score" label="分数"> </el-table-column>
          <el-table-column prop="birthday" label="生日"> </el-table-column>
          <el-table-column label="操作">
            <template slot-scope="scope">
              <el-button
                type="success"
                size="mini"
                @click="handleEdit(scope.row)"
                >编辑</el-button
              >
              <el-button
                size="mini"
                type="danger"
                @click="handleDelete(scope.row.id)"
                >删除</el-button
              >
            </template>
          </el-table-column>
        </el-table>
      </el-card>
      <!-- 分页 -->
      <div class="pagination">
        <el-pagination
          :page-sizes="[limit, 7, 9, 11]"
          :current-page="page"
          :page-size="limit"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          prev-text="上一页"
          next-text="下一页"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :hide-on-single-page="true"
        >
        </el-pagination>
      </div>
    </div>
  </div>
</template>

<script>
import { getUser, addUser, editUser, delUser } from "../api/user/index";
export default {
  data() {
    return {
      //当只有一页时隐藏分页
      isShow: false,
      // 加载动画
      loading: true,
      // 数据列表
      list: [],
      // 每页展示条数
      limit: 5,
      // 默认当前页码
      page: 1,
      // 数据列表总数据
      total: 0,
      // 模态框的值,用于判断是走入add还是edit逻辑
      modalType: false,
      // 模态框的显示隐藏控制
      dialogVisible: false,
      // 搜索栏表单字段信息
      userform: {
        username: "",
        birthday: [],
        // score: "",
        sex: "",
        // level: "",
      },
      // 搜索栏的日期时间选择快捷处理
      pickerOptions: {
        shortcuts: [
          {
            text: "最近一周",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
              picker.$emit("pick", [start, end]);
            },
          },
          {
            text: "最近一个月",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
              picker.$emit("pick", [start, end]);
            },
          },
          {
            text: "最近三个月",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
              picker.$emit("pick", [start, end]);
            },
          },
        ],
      },
      // 模态框表单字段信息
      form: {
        username: "",
        birthday: "",
        score: "",
        sex: "",
        level: "",
      },
      // 模态框表单字段的验证规则
      rules: {
        username: [{ required: true, message: "请输入姓名" }],
        birthday: [{ required: true, message: "请选择生日" }],
        score: [{ required: true, message: "请输入分数" }],
        sex: [{ required: true, message: "请输入性别" }],
        level: [{ required: true, message: "请输入等级" }],
      },
    };
  },
  computed: {
    title() {
      return this.modalType ? "修改" : "添加";
    },
  },
  methods: {
    // 搜索表单
    search() {
      // 重置页码
      this.initPage();
      // 拿到最新数据
      this.handleList(this.userform);
    },
    // 重置搜索表单字段
    resetForm() {
      this.$refs.userform.resetFields();
      // 拿到最新数据
      this.handleList();
    },
    // 多选删除
    multipleDel() {
      const selection = this.$refs.list.selection;
      const ids = [];
      selection.map((obj) => {
        ids.push(obj.id);
      });
      this.handleDelete(ids);
    },
    // 取消表格checkbox选中
    toggleSelection() {
      this.$refs.list.clearSelection();
    },
    // 表单提交
    submit() {
      // 使用element-ui的表单验证方法,得到验证后结果值和验证失败的对象
      this.$refs.form.validate((res, obj) => {
        // 验证通过
        if (res) {
          // 根据modalType值来判断走入add还是edit
          if (this.modalType) {
            // edit----传参进行ajax请求
            editUser(this.form).then((res) => {
              this.handleSuccess(res);
            });
          } else {
            // add----传参进行ajax请求
            addUser(this.form).then((res) => {
              this.handleSuccess(res);
            });
          }
        }
      });
    },
    // 处理API成功响应回来的逻辑
    handleSuccess(res) {
      // 响应码判断
      if (200 == res.code) {
        // 成功提示
        this.$message({
          showClose: true,
          center: true,
          message: res.msg,
          type: "success",
          duration: 1500,
        });
        // 关闭弹窗
        this.handleClose();
        // add/edit后,都需要刷新列表,拿到最新的数据
        this.handleList();
      }
    },
    // 关闭模态框,重置form表单字段值
    handleClose() {
      this.dialogVisible = false;
      // this.$refs["form"].resetFields();
      this.$nextTick(() => {
        for (let key in this.form) {
          this.form[key] = "";
        }
        this.$refs["form"].clearValidate();
      });
      for (let key in this.form) {
        this.form[key] = "";
      }
      this.$refs["form"].clearValidate();
    },
    // 取消表单,清空所有字段值
    cancel() {
      this.handleClose();
    },
    // 增加
    handleAdd() {
      // 开启弹窗
      this.dialogVisible = true;
      // 赋值模态框类型为true,提供ajax提交时判断是add
      this.modalType = false;
      console.log("测试编辑后再点击添加是否还有值", this.form.username);
    },
    // 删除
    handleDelete(id) {
      this.$confirm("确定删除吗?", "提示信息", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          delUser({ id: id }).then((res) => {
            this.$message({
              showClose: true,
              center: true,
              message: res.msg,
              type: "success",
              duration: 1500,
            });
            this.handleList();
          });
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 编辑
    handleEdit(row) {
      // 开启弹窗
      this.dialogVisible = true;
      // 赋值模态框类型为true,提供ajax提交时判断是edit
      this.modalType = true;
      // 深拷贝赋值,让dialog框有值渲染,不能直接浅拷贝赋值this.form = row,否则会影响到add时候的弹窗
      this.form = JSON.parse(JSON.stringify(row));
    },
    // 查询
    handleList(param) {
      // 默认分页查询参数
      const defaultPageInfo = { page: this.page, limit: this.limit };
      /* 
          传入了额外参数,则将额外参数与搜索栏参数、分页查询参数合并组成查询条件
          否则直接使用搜索栏参数、分页查询参数合并作为查询条件
      */
      const data = param
        ? { ...param, ...this.userform, ...defaultPageInfo }
        : { ...defaultPageInfo, ...this.userform };
      // 携带参数进行请求
      getUser(data)
        .then((res) => {
          // 赋值表格数据列表,以供渲染
          this.list = res.data;
          // 赋值总条数,当不存在total属性时赋值为0
          this.total = res.total || 0;
          // 取消过渡加载动画
          this.loading = false;
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 每页展示条数变化
    handleSizeChange(val) {
      this.limit = val;
      // 每次切换展示条数时,都要重置页码为1。否则会出现明明有数据却因为页码错误导致的api返回空数据
      this.initPage();
      // 开启过渡加载动画
      this.loading = true;

      this.handleList();
    },
    // 当前页码变化
    handleCurrentChange(val) {
      this.page = val;
      // 开启过渡加载动画
      this.loading = true;
      this.handleList();
    },
    // 初始化页码
    initPage() {
      this.page = 1;
    },
  },
  created() {
    this.handleList();
  },
};
</script>

<style lang="less" scoped>
.manage {
  height: 100%;
}
.userForm {
  margin-top: 30px;
}
.table {
  position: relative;
  .pagination {
    position: absolute;
    right: 0;
    margin-top: 20px;
  }
}
</style>
posted @ 2024-02-01 14:51  Anbin啊  阅读(44)  评论(0)    收藏  举报