Vue
Vue脚手架构建前后端分离项目小模块
一、用户列表搭建
- 构建前端项目
vue init webpack users
- 启动前端项目
进入user目录cd users
npm start
- 访问测试
http://localhost:8080/
- 前端项目搭建
main.js:↓
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'; //引入axios
Vue.prototype.$http=axios; //修改内部的$http为axios
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
components: {
App },
template: '<App/>'
})
App.vue:↓
<template>
<div id="app">
<a href="#/home">主页</a>
<a href="#/user">用户管理</a>
<a href="#/student">学生管理</a>
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style></style>
router/index.js:↓
import Vue from 'vue'
import Router from 'vue-router'
import Home from '../components/Home.vue'
import User from '../components/User.vue'
import Student from '../components/Student.vue' //引入组件
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',redirect:'/home'}, //默认路由
{
path:'/user',component: User},
{
path:'/Student',component: Student},
{
path:'/home',component: Home},//注册组件
]
})
components/Home.vue
.<template>
<div>
<h1>欢迎</h1>
</div>
</template>
<script>
export default {
name:'Home',
}
</script>
<style></style>
components/Student.vue
.<template>
<div>
<h1>学生列表</h1>
</div>
</template>
<script>
export default {
name:'Student',
}
</script>
<style></style>
components/User.vue
.<template>
<div>
<h1>用户列表</h1>
<table border="1">
<tr>
<td>id</td>
<td>姓名</td>
<td>年龄</td>
<td>生日</td>
<td>操作</td>
</tr>
<!-- 遍历数据 -->
<tr v-for="user in users">
<!-- 通过差值表达式获取数据 -->
<td>{
{user.id}}</td>
<td>{
{user.name}}</td>
<td>{
{user.age}}</td>
<td>{
{user.bir}}</td>
<td>
<a href="">删除</a>
<a href="">修改</a>
</td>
</tr>
</table>
<a href="">添加</a>
</div>
</template>
<script>
export default {
name:'User',
data() {
return {
users:[]
}
},
methods: {
},
components:{
},
created() {
let _this = this;
// 使用axios,发起异步请求,下面url地址通过RAP2来模拟后端接口
this.$http.get("http://rap2api.taobao.org/app/mock/277648/user/findAll").then(function(resp){
_this.users=resp.data.result
})
},
}
</script>
<style></style>
User.vue下面的aixos,老师推荐了一个前端测试,模拟后端接口的网址
http://rap2.taobao.org/
注册-登录-创建仓库-创建接口
生成的模拟请求:
http://rap2api.taobao.org/app/mock/277648/user/findAll
用于axios发送异步请求,获取后端的数据
- 项目布局
- 效果
二、用户添加
- 创建用户添加组件UserAdd.vue
.<template>
<div>
<h2>用户添加信息</h2>
<form action="">
用户名:<input type="text" v-model="user.name"><br>
年龄<input type="text" v-model="user.age"><br>
生日<input type="text" v-model="user.bir"><br>
<input type="button" @click="saveUserInfo" value="添加用户信息"/>
</form>
</div>
</template>
<script>
export default {
name:'UserAdd',//暴露组件
data() {
return {
user:{
},
}
},
methods: {
saveUserInfo(){
console.log(this);
//发送aixos请求
let _this= this;
this.$http.post("url",_this.user).then(function(resp){
})
}
},
}
</script>
<style></style>
- 注册组件router/index.js
添加到User组件下的,成为子组件
- 创建模拟接口
http://rap2api.taobao.org/app/mock/277648/user/add
- 测试saveUserInfo()函数,是否可以接收到接口返回的值
methods: {
saveUserInfo(){
console.log(this);
//发送aixos请求
let _this= this;
this.$http.post("http://rap2api.taobao.org/app/mock/277648/user/add",_this.user).then(function(resp){
console.log(resp);
})
}
},
- 加入切换路由功能
saveUserInfo(){
console.log(this);
//发送aixos请求
let _this= this;
this.$http.post("http://rap2api.taobao.org/app/mock/277648/user/add",_this.user).then(function(resp){
console.log(resp);
if(resp.data.success){
_this.$router.push("/user"); //切换路由
}
})
}
发现路由确实切换了,但是没有发起findAll查询所有的axios请求
- 给user.vue组件加入监听路由
watch:{
//用来监听
$route:{
handler: function(val,oldval){
//参数1:变化之后的路径 参数2:变化之前的路径
console.log(val);
},
//深度观察监听
deep: true
}
}
- 在监听器里面调用findAll()函数,之前是没这个函数的,将User.vue的created()生命周期函数里面的方法封装成findAll()放入User.vue的methods中
- 输完数据后点添加会路由切换成/user,并再发送一个findAll查询所有数据
因为接口的是模拟的,所以数据不可能更新
三、用户删除
- 创建虚拟删除接口
访问:http://rap2api.taobao.org/app/mock/277648/user/delete?id=1
delRow(id){
console.log(id);
let _this = this;
this.$http.get("http://rap2api.taobao.org/app/mock/277648/user/delete?id="+id).then(function(resp){
console.log(resp);
if(resp.data.success){
//判断数据是否已经删除
_this.findAll() //刷新页面,查询所有
}
});
}
四、用户修改
- 创建组件 UserEdit.vue
.<template>
<div>
<h2>修改用户信息</h2>
<form action="">
用户名:<input type="text"/> <br>
年龄: <input type="text"/> <br>
生日: <input type="text"/> <br>
<input type="button" value="添加" @click="UserEdit"/>
</form>
</div>
</template>
<script>
export default {
name:'UserEdit',
}
</script>
<style></style>
- 注册组件router/index.js
- User.vue
- 效果
- 获取另一个组件中的数据
获取到id后, 就可以根据id查询用户了,
- 创建虚拟findOne接口
访问:http://rap2api.taobao.org/app/mock/277648/user/findOne
- findOne()
findOne(){
let _this = this;
this.$http.get("http://rap2api.taobao.org/app/mock/277648/user/findOne?id="+this.user.id).then(function(resp){
console.log(resp.data);
_this.user=resp.data;
});
}
- 创建虚拟用户更新接口
地址:http://rap2api.taobao.org/app/mock/277648/user/edit
- UserEdit()
UserEdit(){
console.log(this);
//发送一个更新的请求
let _this = this;
this.$http.post("http://rap2api.taobao.org/app/mock/277648/user/edit",this.user).then(function(resp){
console.log(resp);
if(resp.data.success){
_this.$router.push("/user"); //切换路由
}
});
}
user组件他有watch来监听路由的切换
- UserEdit.vue组件
.<template>
<div>
<h2>修改用户信息</h2>
<form action="">
<!--通过v-model 来双向绑定数据,让修改框中的数据回显出来-->
用户名:<input v-model="user.name" type="text"/> <br>
年龄: <input v-model="user.age" type="text"/> <br>
生日: <input v-model="user.bir" type="text"/> <br>
<input type="button" value="添加" @click="UserEdit"/>
</form>
</div>
</template>
<script>
export default {
name:'UserEdit',
data() {
return {
user:{
id:'', //给user定义一个id属性
}
}
},
methods: {
UserEdit(){
console.log(this);
//发送一个更新的请求
let _this = this;
this.$http.post("http://rap2api.taobao.org/app/mock/277648/user/edit",this.user).then(function(resp){
console.log(resp);
if(resp.data.success){
_this.$router.push("/user"); //切换路由
}
});
},
findOne(){
let _this = this;
this.$http.get("http://rap2api.taobao.org/app/mock/277648/user/findOne?id="+this.user.id).then(function(resp){
console.log(resp.data);
_this.user=resp.data;
});
}
},
created(){
console.log("UserAdd组件 中获取的id:"+this.$route.query.id) //获取组件中的数据
this.user.id=this.$route.query.id //给user.id属性值赋值
this.findOne();
}
}
</script>
<style></style>
以上使用的模拟接口来实现的,
下面在将模拟的接口转换后端的接口
五、后台开发
- 新建数据库
使用之前的bootvue数据库
CREATE TABLE vue_user(
id INT(6) PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(40),
age INT(3),
bir datetime
)
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- application.yaml配置文件
spring:
application:
name: vue #项目名
datasource:
password: '00000'
username: 'root'
type: com.alibaba.druid.pool.DruidDataSource #使用Druid数据连接池
driver-class-name: com.mysql.jdbc.Driver #数据库驱动
url: jdbc:mysql://localhost:3306/bootvue?characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
server:
port: 6161
servlet:
context-path: /vue #项目路径
mybatis:
mapper-locations: classpath:com.achang.mapper/*.xml #指定sql映射文件位置
type-aliases-package: com.achang.entity #指定bean对象位置
- 项目整体布局
- 根据数据库新建entity实例
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true) //链式调用
public class User {
private Integer id;
private String name;
private Integer age;
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GTM+8")
//设置日期格式,pattern格式化格式,timezone时区:我们在东八区
private Date bir;
}
- dao/UserDao
@Mapper
public interface UserDao {
//保存
void save(User user);
//更新
void update(User user);
//删除
void delete(Integer id);
//查询所有
List<User> findAll();
//根据id,查询一个用户
User findById(Integer id);
}
- mapper/UserDaoMapper.xml
<mapper namespace="com.achang.dao.UserDao">
<!--接口如果有返回值就用resultType指明
接口没有返回值,但有传入参数就用parameterType指明
又有返回值,又有传入参数,就都用
-->
<!-- useGeneratedKeys="true"把新增加的主键赋值到自己定义的keyProperty(id)中 -->
<insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">
insert into vue_user
values(#{id},#{name},#{age},#{bir})
</insert>
<update id="update" parameterType="User">
update vue_user
set name=#{name},age=#{age},bir=#{bir}
where id = #{id}
</update>
<select id="findAll" resultType="User">
select id,name,age,bir from vue_user
</select>
<delete id="delete" parameterType="Integer">
delete from vue_user
where id = #{id}
</delete>
<select id="findById" parameterType="Integer" resultType="User">
select id,name,age,bir from vue_user
where id = #{id}
</select>
</mapper>
- service/UserService接口
public interface UserService {
//保存
void save(User user);
//更新
void update(User user);
//删除
void delete(Integer id);
//查询所有
List<User> findAll();
//根据id,查询一个用户
User findById(Integer id)
}
- impl/UserServiceImpl
@Service
@Transactional
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
@Override
public void save(User user) {
userDao.save(user);
}
@Override
public void update(User user) {
userDao.update(user);
}
@Override
public void delete(Integer id) {
userDao.delete(id);
}
@Override
public List<User> findAll() {
return userDao.findAll();
}
@Override
public User findById(Integer id) {
return userDao.findById(id);
}
}
- controller/UserController/findAll()查询所有方法
@RestController
@CrossOrigin //解决跨域问题
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
//查询所有
@GetMapping("/findAll")
public Map<String,Object> findAll(Integer page, Integer rows){
List<User> result = userService.findAll();
HashMap<String, Object> map = new HashMap<>();
map.put("total",1);
map.put("totalPage",1);
map.put("page",1);
map.put("result",result);
return map;
}
}
- 前端components/User.vue,findAll()查询所有用户
将之前的模拟接口修改为后端接口
findAll(){
//查询所有
let _this = this;
// 使用axios,发起异步请求,下面url地址通过RAP2来模拟后端接口
this.$http.get("http://localhost:6161/vue/user/findAll").then(function(resp){
_this.users=resp.data.result
})
}
- controller/UserController/add() 添加用户
//添加用户
@PostMapping("/add")
public Map<String,Object> add(@RequestBody User user){
HashMap<String, Object> map = new HashMap<>();
try {
userService.save(user);
map.put("success",true);
map.put("msg","添加成功");
} catch (Exception e) {
e.printStackTrace();
map.put("success",false);
map.put("msg","添加失败: "+e.getMessage());
}
return map;
}
- 前端components/UserAdd.vue,saveUserInfo()添加用户
saveUserInfo(){
console.log(this);
//发送aixos请求
let _this= this;
this.$http.post("http://localhost:6161/vue/user/add",_this.user).then(function(resp){
console.log(resp);
if(resp.data.success){
_this.$router.push("/user"); //切换路由
}
})
}
- controller/UserController /delete(),删除用户
//用户删除
@GetMapping("/delete")
public Map<String,Object> delete(Integer id){
HashMap<String, Object> map = new HashMap<>();
try {
userService.delete(id);
map.put("success",true);
map.put("msg","删除成功");
} catch (Exception e) {
e.printStackTrace();
map.put("success",false);
map.put("msg","删除失败: "+e.getMessage());
}
return map;
}
- 前端components/UserAdd.vue,delRow()删除用户
delRow(id){
console.log(id);
let _this = this;
this.$http.get("http://localhost:6161/vue/user/delete?id="+id).then(function(resp){
console.log(resp);
if(resp.data.success){
//判断数据是否已经删除
_this.findAll() //刷新页面,查询所有
}
});
}
- controller/UserController/findOne(),根据id获取用户
//根据id查询用户
@GetMapping("findOne")
public User finOne(Integer id){
return userService.findById(id);
}
- 前端components/UserEdit.vue,findOne()
findOne(){
let _this = this;
this.$http.get("http://localhost:6161/vue/user/findOne?id="+this.user.id).then(function(resp){
console.log(resp.data);
_this.user=resp.data;
});
}
- controller/UserController/edit(),修改用户
//修改用户
@PostMapping("/edit")
public Map<String,Object> edit(@RequestBody User user){
HashMap<String, Object> map = new HashMap<>();
try {
userService.update(user);
map.put("success",true);
map.put("msg","更新成功");
} catch (Exception e) {
e.printStackTrace();
map.put("success",true);
map.put("msg","感谢成功");
}
return map;
}
- 前端components/UserEdit.vue,UserEdit()
UserEdit(){
console.log(this);
//发送一个更新的请求
let _this = this;
this.$http.post("http://localhost:6161/vue/user/edit",this.user).then(function(resp){
console.log(resp);
if(resp.data.success){
_this.$router.push("/user"); //切换路由
}
});
}
六、项目打包&部署
package.json所在目录为项目根目录:
打包命令:npm run build
- 将dist文件夹CV到IDEA的static文件夹中
-
启动springboot主程序
-
访问:
localhost:6161/vue/index.html
发现页面白屏访问不了
- 去resources/static/dist/index.html
按Ctrl+shift+alt+L
格式化
- 再次访问,
localhost:6161/vue/index.html
- 测试功能
功能都可以使用