day45-46-Vue+ElementUI实现学生管理

Vue+ElementUI实现学生管理

代码: qiushiju/java2313_vue_elementui_crud (gitee.com)

一、思考

  1. 考虑需求(登录,查询全部,基本增删改查,分页,搜索,批量)

    image-20231207170514721
image-20231207170737870
  1. 设计数据库
  2. 搭建项目
    1. 后端项目(day39_springboot_curd)已经完成
    2. 前端项目(暂无)ps:前端写的接口数据 需要和后端一致

二、搭建前端项目

2.1 使用vue-cli创建项目,选择router,vuex

2.2 安装所需axios,elementui

# 安装依赖
npm install --save axios vue-axios
npm i element-ui -S
// 在main.js中配置axios,element
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);

// axios
import axios from "axios";
axios.defaults.baseURL = 'http://localhost:8888'

// 添加Axios响应拦截器
axios.interceptors.response.use(function (response) {
  //console.log('响应拦截',response)
  return response.data;
}, function (error) {
  console.log(error)
});

2.3 自带About,HomeView,HelloWorld组件删除

三、登录页

考虑: 项目默认访问首页是登录页.怎么实现?

解决: 在路由表中定义/路径匹配Login.vue

App.vue中只保留一个路由 出口<router-view/>

const routes = [
  {
    path: '/',
    component: View1Login
  }
]

登录页View1Login.vue

<template>
<div>
  <el-row class="c1">
    <el-col class="c1" :span="6" :offset="9">
      <div class="c2">
        <el-form ref="form" :model="stu" label-width="80px">
          <el-form-item label="用户名">
            <el-input v-model="stu.sname"></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="onSubmit">登录</el-button>
          </el-form-item>
        </el-form>
      </div>
    </el-col>
  </el-row>
</div>
</template>

<script>
import axios from "axios";
export default {
  name: "View1Login",
  data(){
    return  {
      stu:{
        sname:""
      }
    }
  },
  methods:{
    onSubmit(){
      // axios.post('/stu/login',{},{
      //   params:{
      //     username:this.stu.sname
      //   }
      // })
      // console.log(this.stu.sname)
      axios.post('/stu/login',{
        sname:this.stu.sname
      }).then(ret => {
        if (ret.code==20000){
          this.$message({
            message:"登录成功",
            type:"success",
            duration:700
          })
          // TODO 跳转页面
        }else{
          this.$message({
            message:"登录失败",
            type:"error",
            duration:700
          })
        }
      })
    }
  }
}
</script>

<style scoped>
.c1 {
  margin-top: 150px;
}
.c2{
  border: 2px #2c3e50 solid;
}
</style>

扩展: 输入框输入完,提示该人是否注册


登录成功后,跳转主页

onSubmit(){
      axios.post('/stu/login',{
        sname:this.stu.sname
      }).then(ret => {
        if (ret.code==20000){
          this.$message({
            message:"登录成功",
            type:"success",
            duration:700
          })
         // 登陆成功 ,要跳转主页
          this.$router.push('/admin')
        }else{
          this.$message({
            message:"登录失败",
            type:"error",
            duration:700
          })
        }
      })
    }

image-20231208094942042

四、主页

思考:

  1. 登录成功后,App.vue页面切换成主页
  2. 主页面需要容器布局,在右侧main主页内容这里还能 再切换其后页面

首先,创建View2Admin.vue主页,布局效果

<template>
<div>
  <el-container>
    <el-header style="text-align: right; font-size: 20px">
      <span>王小虎</span>
    </el-header>
    <el-container>
      <el-aside width="200px">
        <el-menu>
          <el-submenu index="1">
            <template slot="title"><i class="el-icon-message"></i>导航一</template>
            <el-menu-item index="1-1">选项1</el-menu-item>
            <el-menu-item index="1-2">选项2</el-menu-item>
          </el-submenu>
          <el-submenu index="2">
            <template slot="title"><i class="el-icon-menu"></i>导航二</template>
            <el-menu-item index="2-1">选项1</el-menu-item>
            <el-menu-item index="2-2">选项2</el-menu-item>
          </el-submenu>
        </el-menu>
      </el-aside>
      <el-container>
        <el-main>Main</el-main>
        <el-footer>© 2023 Taotie Copyright</el-footer>
      </el-container>
    </el-container>
  </el-container>
</div>
</template>

<script>
export default {
  name: "View2Admin"
}
</script>

<style scoped>
.el-header, .el-footer {
  background-color: #3c8dbc;
  color: #333;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  background-color: #2f4050;
  color: white;
  text-align: center;
  line-height: 200px;
  height: 650px;
}

.el-main {
  background-color: #E9EEF3;
  color: #333;
  text-align: center;
  line-height: 160px;
}

body > .el-container {
  margin-bottom: 40px;
}

.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
  line-height: 260px;
}

.el-container:nth-child(7) .el-aside {
  line-height: 320px;
}
</style>

image-20231208094959147

五、用户名

  1. 现在vuex中设置用户名变量
  2. 登录时存入state
  3. 主页中取出

// vuex

export default new Vuex.Store({
  state: {
    username:"" // 设置变量名
  },
  mutations: {
    setUsername(state,v){  // 提供一个改变用户名的方式
      state.username = v;
    }
  }
})

// 登录时存入state

axios.post('/stu/login',{
        sname:this.stu.sname
      }).then(ret => {
        if (ret.code==20000){
          this.$message({
            message:"登录成功",
            type:"success",
            duration:700
          })
          // 存储用户名
          this.$store.commit('setUsername',ret.data.sname)
         // 登陆成功 ,要跳转主页
          this.$router.push('/admin')
        }else{
          this.$message({
            message:"登录失败",
            type:"error",
            duration:700
          })
        }
      })

// 主页中取出

<script>
import {mapState}  from 'vuex'
export default {
  name: "View2Admin",
  // computed:{
  //   username(){
  //     return this.$store.state.username
  //   }
  // }
  computed:mapState(['username'])
}
</script>

六、退出按钮

    <el-header style="text-align: right; font-size: 20px">
      <span>{{username}}</span> &nbsp;&nbsp;
      <span>
        <el-button @click="logout" type="warning" size="small">退出</el-button>
      </span>
    </el-header>
  methods:{
    logout(){
      this.$router.push("/")
    }
  }

七、欢迎页

登录成功,跳转主页,主页先不展示数据,而是展示欢迎页

创建欢迎页,引入图片

<template>
<div>
  <img width="700px" src="../assets/bgm.jpg" alt="背景图">
</div>
</template>

<script>
export default {
  name: "View3Welcome"
}
</script>

<style scoped>

</style>

Admin.vue中设置路由出口

image-20231208102429999

router/index.js路由表给admin设置子路由,目的是访问主页时,默认跳转至欢迎页

image-20231208102453451

image-20231208102247271

八、学生列表

思路: 点击左边菜单,路由到Admin的内部(即,子路由),分页展现所有学生信息

// 创建学生信息页,写table组件展示数据,在生命周期函数发请求查数据,给data中变量赋值

<template>
<div>
<!--  卡片-->
<el-card :body-style="{ padding: '20px',height:'400px' }">
  <!-- TODO: 表头行高度需要修改!!:header-row-style设置无效!! -->
  <el-table
      :data="stuList"
      style="width: 100%"
      border
      :header-row-style="{ height: '5px' }"
  >
    <el-table-column
        type="selection"
        width="55">
    </el-table-column>
    <!-- label是列名,prop是对象的属性  -->
    <el-table-column
        label="学号"
        prop="id"
        width="180">
    </el-table-column>
    <el-table-column
        prop="sname"
        label="姓名"
        width="180">
    </el-table-column>
    <el-table-column
        prop="age"
        label="年龄"
        sortable
    >
    </el-table-column>
    <el-table-column
        prop="sex"
        label="性别">
    </el-table-column>
    <el-table-column
        prop="score"
        label="分数">
    </el-table-column>
    <el-table-column
        prop="birthday"
        label="生日">
    </el-table-column>
  </el-table>
</el-card>
</div>
</template>

<script>
import axios from "axios";
export default {
  name: "View4StuInfo",
  data(){
    return {
      stuList:[]
    }
  },
  // 定义生命周期函数,页面加载完即展现数据
  created() {
    axios.get('/stu/list',{
      params:{
        pageNum:1  // 默认访问第一页
      }
    }).then(ret => {
      if (ret.code == 20000){
        // ret.data是后端返回的PageInfo
        console.log(ret.data)
        this.stuList= ret.data.list;
      } else {
        this.$message.error('后台请求错误')
      }
    })
  }
}
</script>

<style scoped>

</style>

// 主页面,左侧菜单,点击路由跳转至学生页

image-20231208111025604

// 经过路由表映射,到admin的子路由中

image-20231208111059040

