环境:jdk1.8、IDEA、Vue-Cli 2.0、Element-Ui
起步
在桌面创建一个Vue-Demo文件夹,cmd此文件夹进入Dos命令
vue init webpack 项目名
- project name :设置项目名(test)
- project description : 项目描述
- author : 作者
- install vue-router :是否安装路由模块,建议安装
- install eslint : 是否安装代码检测工具,建议安装
其他设置为no即可,脚手架的结构如下:
安装依赖模块命令
npm install --执行npm install的,node会从package.json文件读取模块名称,从package-lock.json文件中获取版本号
cnpm install --执行cnpm install是不会去pack-lock.json中获取任何信息的
用IDEA(或者其他工具)打开这个项目,点击下方 Terminal(终端和cmd效果一样),安装依赖
安装成功后文件夹内会多出一个 node_modules 文件夹,点击package.json
脚本点击左边绿色三角可直接执行,成功后显示页面
安装Element-Ui依赖:
npm i element-ui -S
在项目根目录的main.js里面加上:
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(Element, {
size: 'default'
})
新建Springboot项目
点击File—New—Project,创建项目
选择Spring Initializr点击Next
Maven通过GAV标识jar包:
- G:groupId 一般来代表项目名称
- A:artifactId 一般来代表模块名称
- V:version 模块版本
输入Gav,选择对应环境的JDK版本点击Next
进入到项目依赖选择的界面,由于是小Demo,选择的依赖在右侧圈了出来,其余可以不选,这次Demo中不涉及到数据库的操作,但是驱动也可以先选上
填写项目名,项目存放地址,点击下一步:
项目结构如下:
先把目录结构构建出来,在SpringbootApplication(主启动类)的同级目录下新建文件夹 - controller :放一些接口代码
- dao:放一些与数据库交互的代码
- dto:放一些与前端交互的实体类
- entity:放与数据库交互的实体类
- service:放一些接口 impl:放接口的实现类
- utils:放常用到的工具
application.properties是整个项目的核心配置文件,Springboot同样支持yaml格式的配置
#端口设置
server.port=8085
在controller文件夹下新建一个DemoController类:
//此controller只返回json
@RestController
//配置拦截字符
@RequestMapping("Vue")
public class DemoController {
@RequestMapping("test")
public String init(){
return "the controller test !";
}
}
启动项目,测试接口:
在起步开发之前,新建一个公共返回实体类放在utils包下:
//lombok 插件,不需要写setter和getter等等方法
@Data
public class Result {
private String code;
private String message;
private Object data;
//默认成功返回Result
public Result success(String mes, Object da) {
this.code = "200";
this.message = mes;
this.data = da;
return this;
}
//默认失败返回Result
public Result failed(String mes) {
this.code = "500";
this.message = mes;
return this;
}
public Result deFault(String code, String message, Object data) {
this.code = code;
this.message = message;
this.data = data;
return this;
}
}
在dto文件夹下新建一个Login实体类,用来封装前端传递过来的数据:
@Data
public class Login {
private String id;
private String username;
private String password;
}
准备工作都做好后,在DemoController里面写登录接口:
//此controller只返回json
@RestController
//配置拦截字符
@RequestMapping("Vue")
public class DemoController {
@RequestMapping("test")
public String init() {
return "the controller test !";
}
@RequestMapping("login")
public Result login(@RequestBody Login login) {
String loginUsername = login.getUsername();
String loginPassword = login.getPassword();
//模拟从数据库查询出用户名和密码
if (loginUsername.equals("1381") && loginPassword .equals("123456test")) {
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("username", loginUsername);
hashMap.put("password", loginPassword);
return new Result().success("登陆成功!", hashMap);
}
return new Result().failed("登陆失败!");
}
}
测试接口,成功返回:
失败返回:
后台登录接口已经完成
Element-UI
Element的学习,我推荐照着官网写demo,每一个模块都有示例代码,可以再项目中直接使用
基本的登录界面有两个输入框和一个登录按钮,加一些多样的样式,这个就很符合:
在vue项目中新建Login.vue组件,把代码直接复制过来:
<template>
<div id="loginId">
<el-form :model="LoginFrom" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="username" id = "inputId" >
<el-input type="username" v-model="LoginFrom.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="pass" id = "inputId">
<el-input type="password" v-model="LoginFrom.pass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass" id = "inputId">
<el-input type="password" v-model="LoginFrom.checkPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age" id = "inputId">
<el-input v-model.number="LoginFrom.age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "login",
data() {
let checkAge = (rule, value, callback) => {
if (!value) {
return callback(new Error('年龄不能为空'));
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
if (value < 18) {
callback(new Error('必须年满18岁'));
} else {
callback();
}
}
}, 1000);
};
let validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.LoginFrom.checkPass !== '') {
this.$refs.LoginFrom.validateField('checkPass');
}
callback();
}
};
let validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.LoginFrom.pass) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
LoginFrom: {
username: '',
pass: '',
checkPass: '',
age: ''
},
rules: {
pass: [
{validator: validatePass, trigger: 'blur'}
],
checkPass: [
{validator: validatePass2, trigger: 'blur'}
],
age: [
{validator: checkAge, trigger: 'blur'}
]
}
}
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
<style scoped>
#loginId{
padding-top: 50px;
border:1px solid #2c3e50;
border-radius: 5px;
margin: auto;
width: 30%;
}
#inputId{
width: 85%;
}
</style>
路由 router.js 修改:
import login from "../components/login";
routes: [
{
// /代表根地址访问
path: '/',
name: 'login',
component: login
}
]
重启项目,查看效果:
引入Axios模块
前端页面和后端接口都开发好了,现在就要通过axios做前后端交互传输数据
cnpm install --save axios
提交表单的方法加入axios方法:
import axios from 'axios';
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
let url = 'http://localhost:8085/Vue/login'
let params = {
username: this.username,
password: this.password,
}
axios.post(url, params).then(res => {
console.log(res.data)
})
} else {
console.log('error submit!!');
return false;
}
});
},
查看效果:
CORS
什么是跨域
跨域指浏览器不允许当前页面的所在的源去请求另一个源的数据。源指协议,端口,域名。只要这个3个中有一个不同就是跨域。
Vue解决跨域问题
vue2.0 版本打开webpack.dev.conf.js文件,在devServer里面加上proxy的配置
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: {
'/demo': {
target: 'http://localhost:8085/Vue/', // 要访问的接口域名
changeOrigin: true, //开启代理:本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,服务端和服务端进行数据的交互就不会有跨域问题
pathRewrite: {
'^/demo': '' //这里理解成用'/demo'代替target里面的地址,比如我要调用'http://localhost:8085/Vue/login/',直接写'/demo/login'即可
}
},
},
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
登录提交代码修改为
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
let url = 'demo/login'
let params = {
username: this.username,
password: this.password,
}
axios.post(url, params).then(res => {
console.log(res.data)
})
} else {
console.log('error submit!!');
return false;
}
});
},
重启项目,查看修改后效果: