尚硅谷谷粒学院学习笔记4--前端知识总结,讲师列表前端实现

es6和vue基础知识点

es6语法新特性博客链接
vue基础知识点博客链接
axios博客链接
npm,webpack博客链接

vue-element-admin

而vue-element-admin是基于element-ui 的一套后台管理系统集成方案。

功能:https://panjiachen.github.io/vue-element-admin-site/zh/guide/#功能

GitHub地址:https://github.com/PanJiaChen/vue-element-admin

项目在线预览:https://panjiachen.gitee.io/vue-element-admin

安装

# 解压压缩包
# 进入目录
cd vue-element-admin-master


# 安装依赖
npm install

# 启动。执行后,浏览器自动弹出并访问http://localhost:9527/
npm run dev

vue-admin-template

ueAdmin-template是基于vue-element-admin的一套后台管理系统基础模板(最少精简版),可作为模板进行二次开发。

GitHub地址:https://github.com/PanJiaChen/vue-admin-template

建议:你可以在 vue-admin-template 的基础上进行二次开发,把 vue-element-admin当做工具箱,想要什么功能或者组件就去 vue-element-admin 那里复制过来

# 解压压缩包
# 进入目录
cd vue-admin-template-master

# 安装依赖
npm install

# 启动。执行后,浏览器自动弹出并访问http://localhost:9528/
npm run dev

前端项目的创建和基本配置

将vue-admin-template-master重命名为guli-admin

修改端口号

config/index.js中修改

port: 9528,

关闭语法检查

config/index.js中修改

useEslint: false

在这里插入图片描述

项目的目录结构


├── build // 构建脚本
├── config // 全局配置 
├── node_modules // 项目依赖模块
├── src //项目源代码
├── static // 静态资源
└── package.jspon // 项目信息和依赖配置
src 

├── api // 各种接口 
├── assets // 图片等资源 
├── components // 各种公共组件,非公共组件在各自view下维护 
├── icons //svg icon 
├── router // 路由表 
├── store // 存储 
├── styles // 各种样式 
├── utils // 公共工具,非公共工具,在各自view下维护 
├── views // 各种layout
├── App.vue //***项目顶层组件*** 
├── main.js //***项目入口文件***
└── permission.js //认证入口

运行项目

npm run dev

修改模拟登录

前端

config下的dev.env.js的 BASE_API的路径换成本地

module.exports = merge(prodEnv, {
    
    
  NODE_ENV: '"development"',
  // BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',

  BASE_API: '"http://localhost:8001"'
})

src/api/login.js的路径换成接口的路径

export function login(username, password) {
    
    
  return request({
    
    
    url: '/eduservice/user/login',
    method: 'post',
    data: {
    
    
      username,
      password
    }
  })
}

export function getInfo(token) {
    
    
  return request({
    
    
    url: '/eduservice/user/info',
    method: 'get',
    params: {
    
     token }
  })
}

export function logout() {
    
    
  return request({
    
    
    url: '/eduservice/user/logout',
    method: 'post'
  })
}

后端

EduLoginController

@RestController
@RequestMapping("/eduservice/user")
@Api(tags="登录管理")
@CrossOrigin
public class EduLoginController {
    
    

    //login
    @PostMapping("/login")
    public ResultVo login(){
    
    
        return ResultVo.ok().data("token","admin");
    }
    //info
    @GetMapping("/info")
    public  ResultVo info(){
    
    
        return ResultVo.ok().data("roles","[admin]").data("name","admin").data("avatar","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
    }
}

启动前端和后端

跨域问题

在这里插入图片描述

解决跨域问题

在接口上面添加

@CrossOrigin

讲师列表前端实现

创建路由页面

在src/views 下新建edu/teacher 文件夹
并新建 list.vue save.vue

在这里插入图片描述

list.vue

<template>

  <div class="app-container">
    讲师列表
  </div>
</template>

add.vue

<template>

  <div class="app-container">
    讲师添加
  </div>
</template>

添加路由

在src/router/index.js 添加

{
    
    
    path: '/teacher',
    component: Layout,
    redirect: '/teacher/table',
    name: '讲师管理',
    meta: {
    
     title: '讲师管理', icon: 'example' },
    children: [
      {
    
    
        path: 'list',
        name: '讲师列表',
        component: () => import('@/views/edu/teacher/list'),
        meta: {
    
     title: '讲师列表', icon: 'table' }
      },
      {
    
    
        path: 'save',
        name: '添加讲师',
        component: () => import('@/views/edu/teacher/save'),
        meta: {
    
     title: '添加讲师', icon: 'tree' }
      }
    ]
  },

定义teacher.js

在src/api下创建 edu/teacher.js

import request from '@/utils/request'

export default{
    
    

  //讲师列表(条件查询分页)
  //current 当前页 limit每页记录数  teacherQuery条件对象
  getTeacherListPage(current,limit,teacherQuery){
    
    
    return request({
    
    
      url: `/eduservice/teacher/pageTeacherCondition/${
      
      current}/${
      
      limit}`, //这里用的是es6的``不是单引号
      method: 'post',
      //teacherQuery条件对象,后端使用RequestBody获取数据
      //data表示把对象转换json进行传递到接口
      data: teacherQuery
    })
  }

}

初始化vue组件

src/views/edu/teacher/list.vue

<template>