九、分页查询

1)设置分页组件

2) 设置对应的 函数

<template>
<div>
<!--  卡片-->
<el-card :body-style="{ padding: '20px',height:'400px' }">
  <!-- TODO: 表头行高度需要修改!!:header-row-style设置无效!! -->
  <el-table
      :data="stuList"
      style="width: 100%"
      border
      :header-row-style="{ height: '5px' }"
      height="370px"
  >
    <el-table-column
        type="selection"
        width="55">
    </el-table-column>
    <!-- label是列名,prop是对象的属性  -->
    <el-table-column
        label="学号"
        prop="id"
        width="180">
    </el-table-column>
    <el-table-column
        prop="sname"
        label="姓名"
        width="180">
    </el-table-column>
    <el-table-column
        prop="age"
        label="年龄"
        sortable
    >
    </el-table-column>
    <el-table-column
        prop="sex"
        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
            size="mini"
           >编辑</el-button>
        <el-button
            size="mini"
            type="danger"
            >删除</el-button>
      </template>
    </el-table-column>
  </el-table>
  <div>
    <!--
        @size-change="handleSizeChange"      页面大小改变会触发函数
        @current-change="handleCurrentChange"当前页改变 触发函数
        :current-page.sync="currentPage"
        :page-sizes="[3, 6, 9]"   演示每页大小列表
        :page-size="pageSize"     绑定页面大小,下方data中定义变量
        layout="sizes,prev, pager, next"  外观显示效果
        :total="total">   总条数,下方data中定义变量
    -->
    <el-pagination
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page.sync="currentPage"
        :page-sizes="[3, 6, 9]"
        :page-size="pageSize"
        layout="sizes,prev, pager, next"
        :total="total">
    </el-pagination>
  </div>
</el-card>
</div>
</template>

<script>
import axios from "axios";
export default {
  name: "View4StuInfo",
  data(){
    return {
      stuList:[],
      currentPage: 1,
      pageSize: 3,
      total: 0,
    }
  },
  methods:{
    // 抽取查询数据的方法,可以复用
    getData(){
      axios.get('/stu/list',{
        params:{
          pageNum:this.currentPage,  // 默认访问第一页
          pageSize: this.pageSize
        }
      }).then(ret => {
        if (ret.code == 20000){
          // ret.data是后端返回的PageInfo
          console.log(ret.data)
          this.stuList= ret.data.list;
          this.total=ret.data.total;
        } else {
          this.$message.error('后台请求错误')
        }
      })
    },
    // 页面大小变化时,改变pageSize
    handleSizeChange(val) {
      this.pageSize = val;
      this.getData();
    },
    // 当前页变化,即跳转页面时
    handleCurrentChange(val) {
      this.currentPage = val;
      // 重新查询当前页数据
      this.getData();
    },
  },
  // 定义生命周期函数,页面加载完即展现数据
  created() {
    this.getData();
  }
}
</script>

<style scoped>

</style>

image-20231208113907620

十、添加

image-20231211174530052

需求:

1)表格上方设置添加按钮

2)弹出弹出层对话框

3)其中设置表单

4)点击保存,插入数据库

5)对话框隐藏,查询最新数据


在StuInfo.vue中添加对话框和对应的js

<template>
<div>
<!--  卡片-->
<el-card :body-style="{ padding: '20px',height:'400px' }">
  <div style="text-align: left">
    <el-button type="danger">批量删除</el-button>
    <!-- 显示/隐藏对话框,通过变量 -->
    <el-button type="primary" @click="addDialogVisible = true">添加</el-button>
  </div>
  <!-- 添加对话框,默认是隐藏 -->
  <el-dialog
      title="添加"
      :visible.sync="addDialogVisible"
      width="30%"
      :before-close="handleClose">

    <el-form :model="stu" status-icon :rules="rules" ref="stu" label-width="100px" class="demo-stu">
      <el-form-item label="用户名" prop="sname">
        <el-input type="text" v-model="stu.sname" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="年龄" prop="age">
        <!-- TODO: .number是修饰符,输入的直接就是数字 -->
        <el-input type="text" v-model.number="stu.age" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="性别" prop="sex">
        <!--todo: 单选框获得的值是什么?是label的值? 结论!是label值-->
        <el-radio-group v-model="stu.sex">
          <el-radio label=""></el-radio>
          <el-radio label=""></el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="分数" prop="score">
        <el-input type="text" v-model="stu.score" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="生日" prop="birthday">
        <el-col :span="11">
          <el-date-picker type="date" placeholder="选择日期" v-model="stu.birthday" value-format="yyyy-MM-dd" style="width: 100%;"></el-date-picker>
        </el-col>
      </el-form-item>

      <el-form-item>
        <el-button @click="addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitForm('stu')">提交</el-button>
      </el-form-item>
    </el-form>
  </el-dialog>

  <!-- 表格渲染数据: 省略 -->
  <!-- 分页: 省略 -->
  </div>
</el-card>
</div>
</template>

<script>
import axios from "axios";
export default {
  name: "View4StuInfo",
  data(){
   // 自定义校验年龄
    var checkAge = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('年龄不能为空'));
      }
      if (!Number.isInteger(value)) {
        callback(new Error('请输入数字值'));
      } else {
        if (value < 18) {
          callback(new Error('必须年满18岁'));
        } else {
          // 校验通过放行!!
          callback();
        }
      }
    };
    return {
      stuList:[],
      currentPage: 1,
      pageSize: 3,
      total: 0,
      addDialogVisible: false,
      stu:{
        sname:"",
        age:0,
        sex:"",
        score:0.0,
        birthday:""
      },
      rules: {
        age: [
          { validator: checkAge, trigger: 'blur' }
        ]
      }
    }
  },
  methods: {
    // 抽取查询数据的方法,可以复用
    getData() {
      axios.get('/stu/list', {
        params: {
          pageNum: this.currentPage,  // 默认访问第一页
          pageSize: this.pageSize
        }
      }).then(ret => {
        if (ret.code == 20000) {
          // ret.data是后端返回的PageInfo
          console.log(ret.data)
          this.stuList = ret.data.list;
          this.total = ret.data.total;
        } else {
          this.$message.error('后台请求错误')
        }
      })
    },
    // 页面大小变化时,改变pageSize
    handleSizeChange(val) {
      this.pageSize = val;
      this.getData();
    },
    // 当前页变化,即跳转页面时
    handleCurrentChange(val) {
      this.currentPage = val;
      // 重新查询当前页数据
      this.getData();
    },
    handleClose(done) {
      this.$confirm('确认关闭?')
          .then(_ => {
            done();
          })
          .catch(_ => {
          });
    },
    // 提交表单,并隐藏对话框
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          console.log("提交表单--->  ",this.stu)
          // TODO 添加成功! 但是市区不对!
          //  已解决! 给el-date-picker设置value-format="yyyy-MM-dd"即可
          axios.post('/stu/add',this.stu).then(ret =>{
            console.log(ret)
          })
        } else {
          console.log('error submit!!');
          return false;
        }
      });

      // 重置当前页为第一页,
      this.currentPage = 1;
      // 查询最新数据,从第一页查
      this.getData();

      // 隐藏对话框
      this.addDialogVisible = false;
      // 对话框清空
      this.$refs.stu.resetFields()
    },
  },
  // 定义生命周期函数,页面加载完即展现数据
  created() {
    this.getData();
  }
}
</script>

<style scoped>

</style>

问题1: 时区,时间差一天 // 已解决! 给el-date-picker设置value-format="yyyy-MM-dd"即可

问题2:添加表格没有清空

// 解决方案:对话框清空,注意此处stu是el-form上面定义的ref的值
this.$refs.stu.resetFields()

十一、更新

image-20231211174547519

思路:

1)点击更新按钮,弹出对话框

2)对话框回显数据 ps: elementui-table组件,按钮事件中自带属性scope,触发按钮获得当前行内数据

3)点击保存

4)对话框隐藏,重新查询


StuInfo.vue

<template>
<div>
<!--  卡片-->
<el-card :body-style="{ padding: '20px',height:'400px' }">
  <div style="text-align: left">
    <el-button type="danger">批量删除</el-button>
    <!-- 显示/隐藏对话框,通过变量 -->
    <el-button type="primary" @click="addDialogVisible = true">添加</el-button>
  </div>
  <!-- 添加对话框,默认是隐藏 -->

  <!--更新对话框,默认是隐藏 -->
  <el-dialog
      title="更新"
      :visible.sync="editDialogVisible"
      width="30%"
  >

    <el-form :model="stu" status-icon :rules="rules" ref="editStuRef" label-width="100px" class="demo-stu">
      <el-form-item label="用户名" prop="sname">
        <el-input type="text" v-model="stu.sname" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="年龄" prop="age">
        <el-input type="text" v-model.number="stu.age" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="性别" prop="sex">
        <el-radio-group v-model="stu.sex">
          <el-radio label=""></el-radio>
          <el-radio label=""></el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="分数" prop="score">
        <el-input type="text" v-model="stu.score" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="生日" prop="birthday">
        <el-col :span="11">
          <el-date-picker type="date" placeholder="选择日期" v-model="stu.birthday" value-format="yyyy-MM-dd" style="width: 100%;"></el-date-picker>
        </el-col>
      </el-form-item>

      <el-form-item>
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editForm('editStuRef')">更新</el-button>
      </el-form-item>
    </el-form>
  </el-dialog>
  <!-- 表格渲染数据 -->
  <el-table
      :data="stuList"
      style="width: 100%"
      border
      height="340px"
  >
    <el-table-column
        type="selection"
        width="55">
    </el-table-column>
    <!-- label是列名,prop是对象的属性  -->
    <el-table-column
        label="学号"
        prop="id"
        width="180">
    </el-table-column>
    <el-table-column
        prop="sname"
        label="姓名"
        width="180">
    </el-table-column>
    <el-table-column
        prop="age"
        label="年龄"
        sortable
    >
    </el-table-column>
    <el-table-column
        prop="sex"
        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="warning"
            size="mini"
            @click="handleEdit(scope.$index, scope.row)"
           >编辑</el-button>
        <el-button
            size="mini"
            type="danger"
            >删除</el-button>
      </template>
    </el-table-column>
  </el-table>
  <!-- 分页 -->

</div>
</template>

<script>
import axios from "axios";
export default {
  name: "View4StuInfo",
  data(){
   // 自定义校验年龄
    var checkAge = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('年龄不能为空'));
      }
      if (!Number.isInteger(value)) {
        callback(new Error('请输入数字值'));
      } else {
        if (value < 18) {
          callback(new Error('必须年满18岁'));
        } else {
          // 校验通过放行!!
          callback();
        }
      }
    };
    // 数据
    return {
      stuList:[],
      currentPage: 1,
      pageSize: 3,
      total: 0,
      addDialogVisible: false,
      editDialogVisible:false,
      stu:{
        sname:"",
        age:0,
        sex:"",
        score:0.0,
        birthday:""
      },
      rules: {
        age: [
          { validator: checkAge, trigger: 'blur' }
        ]
      }
    }
  },
  // 函数
  methods: {
    // 抽取查询数据的方法,可以复用

    // 页面大小变化时,改变pageSize

    // 当前页变化,即跳转页面时

    // 提交添加表单,并隐藏对话框
    // 处理更新回显
    handleEdit(index, row) {
      this.editDialogVisible = true;
      this.stu = row
    },
    // 提交更新表单,并隐藏对话框
    editForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          console.log("提交更新表单--->  ",this.stu)
          axios.put('/stu/edit',this.stu).then(ret =>{
            if (ret.code == 20000) {
              // 重置当前页为第一页,
              this.currentPage = 1;
              // 查询最新数据,从第一页查
              this.getData();
            }
          })
        } else {
          console.log('error submit!!');
          return false;
        }
      });

      // 隐藏对话框
      this.editDialogVisible = false;
      // 对话框清空
      this.$refs.editStuRef.resetFields()
    },
  },
  // 定义生命周期函数,页面加载完即展现数据
}
</script>

问题1: 后端查询日期到前端显示少一天!

解决: @JsonFormat(pattern = “yyyy-MM-dd”,timezone = “GMT+8”)

参考解决springboot框架返回前端的日期值少一天_springboot 后端传给前端的时间不是24小时-CSDN博客

十二、删除

image-20231211174605778

思路:

1)删除按钮

2)弹出确认框,确定删除,取消

3)确定删除,发请求携带id

4)删除完重新查询数据


image-20231211142808829

image-20231211142910357

十三、批量删除

image-20231211174629974

1)设置复选框改变,获得选中行数据

image-20231211150256814

2)点击批量删除按钮,发请求

image-20231211150435783

3)后端接收id数组

image-20231211150535084

十四、模糊搜索

image-20231211174503098

需求: 提供根据名字模糊搜索,年龄等值搜索,时间区间搜


思路:

1)设置卡片,卡片中设置 搜索表单

2)点击搜索,发请求搜索 -->用的还是查询全部,只不过多带了一些搜索关键词

3)搜索后数据还在表格 中展现


  <div style="margin-bottom: 10px">
<!--  搜索框卡片-->
  <el-card :body-style="{ padding: '20px',height:'30px'}">
    <el-form :inline="true" :model="searchModel" status-icon ref="searchModelRef" label-width="100px" class="demo-stu">
      <el-form-item label="用户名"prop="sname">
        <el-input style="width: 200px" size="small" type="text" v-model="searchModel.sname" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="年龄" prop="age">
        <el-input style="width: 50px" size="small" type="text" v-model.number="searchModel.age" autocomplete="off"></el-input>
      </el-form-item>
      <el-form-item label="生日">
        <el-col :span="11">
          <el-form-item prop="birthday1">
            <el-date-picker size="small" type="date" placeholder="选择日期" v-model="searchModel.birthday1" value-format="yyyy-MM-dd" style="width: 100%;"></el-date-picker>
          </el-form-item>
        </el-col>
        <el-col class="line" :span="2">-</el-col>
        <el-col :span="11">
          <el-form-item prop="birthday2">
            <el-date-picker size="small" type="date" placeholder="选择日期" v-model="searchModel.birthday2" value-format="yyyy-MM-dd" style="width: 100%;"></el-date-picker>
          </el-form-item>
        </el-col>
      </el-form-item>

      <el-form-item>
        <el-button size="small" type="primary" @click="searchSubmit">提交</el-button>
        <el-button size="small" @click="resetSearch('searchModelRef')">重置 </el-button>
      </el-form-item>
    </el-form>
  </el-card>
  </div>
<script>
import axios from "axios";
export default {
  name: "View4StuInfo",
  data(){
      return{
          // 搜索关键词
      	searchModel:{
            sname:"",
            age:0,
            birthday1:"",
            birthday2:"",
            pageSize:3,
            pageNum:1
      	}
      }
  },
    methods:{
        //代码见图
    }
}

image-20231211163946789

改动 了getData()函数,从原来只有分页查询,改成了带上模糊关键词查询

image-20231211164039908


后端查询全部的接口,变成接收map,map中就包含搜索关键词和分页数据

image-20231211164139806

mapper做动态sql查询

image-20231211164241383

总结

  1. 前后端对接注意事项
// 前端发 get,用params
axios.get('/login',{
  params:{
  		username:this.username,
  		password:this.password,
  }
}).then(ret =>{})

// 后端Controller,方法正常写两个变量名接收
@GetMapping("/login")
public R login(String username,String password){}
// 前端发 post
axios.post('/login',{
  	username:this.username,
  	password:this.password,
}).then(ret =>{})

// 后端Controller,方法正常写两个变量名接收接不到!!!
// 方法参数列表需要用对象,且加@RequestBody
@PostMapping("/login")
public R login(@RequestBody User user){}
  1. 看日志,从日志中 你自己写过的相关的单词,变量,属性,方法等等

  2. axios有响应拦截,确定项目是否配置拦截!! 如果配置了拦截,我们已经在拦截中取出了响应的数据,即axios成功回调函数then中的ret就是获得的R

  3. 前后端对接

    增
       前端发post,携带数据是json
       后端@PostMapping,参数列表用json对应的java实体类,配上@RequestBody
    删一个
    	前端发get,携带参数可以 用{param:{id:1}}
    	后端@GetMapping,参数列表用一个基本类型int id接收
    删多个(批量)
        方案一:前端发get,携带参数可以拼接
    	     后端@GetMapping,参数列表用List,配合@RequestParam
        方案一:前端发post,携带参数,直接将数组放在data处
    	      后端@PostMapping,参数列表用List,配合@RequestBody	  	
    改
       前端发post/put,携带数据是json
       后端@PostMapping,参数列表用json对应的java实体类,配上@RequestBody
    查(空参)
    查(简单参数)
    	前端发post,携带json参数
    	后端方法参数列表用对象接收,@RequestBody
    	------
    	前端发get,携带{params:{username:'zs',password:'123'}}
    	后端方法参数列表,直接设置(String username,String password)
    查(复杂参数)
    	前端发get,携带params参数
    	后端方法参数列表用Map接收,配合@RequestParam
    

    基本上,前端只要使用post发送json,后端就得使用@RequestBody+对象

    前端使用get发送,普通参数,后端 正常接收 ,默认List,Map类型参数需要@RequestParam
    ord){}




```js
// 前端发 post
axios.post('/login',{
  	username:this.username,
  	password:this.password,
}).then(ret =>{})

// 后端Controller,方法正常写两个变量名接收接不到!!!
// 方法参数列表需要用对象,且加@RequestBody
@PostMapping("/login")
public R login(@RequestBody User user){}
  1. 看日志,从日志中 你自己写过的相关的单词,变量,属性,方法等等

  2. axios有响应拦截,确定项目是否配置拦截!! 如果配置了拦截,我们已经在拦截中取出了响应的数据,即axios成功回调函数then中的ret就是获得的R

  3. 前后端对接

    增
       前端发post,携带数据是json
       后端@PostMapping,参数列表用json对应的java实体类,配上@RequestBody
    删一个
    	前端发get,携带参数可以 用{param:{id:1}}
    	后端@GetMapping,参数列表用一个基本类型int id接收
    删多个(批量)
        方案一:前端发get,携带参数可以拼接
    	     后端@GetMapping,参数列表用List,配合@RequestParam
        方案一:前端发post,携带参数,直接将数组放在data处
    	      后端@PostMapping,参数列表用List,配合@RequestBody	  	
    改
       前端发post/put,携带数据是json
       后端@PostMapping,参数列表用json对应的java实体类,配上@RequestBody
    查(空参)
    查(简单参数)
    	前端发post,携带json参数
    	后端方法参数列表用对象接收,@RequestBody
    	------
    	前端发get,携带{params:{username:'zs',password:'123'}}
    	后端方法参数列表,直接设置(String username,String password)
    查(复杂参数)
    	前端发get,携带params参数
    	后端方法参数列表用Map接收,配合@RequestParam
    

    基本上,前端只要使用post发送json,后端就得使用@RequestBody+对象

    前端使用get发送,普通参数,后端 正常接收 ,默认List,Map类型参数需要@RequestParam

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/238320.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构期末考前复习

时间复杂度分析 常数时间复杂度 O(1) 的示例&#xff1a; def print_first_element(arr):print(arr[0])# 无论 arr 的大小如何&#xff0c;执行时间都是恒定的&#xff0c;因此具有常数时间复杂度。线性时间复杂度 O(n) 的示例&#xff1a; def print_all_elements(arr):for …

【并发编程篇】Callable实现多线程计算

文章目录 &#x1f354;简述Callable&#x1f33a;代码测试⭐如果改为了两个线程&#xff0c;效果如何 &#x1f354;简述Callable Callable是Java中一个函数式接口&#xff0c;用于表示可以返回结果并且可能会抛出异常的计算任务。该接口定义了一个call()方法&#xff0c;该方…

Flink Window中典型的增量聚合(ReduceFunction / AggregateFunction)

一、什么是增量聚合函数 在Flink Window中定义了窗口分配器&#xff0c;我们只是知道了数据属于哪个窗口&#xff0c;可以将数据收集起来了&#xff1b;至于收集起来到底要做什么&#xff0c;其实还完全没有头绪&#xff0c;这也就是窗口函数所需要做的事情。所以在窗口分配器…

VR转接线方案/VR Link串流数据线方案/VR眼镜PD快充方案

虚拟现实技术(英文名称&#xff1a;Virtual Reality&#xff0c;缩写为VR)&#xff0c;又称虚拟实境或灵境技术&#xff0c;是20世纪发展起来的一项全新的实用技术。虚拟现实技术囊括计算机、电子信息、仿真技术&#xff0c;其基本实现方式是以计算机技术为主&#xff0c;利用并…

数据库系列之简要对比下GaussDB和OpenGauss数据库

GaussDB作为一款企业级的数据库产品&#xff0c;和开源数据库OpenGauss之间又是什么样的关系&#xff0c;刚开始接触的时候是一头雾水&#xff0c;因此本文简要对比下二者的区别&#xff0c;以加深了解。 1、GaussDB和OpenGauss数据库简要对比 GaussDB是华为基于PostgreSQL数据…

表格中上传文件的表单验证

<template><!-- 新增记录 --><div class"newRecord"><div class"danger-detail"><div class"detail-right"><el-form :model"ruleForm" :rules"rules" ref"ruleForm" label-wid…

数据库系统原理与实践 笔记 #12

文章目录 数据库系统原理与实践 笔记 #12事务管理和并发控制与恢复(续)并发控制SQL-92中的并发级别基于锁的协议基于锁的协议的隐患锁的授予封锁协议两阶段封锁协议多粒度粒度层次的例子意向锁类型相容性矩阵多粒度封锁模式基于时间戳的协议基于时间戳协议的正确性基于有效性检…

解决:TypeError: write() argument must be str, not Tag

解决&#xff1a;TypeError: write() argument must be str, not Tag 文章目录 解决&#xff1a;TypeError: write() argument must be str, not Tag背景报错问题报错翻译报错位置代码报错原因解决方法今天的分享就到此结束了 背景 在使用之前的代码时&#xff0c;报错&#xf…

如何轻松解决企业报修系统问题?有什么比较实用的工单管理系统?

许多企业报修方面的问题就是兼职师傅多&#xff0c;难以管理&#xff0c;导致整个报修流程都比较滞后。关于这个问题&#xff0c;我个人的建议是引入工单管理系统&#xff0c;依靠线上平台进行统一的管理。 引入工单管理系统的好处主要有&#xff1a;   1、沟通报修更加高效 …

频率、概率

频率 在相同的条件下进行试验&#xff0c;假设试验进行了次&#xff0c;其中随机事件A发生了次&#xff0c;那么就称为随机事件A发生的频率。 概率 假设随机试验E的样本空间是S&#xff0c;对于其中每个随机事件&#xff0c;都对应了一个实数&#xff0c;把这个实数称为随机…

Qt/C++音视频开发59-使用mdk-sdk组件/原qtav作者力作/性能凶残/超级跨平台

一、前言 最近一个月一直在研究mdk-sdk音视频组件&#xff0c;这个组件是原qtav作者的最新力作&#xff0c;提供了各种各样的示例demo&#xff0c;不仅限于支持C&#xff0c;其他各种比如java/flutter/web/android等全部支持&#xff0c;性能上也是杠杠的&#xff0c;目前大概…

力扣每日一题day34[110. 平衡二叉树]

给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;t…

Linux学习第46天:Linux音频驱动试验:能不能?不行也得行。

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 CAN 是目前应用非常广泛的现场总线之一&#xff0c;主要应用于汽车电子和工业领域&#xff0c;尤其是汽车 领域&#xff0c;汽车上大量的传感器与模块都是通过 C…

【SpringBoot篇】详解基于Redis实现短信登录的操作

文章目录 &#x1f970;前言&#x1f6f8;StringRedisTemplate&#x1f339;使用StringRedisTemplate⭐常用的方法 &#x1f6f8;为什么我们要使用Redis代替Session进行登录操作&#x1f386;具体使用✨编写拦截器✨配置拦截器&#x1f33a;基于Redis实现发送手机验证码操作&am…

DNSLog漏洞探测(三)之XSS漏洞实战

DNSLog漏洞探测(三)之XSS漏洞实战 通过前面的学习&#xff0c;我们已经明白了什么是DNSLog平台&#xff0c;那么DNSLog平台到底能为我们做些什么呢&#xff1f; DNSLog的平台实际使用很长见的一种情况就是针对漏洞无回显的情况&#xff0c;我们通过让受害者的服务器主动发起对…

Error: Failed to resolve vue/compiler-sfc——vite项目启动报错——npm run serve

运行项目时&#xff0c;报错如下&#xff1a; Error: Failed to resolve vue/compiler-sfc 根据报错信息的提示&#xff1a;vue的版本必须大于3.2.25&#xff0c;经过查看package.json文件&#xff0c;可以看到vue的版本为3.2.36&#xff0c;是满足条件的。 因此考虑缓存问题&…

Python部分基础知识入门学习,十分钟快速上手

文章目录 一、基础语法二、变量类型三、运算符四、条件语句关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 一、…

并发编程的基本概念

进程与线程 进程 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至 CPU&#xff0c;数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的当一个程序被运行&…

【计算机网络】UDP报文详解

目录 一. UDP协议概述 二. UDP报文格式 1. 首部 2. 校验和 三. UDP的缓冲区 结束语 一. UDP协议概述 UDP——用户数据报协议&#xff0c;是传输层的一个重要协议 基于UDP的应用层协议有&#xff1a;DNS&#xff0c;TFTP&#xff0c;SNMP&#xff0c;NTP 协议全称默认端…

pt34-python-Celery

Celery异步网络框架 定义 Celery 是一个简单、灵活且可靠的&#xff0c;处理大量消息的分布式系统&#xff0c;它是一个专注于实时处理的任务队列&#xff0c;同时也支持任务调度。中文官网&#xff1a;http://docs.jinkan.org/docs/celery/ 在线安装 sudo pip3 install -U…