2024-07-02

# 前言

主要通过后端 Spring Boot 技术和前端 Vue 技术来简单开发一个demo,实现增删改查、分页功能以及了解Springboot搭配vue完成前后端分离项目的开发流程。

## 开发栈

### 前端

  - 开发工具:vscode

  - 开发框架:vue + axios

  - 包管理工具: npm

  - 打包工具:webpack

### 后端

  - 开发工具:IDEA

  - 开发框架:Springboot + mybatis

  - 打包工具:maven

  - 数据库:

## 后端开发环境搭建

1、File->New->Project...

![1.1.png](https://boostnote.io/api/teams/jcBLRsknW/files/95e968319c7d4547d59783aa7cd45b0bc2ec5ed6d42834455cafce3077346258-1.1.png)

2、选择 Spring Initializr ,然后选择默认的 url 点击next

![1.2.png](https://boostnote.io/api/teams/jcBLRsknW/files/d2e41073e32f89bf1d78595f910eab40d25353265720b58f95fcf4c3dfc8a952-1.2.png)

3、勾选Spring Web、SQL模板,next

![1.3.png](https://boostnote.io/api/teams/jcBLRsknW/files/4605ea72e08882785b4d95a7c7078c2e9f5e3bce55b203da37d16afea7e5ac2c-1.3.png)

4、点击finish,搭建完成

![1.4.png](https://boostnote.io/api/teams/jcBLRsknW/files/4011781ed6c5d9f705c99452ecc0a2651ff48fd0cd498a09e2fe5f6118e38147-1.4.png)

## 后端开发过程

### 后端框架

开发过程从底层数据库开始往上编程

![后端框架.png](https://boostnote.io/api/teams/jcBLRsknW/files/1dad06e395e2cb8b295f466b6810d90810727dd5da60ca69a35e586bb621b467-%E5%90%8E%E7%AB%AF%E6%A1%86%E6%9E%B6.png)

1、更新pom.xml如下:

先导入项目相应的依赖:数据库:jdbc、mysql dever;网页:web

```

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>

    <artifactId>demo</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <name>springboot-mybatis</name>

    <!-- Spring Boot 启动父依赖 -->

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>2.1.3.RELEASE</version>

    </parent>

    <properties>

        <mybatis-spring-boot>1.2.0</mybatis-spring-boot>

        <mysql-connector>5.1.39</mysql-connector>

    </properties>

    <dependencies>

        <!-- Spring Boot Web 依赖 -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

        <!-- Spring Boot Test 依赖 -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-test</artifactId>

            <scope>test</scope>

        </dependency>

        <!-- Spring Boot Mybatis 依赖 -->

        <dependency>

            <groupId>org.mybatis.spring.boot</groupId>

            <artifactId>mybatis-spring-boot-starter</artifactId>

            <version>${mybatis-spring-boot}</version>

        </dependency>

        <!-- MySQL 连接驱动依赖 -->

        <dependency>

            <groupId>mysql</groupId>

            <artifactId>mysql-connector-java</artifactId>

            <version>${mysql-connector}</version>

        </dependency>

        <!-- Junit -->

        <dependency>

            <groupId>junit</groupId>

            <artifactId>junit</artifactId>

            <version>4.12</version>

        </dependency>

    </dependencies>

</project>

```

2、先在properties文件中添加数据库链接,更新demo\src\main\resources\application.properties

```

## 数据源配置

##//jdbc.mysql://是指JDBC连接方式, JDBC就是用于在Java语言编程中与数据库连接的API;localhost:是指你的本机IP地址Q,在本地等同于127.0.0.1.3306 :数据库所使用的端口号默认3306;study:就是你要连接的数据库的地址(后面如果为jdbc、 test则同理)JDBC代表Java数据库连接Q (Java Database Connectivity)

spring.datasource.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf8

spring.datasource.username=root

spring.datasource.password=123

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

## Mybatis 配置

mybatis.typeAliasesPackage=org.spring.springboot.domain

mybatis.mapperLocations=classpath:mapper/*.xml

## 端口

server.port=8081

```

3、根据数据库中的表格形式建立相应实体类,新建 demo\src\main\java\com\example\demo\entity\User.java

```

package com.example.entity;

import lombok.Data;

@Data//@Data注解的主要作用是提高代码的简洁,使用这个注解可以省去实体类中大量的get()、 set()、 toString()等方法。

public class User {

    private int userId;

    private String userDate;

    private String userName;

    private String userAddress;

    //省略get() and set()

}

```

4、实体类写完后,创建mapper文件夹(dao层(也叫mapper层或持久层)mapper层是操作数据库的一层。想要访问数据库并且操作,只能通过mapper层向数据库发送sql语句,将这些通过接口传给service层,对数据库进行操作。新建demo\src\main\java\com\example\demo\mapper\UserMapper.java

```

package com.example.mapper;

import com.example.entity.User;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper//@Mapper注解用于标识个接口是mybatis的Mapper接口, Spring会自动扫描这个注解并将其实例化为一个Mapper对象,从而可以在代码中直接使用Mapper接口中定义的方法来操作数据库。

public interface UserMapper {

    public List<User> findUserByName(String userName);

    public List<User> ListUser();//这里ListUser是定义的方法

    public List<User> queryPage(Integer startRows);

    public int getRowCount();

    public int insertUser(User user);

    public int delete(int userId);

    public int Update(User user);

}

```

5、新建demo\src\main\resources\mapper\UserMapper.xml

```

<?xml version = "1.0" encoding = "UTF-8"?>

<!DOCTYPE mapper PUBLIC

        "-//mybatis.org//DTD com.example.Mapper 3.0//EN"

        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.mapper.UserMapper">

    <resultMap id="result" type="com.example.entity.User">

        <result property="userId" column="userId" />

        <result property="userDate" column="userDate" />

        <result property="userName" column="userName" />

        <result property="userAddress" column="userAddress"/>

    </resultMap>

    <select id="ListUser" resultMap="result">

        SELECT * FROM user

    </select>

    <select id="findUserByName" resultMap="result" parameterType="String">

        SELECT * FROM user

        where userName like concat(concat('%',#{userName}),'%')

        order by userId desc

    </select>

    <select id="queryPage" resultMap="result"  parameterType="Integer">

        select * from user

        order by userId desc

            limit #{startRows},5

    </select>

    <select id="getRowCount" resultType="Integer">

        select count(*) from user

    </select>

    <insert id="insertUser" parameterType="com.example.entity.User">

        INSERT INTO user

        (

            userId,userDate,userName,userAddress

        )

        VALUES (

                  #{userId},

                  #{userDate, jdbcType=VARCHAR},

                  #{userName, jdbcType=VARCHAR},

                  #{userAddress, jdbcType=VARCHAR}

              )

    </insert>

    <delete id="delete" parameterType="int">

        delete from user where userId=#{userId}

    </delete>

    <update id="Update" parameterType="com.example.entity.User">

        update user

        set user.userDate=#{userDate},user.userName=#{userName},user.userAddress=#{userAddress}

        where user.userId=#{userId}

    </update>

</mapper>

```

6、新建demo\src\main\java\com\example\demo\service\UserService.java

```

package com.example.service;

import com.example.entity.User;

import com.example.mapper.UserMapper;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;

import org.springframework.stereotype.Service;

import java.util.List;

@Service//@Service注解用于告诉Spring容器,被注解的类是一个服务类。它是Spring框架中的一个组件扫描注解,用于自动扫描并创建实例,以便在应用程序中使用。

public class UserService {

    @Autowired//在需要进行依赖注入的类中, 使用 @Autowired 注解来标记需要注入的成员变量、构造函数或者方法。

    private UserMapper userMapper;

    public List<User> findByName(String userName) {

        return userMapper.findUserByName(userName);

    }//findByName是用于相应前端的方法,findUserByName是用于调用数据库sql语句的方法

    public List<User> queryPage(Integer startRows) {

        return userMapper.queryPage(startRows);

    }

    public int getRowCount() {

        return userMapper.getRowCount();

    }

    public User insertUser(User user) {

        userMapper.insertUser(user);

        return user;

    }

    public List<User> ListUser(){

        return userMapper.ListUser();

    }

    public int Update(User user){

        return userMapper.Update(user);

    }

    public int delete(int userId){

        return userMapper.delete(userId);

    }

}

```

7、新建demo\src\main\java\com\example\demo\controller\UserCtrl.java

```

package com.example.controller;

import com.example.entity.User;

import com.example.service.UserService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;

import org.springframework.web.bind.annotation.*;

import java.util.List;

@EnableAutoConfiguration//@EnableAutoConfiguration 注解是用来启动 Spring 应用程序上下文时进行自动配置,它会尝试猜测和配置项目可能需要的 Bean

@RestController@//具体来说,@RestController注解用于标记一个类,表明该类是一个控制器,并且其下的方法都将返回数据作为响应。使用@RestController注解时,不再需要在方法上添加@ResponseBody注解,因为@RestController默认将所有方法的返回值自动序列化为响应体。

public class UserCtrl {

    @Autowired

    private UserService userservice;

    @RequestMapping(value = "@/delete", method = RequestMethod.POST)

    public Integer delete(Integer userId) {

        System.out.println(userId);

        int result = userservice.delete(userId);

        return result;

    }

    @RequestMapping(value = "@/update", method = RequestMethod.POST)

    @ResponseBody

    public String update(User user) {

        int result = userservice.Update(user);

        if (result >= 1) {

            return "修改成功";

        } else {

            return "修改失败";

        }

    }

    @RequestMapping(value = "@/insert", method = RequestMethod.POST)

    public User insert(User user) {

        return userservice.insertUser(user);

    }

    @RequestMapping("@/ListUser")

    @ResponseBody

    public List<User> ListUser() {

        return userservice.ListUser();

    }

    @RequestMapping("@/ListByName")

    @ResponseBody

    public List<User> ListUserByName(String userName) {

        return userservice.findByName(userName);

    }

    /**

    * 分页

    * @return

    */

    @RequestMapping(value="@/page")

    @ResponseBody

    public List<User> page(Integer page){

        int pageNow = page == null ? 1 : page;

        int pageSize = 5;

        int startRows = pageSize*(pageNow-1);

        List<User> list = userservice.queryPage(startRows);

        return list;

    }

    /**

    * rows

    * @return

    */

    @RequestMapping(value="@/rows")

    @ResponseBody

    public int rows(){

        return userservice.getRowCount();

    }

}

```

8、启动MySQL数据库,新建或执行如下表:

![1.5.png](https://boostnote.io/api/teams/jcBLRsknW/files/2e58a40bef8567707fdb6b3f58fc4d990e9be192deb4658e484a173639eab67b-1.5.png)

9、执行sql文件

```

SET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------

-- Table structure for user

-- ----------------------------

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user`  (

  `userId` int(20) NOT NULL AUTO_INCREMENT,

  `userDate` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

  `userName` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

  `userAddress` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

  PRIMARY KEY (`userId`) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 71 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------

-- Records of user

-- ----------------------------

INSERT INTO `user` VALUES (15, '2019-09-29T03:17:12.000Z', '王老三', '上海市普陀区金沙江路 1515 弄');

INSERT INTO `user` VALUES (16, '2019-09-29T03:27:05.000Z', '张小四', '上海市普陀区金沙江路 1514 弄');

INSERT INTO `user` VALUES (17, '2019-09-29T03:30:04.000Z', '王老五', '上海市普陀区金沙江路 1513弄');

INSERT INTO `user` VALUES (18, '2019-09-29T03:33:15.000Z', '小六子', '上海市普陀区金沙江路 1512弄');

INSERT INTO `user` VALUES (20, '2019-09-29T03:33:15.000Z', '王老八', '上海市普陀区金沙江路 1512弄');

INSERT INTO `user` VALUES (21, '2019-09-29T05:42:52.000Z', '王大拿', '上海市普陀区金沙江路 1511弄');

INSERT INTO `user` VALUES (22, '2019-09-29T05:43:50.000Z', '小九九', '上海市普陀区金沙江路 1510弄');

INSERT INTO `user` VALUES (23, '2019-09-29T05:43:50.000Z', '刘诗诗', '上海市普陀区金沙江路 1499弄');

INSERT INTO `user` VALUES (24, '2019-09-29T05:46:07.000Z', '扎昂四四', '上海市大湾区科技路');

INSERT INTO `user` VALUES (25, '2019-09-29T05:46:07.000Z', '扎昂四四新东方', '上海市大湾区科技路2001号');

INSERT INTO `user` VALUES (26, '2019-09-29T05:46:07.000Z', '王小虎', '上海市大湾区科技路2002号');

INSERT INTO `user` VALUES (27, '2019-09-29T05:46:07.000Z', '抽拉吧唧', '上海市大湾区科技路2003号');

INSERT INTO `user` VALUES (28, '2019-09-29T05:46:07.000Z', '年啦编辑', '上海市大湾区科技路2004号');

INSERT INTO `user` VALUES (29, '2019-09-29T05:46:07.000Z', '你多少', '上海市普陀区金沙江路 1211弄');

INSERT INTO `user` VALUES (30, '2019-09-29T05:46:07.000Z', '反发达', '上海市普陀区金沙江路 1212弄');

INSERT INTO `user` VALUES (31, '2019-09-29T05:51:20.000Z', '发官方', '上海市普陀区金沙江路 1213弄');

INSERT INTO `user` VALUES (32, '2019-09-29T05:51:20.000Z', '方还有', '上海市普陀区金沙江路 1214弄');

INSERT INTO `user` VALUES (33, '2019-09-29T05:51:20.000Z', '过不分', '上海市普陀区金沙江路 1498弄');

INSERT INTO `user` VALUES (34, '2019-09-29T05:51:20.000Z', '菜市场', '上海市普陀区金沙江路 1497弄');

INSERT INTO `user` VALUES (35, '2019-09-29T05:51:20.000Z', '权威的', '上海市普陀区金沙江路 1496弄');

INSERT INTO `user` VALUES (36, '2019-09-29T05:55:09.000Z', '冈反对的', '上海市大湾区科技路2001号');

INSERT INTO `user` VALUES (37, '2019-09-29T05:55:09.000Z', '冈反对', '上海市大湾区科技路2003号');

INSERT INTO `user` VALUES (38, '2019-09-29T05:55:09.000Z', '偶哦里面', '上海市大湾区科技路2004号');

INSERT INTO `user` VALUES (39, '2019-09-29T05:55:09.000Z', '偶哦韩大苏打', '上海市大湾区科技路2005号');

INSERT INTO `user` VALUES (40, '2019-09-29T05:55:09.000Z', '偶哦匀', '上海市大湾区科技路2006号');

INSERT INTO `user` VALUES (41, '2019-09-29T05:55:09.000Z', '敢哦匀', '上海市大湾区科技路2006号');

INSERT INTO `user` VALUES (42, '2019-09-29T05:55:09.000Z', '敢孩', '上海市大湾区科技路2006号');

INSERT INTO `user` VALUES (43, '2019-09-29T05:55:09.000Z', '敢女孩', '上海市大湾区科技路2007号');

INSERT INTO `user` VALUES (45, '2019-09-29T05:55:09.000Z', '工行行', '上海市大湾区科技路2008号');

INSERT INTO `user` VALUES (46, '2019-09-29T05:55:09.000Z', '家好吗', '上海市大湾区科技路2008号');

INSERT INTO `user` VALUES (47, '2019-09-29T05:55:09.000Z', '的程度', '上海市大湾区科技路2009号');

INSERT INTO `user` VALUES (48, '2019-09-29T05:55:09.000Z', '称得上', '上海市大湾区科技路2009号');

INSERT INTO `user` VALUES (49, '2019-09-29T05:55:09.000Z', '韩国和', '上海市大湾区科技路2010号');

INSERT INTO `user` VALUES (50, '2019-09-29T05:55:09.000Z', '韩好', '上海市大湾区科技路2010号');

INSERT INTO `user` VALUES (51, '2019-09-29T05:55:09.000Z', '韩吧', '上海市大湾区科技路2011号');

INSERT INTO `user` VALUES (52, '2019-09-29T05:55:09.000Z', '韩吧吧', '上海市大湾区科技路2012号');

INSERT INTO `user` VALUES (53, '2019-09-29T05:55:09.000Z', '长度是', '上海市大湾区科技路2013号');

INSERT INTO `user` VALUES (54, '2019-09-29T05:55:09.000Z', '比如合', '上海市大湾区科技路2014号');

INSERT INTO `user` VALUES (55, '2019-09-29T05:55:09.000Z', '如合境', '上海市大湾区科技路2015号');

INSERT INTO `user` VALUES (56, '2019-09-29T05:55:09.000Z', '如合国', '上海市大湾区科技路2016号');

INSERT INTO `user` VALUES (57, '2019-09-29T05:55:09.000Z', '如更好', '上海市大湾区科技路2017号');

INSERT INTO `user` VALUES (58, '2019-09-29T05:55:09.000Z', '如更法', '上海市大湾区科技路2018号');

INSERT INTO `user` VALUES (59, '2019-09-29T05:55:09.000Z', '反对', '上海市大湾区科技路2019号');

INSERT INTO `user` VALUES (60, '2019-09-29T05:55:09.000Z', '如国部', '上海市大湾区科技路2019号');

INSERT INTO `user` VALUES (61, '2019-09-29T06:04:15.000Z', '奇热网', '上海市普陀区金沙江路 1496弄');

INSERT INTO `user` VALUES (62, '2019-09-29T06:04:33.000Z', '反对法', '上海市普陀区金沙江路 1495弄');

INSERT INTO `user` VALUES (63, '2019-09-29T06:04:33.000Z', '的风格', '上海市普陀区金沙江路 1494弄');

INSERT INTO `user` VALUES (64, '2019-09-29T06:04:33.000Z', '广泛同', '上海市大湾区科技路2020号');

INSERT INTO `user` VALUES (65, '2019-09-10T06:04:33.000Z', '但仍然', '上海市普陀区金沙江路 1493弄');

INSERT INTO `user` VALUES (66, '2019-09-29T06:10:28.000Z', 'vdfv', '放到电饭锅的');

INSERT INTO `user` VALUES (67, '2019-09-14T16:00:00.000Z', '朱老六', '上海市高新区上海中心');

INSERT INTO `user` VALUES (69, '2019-09-10T16:00:00.000Z', '是的', ' 学生的三十四分');

INSERT INTO `user` VALUES (70, '2019-09-29T07:51:44.000Z', '张小子', '上海市浦东区1234号');

SET FOREIGN_KEY_CHECKS = 1;

```

9、后端就写完了,页面展示如下

![1.6.png](https://boostnote.io/api/teams/jcBLRsknW/files/38b694795664f145e22152b5c36c31442b2ac0d321463c4913afb3c6017dee8c-1.6.png)

10、run 'DemoApplication'启动项目,控制台没报错就用浏览器测试一下,在浏览器中输入http://localhost:8081/page?page=3 如果能出现如下字符串就👌,已安装postman的可以每个方法都试一下:

## 前端开发环境搭建

1、win+R->cmd->进入项目目录依次执行命令:vue init webpack projectName、cd projectName、npm install、npm run dev如图所示:

![1.7.png](https://boostnote.io/api/teams/jcBLRsknW/files/e8784f5c80c2313f7c621b01345f96832e2d31a0d65bc18364ed840128b3d331-1.7.png)

2、打开浏览器输入:http://localhost:8080,效果如图:

![1.8.png](https://boostnote.io/api/teams/jcBLRsknW/files/72083815255b3590dbcf7ff9431611f17edc8fe339e2d23699d8df783b2d6b45-1.8.png)

3、Vue-cli项目结构如图:

![1.9.png](https://boostnote.io/api/teams/jcBLRsknW/files/253acb2030ec8d862306c757585e70902c2cfbbc43975f725742d8b88e600885-1.9.png)

## 前端开发过程

### 创建前端项目后,项目首先从根组件App.vue开始执行,

- 在App.vue中的<template>...</template>使用 <router-view/> 来显示当前路由匹配到的组件。

- 在你的 main.js 文件中创建并挂载 Vue 应用,同时使用你配置的路由。

- 在router文件夹创建一个 router.js 文件,用于配置路由。

1、在项目根目录安装axios执行命令npm install axios,安装element ui 执行命令npm i element-ui -S 2、更新vue01\src\App.vue

```

<template>

  <div id="app">

    <el-row type="flex" justify="center">

      <el-col :xs="24" :sm="22" :md="20" :lg="20" :xl="18">

        <router-view/>

      </el-col>

    </el-row>

  </div>

</template>

<script>

    export default {

        name: 'App',

        data() {

            return {

            }

        },

        methods: {

        }

    }

</script>

<style>

  #app {

    font-family: 'Avenir', Helvetica, Arial, sans-serif;

    -webkit-font-smoothing: antialiased;

    -moz-osx-font-smoothing: grayscale;

    margin: 0px;

    padding: 0px;

  }

</style>

```

3、更新vue01\src\main.js

```

// The Vue build version to load with the `import` command

// (runtime-only or standalone) has been set in webpack.base.conf with an alias.

import Vue from 'vue'

import App from './App'

import router from './router'

import elementUI from 'element-ui'

import 'element-ui/lib/theme-chalk/index.css'

import 'element-ui/lib/theme-chalk/display.css'

Vue.use(elementUI)

import axios from 'axios'

Vue.prototype.axios = axios

import qs from 'qs';

Vue.prototype.qs = qs;

Vue.config.productionTip = false

/* eslint-disable no-new */

new Vue({

  el: '#app',

  router,

  components: { App },

  template: '<App/>'

})

```

4、更新vue01\src\components\HelloWorld.vue

```

<template>##template表示页面上所展示的功能

  <div>

      <el-form :inline="true" class="demo-form-inline">

          <el-form-item>

            <el-input

              v-model="search"

              class="search_name"

              size="mini"

              placeholder="输入姓名查询">

            </el-input>

          </el-form-item>

          <el-form-item>

            <el-button

              type="text"

              @click="onSearch()"

              class="el-icon-search">查询

            </el-button>

          </el-form-item>

          <el-form-item>

            <el-button

              class="el-icon-refresh"

              type="text"

              @click="refreshData">刷新

            </el-button>

          </el-form-item>

          <el-form-item>

            <el-button

              class="el-icon-circle-plus-outline"

              type="text"

              @click="dialogVisible = true">添加

            </el-button>

          </el-form-item>

      </el-form>

      <el-table

        :data="tableData"

        highlight-current-row

        border

        style="width: 100%">

        <el-table-column

          label="编号">

          <template slot-scope="scope">

            <span>{{ scope.row.userId }}</span>

          </template>

        </el-table-column>

        <el-table-column

          label="日期">

          <template slot-scope="scope">

            <i class="el-icon-time hidden-sm-and-down"></i>

            <span>{{ scope.row.userDate }}</span>

          </template>

        </el-table-column>

        <el-table-column

          label="姓名">

          <template slot-scope="scope">

            <el-popover trigger="hover" placement="right">

              <p>姓名: {{ scope.row.userName }}</p>

              <p>住址: {{ scope.row.userAddress }}</p>

              <p>日期:{{ scope.row.userDate }}</p>

              <div slot="reference" class="name-wrapper">

                <el-button type="text">{{ scope.row.userName }}</el-button>

              </div>

            </el-popover>

          </template>

        </el-table-column>

        <el-table-column

          label="住址">

          <template slot-scope="scope">

            <span>{{ scope.row.userAddress }}</span>

          </template>

        </el-table-column>

        <el-table-column

          label="操作"

          fixed="right"

          width="200">

          <template slot-scope="scope">

            <el-button

              size="mini"

              icon="el-icon-edit"

              @click="handleEdit(scope.$index, scope.row)">编辑

            </el-button>

            <el-button

              size="mini"

              type="danger"

              icon="el-icon-delete"

              @click="handleDelete(scope.$index, scope.row)">删除

            </el-button>

          </template>

        </el-table-column>

      </el-table>

      <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="70px" class="demo-ruleForm" size="medium">

        <el-dialog

          title="添加"

          :append-to-body='true'

          :visible.sync="dialogVisible"

          width="80%"

          :before-close="handleClose">

          <el-input type="hidden" v-model="ruleForm.userId"/>

          <el-form-item label="时间" prop="userDate">

            <el-date-picker type="datetime" placeholder="选择日期" v-model="ruleForm.userDate" style="width: 100%;"></el-date-picker>

          </el-form-item>

          <el-form-item label="姓名" prop="userName">

            <el-input v-model="ruleForm.userName"></el-input>

          </el-form-item>

          <el-form-item label="住址" prop="userAddress">

            <el-input v-model="ruleForm.userAddress"></el-input>

          </el-form-item>

          <span slot="footer" class="dialog-footer">

            <el-button @click="cancel()" size="medium">取 消</el-button>

            <el-button @click="addUser()" type="primary" size="medium">确 定</el-button>

          </span>

        </el-dialog>

      </el-form>

    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="70px" class="demo-ruleForm" size="medium">

      <el-dialog

        title="编辑"

        :append-to-body='true'

        :visible.sync="dialogUpdate"

        width="80%"

        :before-close="handleClose">

        <el-input type="hidden" v-model="ruleForm.userId"/>

        <el-form-item label="时间" prop="userDate">

          <el-date-picker type="datetime" placeholder="选择日期" v-model="ruleForm.userDate" style="width: 100%;"></el-date-picker>

        </el-form-item>

        <el-form-item label="姓名" prop="userName">

          <el-input v-model="ruleForm.userName"></el-input>

        </el-form-item>

        <el-form-item label="住址" prop="userAddress">

          <el-input v-model="ruleForm.userAddress"></el-input>

        </el-form-item>

        <span slot="footer" class="dialog-footer">

            <el-button @click="cancel()" size="medium">取 消</el-button>

            <el-button @click="updateUser()" type="primary" size="medium">确 定</el-button>

          </span>

      </el-dialog>

    </el-form>

      <br>

      <div class="pages">

        <el-pagination

          background

          :disabled = "disablePage"

          :current-page.sync="currentPage"

          small

          layout="prev, pager, next"

          :page-size="pageSize"

          :total="total"

          @current-change="handleCurrentChange">

        </el-pagination>

      </div>

  </div>

</template>

<script>

    export default {

        data() {

            return {

                ruleForm: {

                    userId: '',

                    userName: '',

                    userDate: '',

                    userAddress: ''

                },

                rules: {

                    userName: [

                        { required: true, message: '请输入姓名', trigger: 'blur' },

                        { min: 2, max: 7, message: '长度在 2 到 7 个字符', trigger: 'blur' }

                    ],

                    userAddress: [

                        { required: true, message: '请输入住址', trigger: 'blur' },

                        { min: 5, message: '长度大于 5 个字符', trigger: 'blur' }

                    ],

                },

                tableData: [],

                search: '',

                dialogVisible: false,

                dialogUpdate: false,

                pageSize: 5,

                currentPage: 1,

                total: 0,

                disablePage: false

            }

        },

        methods: {

            handleEdit(index, row) {

                this.dialogUpdate = true;

                this.ruleForm = Object.assign({}, row); //这句是关键!!!

            },

            handleDelete(index, row) {

                console.log(index, row);

                this.$confirm('删除操作, 是否继续?', '提示', {

                    confirmButtonText: '确定',

                    cancelButtonText: '取消',

                    type: 'warning'

                }).then(() => {

                    let postData = this.qs.stringify({

                        userId: row.userId,

                    });

                    this.axios({

                        method: 'post',

                        url:'/delete',

                        data:postData

                    }).then(response =>

                    {

                        this.getPages();

                        this.currentPage = 1;

                        this.axios.post('/page').then(response =>

                        {

                            this.tableData = response.data;

                        }).catch(error =>

                        {

                            console.log(error);

                        });

                        this.$message({

                            type: 'success',

                            message: '删除成功!'

                        });

                        console.log(response);

                    }).catch(error =>

                    {

                        console.log(error);

                    });

                }).catch(() => {

                    this.$message({

                        type: 'info',

                        message: '已取消删除'

                    });

                });

            },

            handleClose(done) {

                this.$confirm('确认关闭?')

                    .then(_ => {

                        done();

                    })

                    .catch(_ => {});

            },

            handleCurrentChange() {

                console.log(`当前页: ${this.currentPage}`);

                let postData = this.qs.stringify({

                    page: this.currentPage

                });

                this.axios({

                    method: 'post',

                    url:'/page',

                    data:postData

                }).then(response =>

                {

                    this.tableData = response.data;

                }).catch(error =>

                {

                    console.log(error);

                });

            },

            cancel() {

                this.dialogUpdate = false;

                this.dialogVisible = false;

                this.emptyUserData();

            },

            emptyUserData(){

                this.ruleForm = {

                    userName: '',

                    userDate: '',

                    userAddress: ''

                }

            },

            addUser() {

                let postData = this.qs.stringify({

                    userDate: this.ruleForm.userDate,

                    userName: this.ruleForm.userName,

                    userAddress: this.ruleForm.userAddress

                });

                this.axios({

                    method: 'post',

                    url:'/insert',

                    data:postData

                }).then(response =>

                {

                    this.axios.post('/page').then(response =>

                    {

                        this.tableData = response.data;

                        this.currentPage = 1;

                        this.$message({

                            type: 'success',

                            message: '已添加!'

                        });

                    }).catch(error =>

                    {

                        console.log(error);

                    });

                    this.getPages();

                    this.dialogVisible = false

                    console.log(response);

                }).catch(error =>

                {

                    console.log(error);

                });

            },

            updateUser() {

                let postData = this.qs.stringify({

                    userId: this.ruleForm.userId,

                    userDate: this.ruleForm.userDate,

                    userName: this.ruleForm.userName,

                    userAddress: this.ruleForm.userAddress

                });

                this.axios({

                    method: 'post',

                    url:'/update',

                    data:postData

                }).then(response =>

                {

                    this.handleCurrentChange();

                    this.cancel();

                    this.$message({

                        type: 'success',

                        message: '更新成功!'

                    });

                    console.log(response);

                }).catch(error =>

                {

                    this.$message({

                        type: 'success',

                        message: '更新失败!'

                    });

                    console.log(error);

                });

            },

            onSearch() {

                let postData = this.qs.stringify({

                    userName: this.search

                });

                this.axios({

                    method: 'post',

                    url: '/ListByName',

                    data: postData

                }).then(response =>

                {

                    this.tableData = response.data;

                    this.disablePage = true;

                }).catch(error =>

                {

                    console.log(error);

                });

            },

            getPages() {

                this.axios.post('/rows').then(response =>

                {

                    this.total = response.data;

                }).catch(error =>

                {

                    console.log(error);

                });

            },

            refreshData() {

                location.reload();

            }

        },

        created() {

            /*this.axios.get('static/user.json').then(response =>

            {

                this.tableData = response.data.tableData;

                this.total = response.data.tableData.length;

                // console.log(JSON.parse(JSON.stringify(response.data))['tableData'])

            });*/

            this.axios.post('/page').then(response =>

            {

                this.tableData = response.data;

            }).catch(error =>

            {

                console.log(error);

            });

            this.axios.post('/rows').then(response =>

            {

                this.total = response.data;

            }).catch(error =>

            {

                console.log(error);

            });

        },

    }

</script>

<style scoped>

  .search_name{

    width: 200px;

  }

  .pages{

    margin: 0px;

    padding: 0px;

    text-align: right;

  }

</style>

```

## 前后端整合

在vue01\config\index.js文件中配置proxyTable{},如下:

```

proxyTable: {

      '/': {

        target:'http://localhost:8081', // 你请求的第三方接口

        changeOrigin:true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题

        pathRewrite:{  // 路径重写,

          '^/': ''  // 替换target中的请求地址

        }

      }

    },

```

## 实现效果

![1.10.png](https://boostnote.io/api/teams/jcBLRsknW/files/36153d63be2c938d0f310709059757cc3670901a4dc6dcdc7107ee139bd9e267-1.10.png)

![1.11.png](https://boostnote.io/api/teams/jcBLRsknW/files/9823bd641584e5d267fe7c357a051b3b1308fec0b40186bc8ad7f05ef01cb798-1.11.png)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 序号文章作者发布日期1干货!一篇说尽Excel常见函数用法[https://www.jianshu.com/p/c...
    中年大叔阅读 406评论 1 38
  • 十九期3T培训感悟 第一感悟:如何挖掘需求,经过这次3T培训,了解到了六大类的用户需求,也是农资即将面对的趋势,这...
    北方公司吉林大区杨晓康阅读 35评论 0 0
  • 我的无偿献血之旅 我的无偿献血是从一次偶然开始的。正是这次偶然献血,开启了我多年的献血历程。 那天下午,我在常熟市...
    9278dc621000阅读 22评论 0 0
  • 介绍 MGR 是MySQL 是数据库未来发展的一个重要方向 引擎 2.3 设置hostname和ip映射 1 )...
    西南蔡徐坤阅读 719评论 0 0
  • 以前上班开心是因为每天知道自己要干什么可以干什么,现在不开心是因为每天不知道自己要什么,东一榔头西一勺子,想起什么...
    张奉哲阅读 34评论 0 1