  <div class="app-container">
    讲师列表
  </div>
</template>

<script>

//引入teacher.js
import teacher from '@/api/edu/teacher'
export default {
    
    
    //写核心代码
   data(){
    
      //定义变量和初始值
     return{
    
    
       
     }
   },
   created(){
    
    //页面渲染之前执行,一般调用methods定义的方法
     
   },
   methods:{
    
    //创建具体的方法,调用teacher.js定义的方法
       
   }
}
</script>

定义data

data(){
    
      //定义变量和初始值
     return{
    
    
       list:null, //查询之后接口返回的集合
       page:1, //当前页
       limit:10, //每页记录数
       total:0, //总记录数
       teacherQuery:{
    
    } //条件封装对象

     }

定义methods

methods:{
    
    //创建具体的方法,调用teacher.js定义的方法
        //讲师列表方法
        getList(){
    
    
          teacher.getTeacherListPage(this.page,this.limit,this.teacherQuery)
          .then(response =>{
    
    
              // console.log(response.data.rows)
              this.list=response.data.rows;
              this.total=response.data.total;
          })
          .catch(error => {
    
    
            console.log(error)//请求失败
          })
        }

   }

完整版

<template>

  <div class="app-container">
    讲师列表
  </div>
</template>

<script>

//引入teacher.js
import teacher from '@/api/edu/teacher'
export default {
    
    
    //写核心代码
   data(){
    
      //定义变量和初始值
     return{
    
    
       list:null, //查询之后接口返回的集合
       page:1, //当前页
       limit:10, //每页记录数
       total:0, //总记录数
       teacherQuery:{
    
    } //条件封装对象

     }
   },
   created(){
    
    //页面渲染之前执行,一般调用methods定义的方法
      this.getList()
   },
   methods:{
    
    //创建具体的方法,调用teacher.js定义的方法
        //讲师列表方法
        getList(){
    
    
          teacher.getTeacherListPage(this.page,this.limit,this.teacherQuery)
          .then(response =>{
    
    
              // console.log(response.data.rows)
              this.list=response.data.rows;
              this.total=response.data.total;
          })
          .catch(error => {
    
    
            console.log(error)//请求失败
          })
        }

   }
}
</script>

表格渲染

<!-- 表格 -->
    <el-table
      :data="list"
      border
      fit
      highlight-current-row>

      <el-table-column
        label="序号"
        width="70"
        align="center">
        <template slot-scope="scope">
          {
   
   { (page - 1) * limit + scope.$index + 1 }}
        </template>
      </el-table-column>

      <el-table-column prop="name" label="名称" width="80" />

      <el-table-column label="头衔" width="80">
        <template slot-scope="scope">
          {
   
   { scope.row.level===1?'高级讲师':'首席讲师' }}
        </template>
      </el-table-column>

      <el-table-column prop="intro" label="资历" />

      <el-table-column prop="gmtCreate" label="添加时间" width="160"/>

      <el-table-column prop="sort" label="排序" width="60" />

      <el-table-column label="操作" width="200" align="center">
        <template slot-scope="scope">
          <router-link :to="'/teacher/edit/'+scope.row.id">
            <el-button type="primary" size="mini" icon="el-icon-edit">修改</el-button>
          </router-link>
          <el-button type="danger" size="mini" icon="el-icon-delete" @click="removeDataById(scope.row.id)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

分页

<!-- 分页 -->
    <el-pagination
      :current-page="page" 
      :page-size="limit"
      :total="total"
      style="padding: 30px 0; text-align: center;"
      layout="total, prev, pager, next, jumper"
      @current-change="getList"/>

修改getList方法

因为默认current是1,只能查第一页,

methods:{
    
    //创建具体的方法,调用teacher.js定义的方法
        //讲师列表方法
        getList(page=1){
    
    
          this.page = page
          teacher.getTeacherListPage(this.page,this.limit,this.teacherQuery)
          .then(response =>{
    
    
              // console.log(response.data.rows)
              this.list=response.data.rows;
              this.total=response.data.total;
          })
          .catch(error => {
    
    
            console.log(error)//请求失败
          })
        }

   }

并且 @current-change=“getList”/>里面不要加参数,封装好了,会自己帮忙传

查询表单

注意:
element-ui的 date-picker组件默认绑定的时间值是默认世界标准时间,和中国时间差8小时
设置 value-format=“yyyy-MM-dd HH:mm:ss” 改变绑定的值

  <!--查询表单-->
    <el-form :inline="true" class="demo-form-inline">
      <el-form-item>
        <el-input v-model="teacherQuery.name" placeholder="讲师名"/>
      </el-form-item>

      <el-form-item>
        <el-select v-model="teacherQuery.level" clearable placeholder="讲师头衔">
          <el-option :value="1" label="高级讲师"/>
          <el-option :value="2" label="首席讲师"/>
        </el-select>
      </el-form-item>

      <el-form-item label="添加时间">
        <el-date-picker
          v-model="teacherQuery.begin"
          type="datetime"
          placeholder="选择开始时间"
          value-format="yyyy-MM-dd HH:mm:ss"
          default-time="00:00:00"
        />
      </el-form-item>
      <el-form-item>
        <el-date-picker
          v-model="teacherQuery.end"
          type="datetime"
          placeholder="选择截止时间"
          value-format="yyyy-MM-dd HH:mm:ss"
          default-time="00:00:00"
        />
      </el-form-item>

      <el-button type="primary" icon="el-icon-search" @click="getList()">查询</el-button>
      <el-button type="default" @click="resetData()">清空</el-button>
    </el-form>

清空功能

清空表单输入条件数据
查询所有的数据

	resetData(){
    
    
          //表单输入项数据清空
          this.teacherQuery={
    
    }
          //查询所有讲师数据
          this.getList();
        }

删除讲师

定义api

src/api/edu/teacher.js

 //删除讲师
  deleteTeacherById(id){
    
    
    return request({
    
    
      url: `/eduservice/teacher/${
      
      id}`, 
      method: 'delete'
    })
  }

定义methods

src/views/edu/teacher/list.vue
使用MessageBox 弹框组件

removeDataById(id){
    
    
             
            this.$confirm('此操作将永久删除讲师记录, 是否继续?', '提示', {
    
    
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
    
      //点击确定,执行then方法
                //调用删除的方法
               teacher.deleteTeacherById(id)
                    .then(response =>{
    
    //删除成功
                    //提示信息
                    this.$message({
    
    
                        type: 'success',
                        message: '删除成功!'
                    });
                    //回到列表页面
                    this.getList(this.page)
                })
            }) //点击取消,执行catch方法
        }

添加讲师

定义api

src/api/edu/teacher.js

//添加讲师
  addTeacher(teacher){
    
    
    return request({
    
    
      url:'/eduservice/teacher/addTeacher',
      method:'post',
      data: teacher
    })
  }

初始化组件

src/views/edu/teacher/save.vue

<template>
  <div class="app-container">
    讲师添加

    <el-form label-width="120px">
      <el-form-item label="讲师名称">
        <el-input v-model="teacher.name" />
      </el-form-item>
      <el-form-item label="讲师排序">
        <el-input-number
          v-model="teacher.sort"
          controls-position="right"
          :min="0"
        />
      </el-form-item>
      <el-form-item label="讲师头衔">
        <el-select v-model="teacher.level" clearable placeholder="请选择">
          <el-option :value="1" label="高级讲师" />
          <el-option :value="2" label="首席讲师" />
        </el-select>
      </el-form-item>
      <el-form-item label="讲师资历">
        <el-input v-model="teacher.career" />
      </el-form-item>
      <el-form-item label="讲师简介">
        <el-input v-model="teacher.intro" :rows="10" type="textarea" />
      </el-form-item>

      <!-- 讲师头像:TODO -->

      <el-form-item>
        <el-button
          :disabled="saveBtnDisabled"
          type="primary"
          @click="saveOrUpdate"
          >保存</el-button
        >
      </el-form-item>
    </el-form>
  </div>
</template>

js

<script>

import teacherApi from '@/api/edu/teacher'
export default {
    
    
  data(){
    
    
    return {
    
    
       teacher:{
    
    
        name: '',
        sort: 0,
        level: 1,
        career: '',
        intro: '',
        avatar: ''
       },
       saveBtnDisabled: false // 保存按钮是否禁用,
    }
  },
  created(){
    
    },

methods:{
    
    
     saveOrUpdate(){
    
    
       //添加
       this.saveTeacher()
     },
     //添加讲师的方法
     saveTeacher(){
    
    
       teacherApi.addTeacher(this.teacher)
       .then((response) => {
    
    
         //提示信息
          this.$message({
    
    
              type: 'success',
              message: '添加成功!'
          });

          //回到列表页面 ,路由跳转
          this.$router.push({
    
    path:'/teacher/list'})
       }).catch((err) => {
    
    
         
       });
     }
}
}
</script>

修改讲师

通过路由跳转数据回显页面,再由路由index页面添加路由,并且是隐藏路由
添加和修改是同一个页面

隐藏路由

:id 是占位符
hidden: true 是隐藏

{
    
    
        path: 'edit/:id',
        name: '修改讲师',
        component: () => import('@/views/edu/teacher/save'),
        meta: {
    
    
          title: '修改讲师',
          noCache: 'tree'
        },
        hidden: true
      }

路由跳转

<router-link :to="'/teacher/edit/'+scope.row.id">
            <el-button type="primary" size="mini" icon="el-icon-edit">修改</el-button>
</router-link>

数据回显

在表单页面实现数据回显
在 src/api/edu/teacher.js

getTeacherInfoById(id) {
    
    
    return request({
    
    
      url: `/eduservice/teacher/${
      
      id}`,
      method: 'get',

    })
  }

页面调用回显

因为添加和修改页面使用save页面
区别添加还是修改,只有修改时候查询数据回显

判断路径里面是否有讲师id值,如果有id值修改,没有id值直接添加

根据路径是否有id决定回显

 created() {
    
    
    //判断路径有id值,做修改
    if (this.$route.params && this.$route.params.id) {
    
    
      //从路径获取id值
      const id = this.$route.params.id;
      
      this.getInfo(id);
    }
    
  },

修改讲师

在 src/api/edu/teacher.js

//修改讲师
  updateTeacher(teacher) {
    
    
    return request({
    
    
      url: '/eduservice/teacher/updateTeacher',
      method: 'put',
      data: teacher
    })
  },
 updateTeacherInfo() {
    
    
      teacherApi
        .updateTeacher(this.teacher)
        .then((response) => {
    
    
          //提示信息
          this.$message({
    
    
            type: "success",
            message: "修改成功!",
          });

          //回到列表页面 ,路由跳转
          this.$router.push({
    
     path: "/teacher/list" });
        })
        .catch((err) => {
    
    });
    },

saveOrUpdate

saveOrUpdate() {
    
    
      //判断修改还是添加
      //根据teacher是否有id
      if (!this.teacher.id) {
    
    
        //添加
        this.saveTeacher();
      } else {
    
    
        //修改
        this.updateTeacherInfo();
      }
    }

问题bug

如果先点了讲师列表里面的修改,再点击添加讲师,会发现,数据回显还是会存在
表单页面还是现实修改回显的数据,正确 效果应该是表单数据清空

vue-router导航切换 时,如果两个路由都渲染同个组件,组件会重(chong)用,
组件的生命周期钩子(created)不会再被调用, 使得组件的一些数据无法根据 path的改变得到更新
因此:
1、我们可以在watch中监听路由的变化,当路由变化时,重新调用created中的内容
2、在init方法中我们判断路由的变化,如果是修改路由,则从api获取表单数据,
如果是新增路由,则重新初始化表单数据

完整版

<template>
  <div class="app-container">
    讲师添加

    <el-form label-width="120px">
      <el-form-item label="讲师名称">
        <el-input v-model="teacher.name" />
      </el-form-item>
      <el-form-item label="讲师排序">
        <el-input-number
          v-model="teacher.sort"
          controls-position="right"
          :min="0"
        />
      </el-form-item>
      <el-form-item label="讲师头衔">
        <el-select v-model="teacher.level" clearable placeholder="请选择">
          <el-option :value="1" label="高级讲师" />
          <el-option :value="2" label="首席讲师" />
        </el-select>
      </el-form-item>
      <el-form-item label="讲师资历">
        <el-input v-model="teacher.career" />
      </el-form-item>
      <el-form-item label="讲师简介">
        <el-input v-model="teacher.intro" :rows="10" type="textarea" />
      </el-form-item>

      <!-- 讲师头像:TODO -->

      <el-form-item>
        <el-button
          :disabled="saveBtnDisabled"
          type="primary"
          @click="saveOrUpdate"
          >保存</el-button
        >
      </el-form-item>
    </el-form>
  </div>
</template>


<script>
import teacherApi from "@/api/edu/teacher";
export default {
    
    
  data() {
    
    
    return {
    
    
      teacher: {
    
    
        name: "",
        sort: 0,
        level: 1,
        career: "",
        intro: "",
        avatar: "",
      },
      saveBtnDisabled: false, // 保存按钮是否禁用,
    };
  },

  watch: {
    
    
    $route(to, from) {
    
    
      this.init();
    },
  },
  created() {
    
    
    this.init();
  },

  methods: {
    
    
    init() {
    
    
      //判断路径有id值,做修改
      if (this.$route.params && this.$route.params.id) {
    
    
        //从路径获取id值
        const id = this.$route.params.id;

        this.getInfo(id);
      } else {
    
    
        //路径没有id值,做添加
        //清空表单
        this.teacher = {
    
    };
      }
    },

    //根据讲师id查询方法
    getInfo(id) {
    
    
      teacherApi.getTeacherInfoById(id).then((response) => {
    
    
        this.teacher = response.data.teacher;
      });
    },
    saveOrUpdate() {
    
    
      //判断修改还是添加
      //根据teacher是否有id
      if (!this.teacher.id) {
    
    
        //添加
        this.saveTeacher();
      } else {
    
    
        //修改
        this.updateTeacherInfo();
      }
    },
    //添加讲师的方法
    saveTeacher() {
    
    
      teacherApi
        .addTeacher(this.teacher)
        .then((response) => {
    
    
          //提示信息
          this.$message({
    
    
            type: "success",
            message: "添加成功!",
          });

          //回到列表页面 ,路由跳转
          this.$router.push({
    
     path: "/teacher/list" });
        })
        .catch((err) => {
    
    });
    },

    updateTeacherInfo() {
    
    
      teacherApi
        .updateTeacher(this.teacher)
        .then((response) => {
    
    
          //提示信息
          this.$message({
    
    
            type: "success",
            message: "修改成功!",
          });

          //回到列表页面 ,路由跳转
          this.$router.push({
    
     path: "/teacher/list" });
        })
        .catch((err) => {
    
    });
    },
  },
};
</script>

猜你喜欢

转载自blog.csdn.net/qq_44866153/article/details/120606035