一、启动后端服务
安装java、maven、配置环境这些就忽略了,提醒下maven也应该配置阿里云的仓库,否则下载包很慢的。另外maven的依赖库存放位置要选在其他位置,否则C盘很快满…
1、打开IDEA,新建Springboot项目,JDK1.8:
2、选择springboot版本,勾选两个常用组件lombok和configuration
3、配置好IDE
设置里面:
- 构建、执行、部署->构建工具->maven选择Enable Auto Importing
- 编辑器->常规->自动导入,勾选“快速优化导入”或者叫"xxx on the fly",会帮你清理无用的import
4、选择自己熟悉的配置
把springboot版本改回我用的较多的2.1.6:
删掉Test文件,因为2.2.x开始用Jupiter了,2.1.6还是Junit4。
application.properties改为application.yml。
pom添加web支持:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
编写一个DTO:
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class HelloDTO {
private String data;
}
编写一个controller:
@RestController
public class HelloController {
@GetMapping("/hello")
public HelloDTO hello() {
return HelloDTO.builder().data("123").build();
}
}
配置允许跨域的bean,config/beans/CrossRegionConfig:
@Configuration
public class CrossRegionConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); //允许任何域名
corsConfiguration.addAllowedHeader("*"); //允许任何头
corsConfiguration.addAllowedMethod("*"); //允许任何方法
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); //注册
return new CorsFilter(source);
}
}
application.yml给后端服务器换个端口:
server:
port: 11111
启动服务器,并访问http://127.0.0.1:11111/hello即可得到json字符串:
{"data":"123"}
二、配置Vue
1、理解Vue的渲染
Vue最终都是通过index.html渲染的
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>bwb</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
这里面只有一个id为app的块,这个块会由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'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
main.js里面new了一个对象Vue,它的视图是通过template字段渲染的,components表明要引入的模块,template通过标签的形式将这个模块渲染了出来。而App.vue:
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
渲染了一张logo图片,还有一个router-view,这个router-view会根据路由自动渲染子页面,看看路由router/index.js:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})
表明了根路由会渲染HelloWorld组件,再看看HelloWorld.vue:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<ul>
<li>
<a
href="https://vuejs.org"
target="_blank"
>
Core Docs
</a>
</li>
……略
这就是最深的子页面了。总结一下就是这样的结构:
2、理解Vue编码风格
Vue核心概念是组件(Component),一切皆为组件。因为有组件概念,所以组件内部是高度封装的,HTML、CSS、JS都写在同一个Vue文件中,且自由度非常高:
<template>
html语句
</template>
<script>
vue语法、纯js、jquery
</script>
<style scoped>
css、scss等
</style>
其中style如果不加scoped,则为全局css,加上之后,则只在当前文件生效,这也太方便了吧,我以前一直头疼的就是个class起名字,因为不能重复,这个scoped解决了很大的问题。
3、前端代码编写
(1)src文件夹里增加一些文件夹,并明确职责:
- api:管理后端对接api
- assets:静态文件图片
- common:公共组件
- components:页面组件
- const:常量
- router:路由
- utils:工具组件
(2)我们在package.json里面增加axios组件,这是一个http请求组件,可以实现类似jquery的$.ajax的功能。
"dependencies": {
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"axios": "^0.19.2"
},
然后执行npm install,即可引入该组件。
(3)编写一个工具组件utils/request.js:
import axios from 'axios'
const httpService = axios.create({
baseURL: 'http://127.0.0.1:11111',
timeout: 5000,
headers: {
'Content-Type': 'application/json'
},
transformRequest: [function (data) { // , headers
return JSON.stringify(data)
}]
})
// if need login, then redirect to login page
httpService.interceptors.response.use(
response => {
return response
},
err => {
if (err && err.response && err.response.data && err.response.data.code) {
switch (err.response.status) {
case 401:
// do something
break
default:
// do something
break
}
}
return Promise.reject(err)
})
export default httpService
里面配置了一些http请求参数、json解析,以及HTTP响应码的统一拦截,例如当发现有401,说明要求登录,可以跳转到登录页面;当有错误时,可以统一配置错误展示方法等。一定要注意xxx = axios.create前面定义的变量名要和xxx.interceptors.response.use的变量名相同,否则会发现这个拦截器不起作用。拦截器概念类似spring。
(4)编写api
起名方式我喜欢加一个Api后缀,例如helloApi.js:
import httpService from '@/utils/request'
export function hello () {
return httpService.get('/hello')
}
(5)编写页面components/HelloWorld2.vue
<template>
<div class="test-class">{{msg}}</div>
</template>
<script>
import {hello} from '@/api/helloApi'
export default {
data () {
return {
msg: ''
}
},
mounted () {
hello().then((res) => {
this.msg = res.data
})
}
}
</script>
<style scoped>
.test-class {
color: red
}
</style>
这里我们做了这些事情:
- 引入了API的组件中hello方法
- 创建了一个class,作用是使字体变成红色
- 用vue的语法data定义了一个“全局变量”msg
- 用vue的语法定义了当页面开始渲染时要执行的方法,该方法是调用api执行http请求
- 用axios的语法调用hello,并将结果的值赋予msg
- 在template定义一个div,并用vue的语法将msg渲染到div内
(6)我们将router/index.js的路由改为HelloWorld2:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld2 from '@/components/HelloWorld2'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld2
}
]
})
然后ctrl+s保存,由于前面webpack的devtool配置,它会自动热更新的。
(7)浏览http://localhost:8080/#/,我们已经成功地打通了前后端: