目录
1. 安装nodejs服务器
Java
项目可以运行在
tomcat
服务器,开始完成前后端完全分离。前端有自己独立的工程,我们需
要把前端独立的工程运行起来:
运行在
nodejs
服务器下。
(理解为
tomcat
服务器)
验证是否安装过该软件:
node --version
安装过后会显示版本:
2. 安装npm
- Java项目需要依赖jar,安装maven。
- 前端项目需要依赖第三方的插件:比如axios,elementui。
- echarts 前端也需要一个管理组件的软件:npm.。package.json文件类似于pom.xml文件。
- npm通过该文件package.json文件安装依赖的插件。如果安装了node 默认安装了npm。
验证:
npm -v
验证结果:
3. 安装vue cli的脚手架
作用:帮你创建前端项目工程。它的安装需要依赖上面的
npm
。
3.1 安装vue cli
npm install -g @vue/cli
# -g: global 全局
验证是否安装成功:
vue --version
结果:
4. 使用vue cli搭建vue前端项目
- 使用命令:vue create
- 使用图形化界面:vue ui
这里使用第二种,输入vue ui,即可跳转到图形化界面,默认端口号为8000。
4.1 搭建项目
进入端口号为8000的界面:
点击创建项目:
5. 安装相应的插件:elementui
安装插件有两种方式:
- 使用命令: npm i element-ui -S
- 使用图形化:
6. 安装axios依赖
作用:发送异步请求的。
第一种命令
:npm i -S axios
第二种图形化:
7. 使用客户端软件打开vue工程
vscode:
专业的前端工具。
webstorm:idea
团队开发的软件,
只要会使用
idea
那么也会使用该工具。
hbuilder:
适合前端。
这里使用webstorm。
在webstorm中启动该项目。
重启webstorm
vue原理
8. 组件化开发
- 组件化:一个页面可以拆分成一个个组件,每个组件有着自己独立的结构[html]、样式[css]、行为 [js]。
- 好处:便于维护,利于复用 → 提升开发效率。
- 组件分类:普通组件、根组件。
- 比如:下面这个页面,可以把所有的代码都写在一个页面中,但是这样显得代码比较混乱,难易维护。咱们可以按模块进行组件划分。
9. 根组件 App.vue
9.1 根组件介绍
整个应用最上层的组件,包裹所有普通小组件。
9.2 组件是由三部分构成
三部分构成
- template:结构 (有且只能一个根元素)
- script: js逻辑
- style: 样式 (可支持less,需要装包)
让组件支持less
- style标签,lang="less" 开启less功能
- 装包: yarn add less less-loader -D 或者npm i less less-loader -D
10. 普通组件的注册使用
普通组件的注册有两种方式。
- 局部注册
- 全局注册
10.1 普通组件的注册使用-局部注册
1
特点:
只能在注册的组件内使用
2.
步骤:
1.
创建
.vue
文件(三个组成部分)
2.
在使用的组件内先导入再注册,最后使用
3.
使用方式:
当成
html
标签使用即可
<
组件名
></
组件名
>
4.
注意:
组件名规范
—>
大驼峰命名法, 如
AAAHeader
5.
语法:
// 导入需要注册的组件
// import 组件对象 from '.vue文件路径'
import AAAHeader from './components/AAAHeader'
export default {• // 局部注册
components: {
'组件名': 组件对象,
AAAHeader:AAAHeader,
AAAHeader
}
}
10.2 普通组件的注册使用-全局注册
1.
特点:
全局注册的组件,在项目的
任何组件
中都能使用
2.
步骤
1.
创建
.vue
组件(三个组成部分)
2.
main.js
中进行全局注册
3.
使用方式
当成
HTML
标签直接使用
<
组件名
></
组件名
>
4.
注意
组件名规范
—>
大驼峰命名法, 如
AAAHeader
5.
语法
Vue.component('
组件名
',
组件对象
)
例:
// 导入需要全局注册的组件
import AAAButton from './components/AAAButton'
Vue.component('AAAButton', AAAButton)
11. 组件通信
11.1 什么是组件通信?
组件通信,就是指
组件与组件
之间的
数据传递
- 组件的数据是独立的,无法直接访问其他组件的数据。
- 想使用其他组件的数据,就需要组件通信
11.2 组件之间如何通信?
思考:
- 组件之间有哪些关系? [父子关系]
- 对应的组件通信方案有哪几类?
11.3 组件关系分类
- 父子关系
- 非父子关系
11.4 父子通信流程
- 父组件通过 props 将数据传递给子组件(重点)
- 子组件利用 $emit 通知父组件修改更新
11.5 父向子通信代码示例
父组件通过
props
将数据传递给子组件
父组件
App.vue
<template>
<div class="app" style="border: 3px solid #000; margin: 10px">
我是APP组件
<Son></Son>
</div>
</template>
<script>
import Son from './components/Son.vue'
export default {
name: 'App',
data() {
return {
myTitle: '学习前后端分离~',
}
},
components: {
Son,
},
}
</script>
<style>
</style>
子组件
Son.vue
<template>
<div class="son" style="border:3px solid #000;margin:10px">
我是Son组件
</div>
</template>
<script>
export default {
name: 'Son-Child',
}
</script>
<style>
</style>
父向子传值步骤:
- 给子组件以添加属性的方式传值
- 子组件内部通过props接收
- 模板中直接使用 props接收的值
11.6 子向父通信代码示例
子组件利用 $emit 通知父组件,进行修改更新
子向父传值步骤:
- $emit触发事件,给父组件发送消息通知
- 父组件监听$emit触发的事件
- 提供处理函数,在函数的性参中获取传过来的参数
12. 路由介绍
12.1 思考
单页面应用程序,之所以开发效率高,性能好,用户体验好
最大的原因就是:
页面按需更新
比如当点击【发现音乐】和【关注】时,
只是更新下面部分内容
,对于头部是不更新的
要按需更新,首先就需要明确:
访问路径
和
组件
的对应关系!
访问路径 和 组件的对应关系如何确定呢?
路由
12.2 路由的介绍
生活中的路由:设备和
ip
的映射关系
Vue
中的路由:
路径和组件
的
映射
关系
12.3 vue中如何使用路径
我们刚才演示了路由的基本使用。
---
通过在地址栏输入路由地址,在根据路由配置找到对应的组
件,并渲染该组件。
(
1
)第一种
:
声明式路径
<router-link to="/login">登录</router-link>
(
2
)第二种
:
编码式路径
methods:{
my(){
//路由跳转---编码式路由
this.$router.push("/register")
}
}
报错:NavigationDuplicated: Avoided redundant navigation to current location: "/register"
解决方案
: /router/index.js
添加如下代码
Vue-Router3.0
const originalPush = VueRouter.prototype.push
//修改原型对象中的push方法
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}
13. 路由传递
13.1 声明式路由
声明式路由是指使用特定的组件来定义导航链接,通过在模板中声明来进行路由导航。这种方式更加直观和易懂,适用于大多数导航场景。
使用 <router-link>
定义导航链接:
在Vue Router中,您可以使用<router-link>
组件来创建声明式的导航链接。
<template>
<div>
<router-link to="/login">登录</router-link>
</div>
</template>
在上述代码中,<router-link>
会被渲染成一个带有to
属性的链接。点击链接时,Vue Router会根据to
属性的值进行路由跳转。
- 查询参数传参 (比较适合传多个参数)
- 跳转:to="/path?参数名=值&参数名2=值"
- 获取:this.$route.query.参数名
- 动态路由传参 (优雅简洁,传单个参数比较方便)
- 配置动态路由:path: "/path/:参数名"
- 跳转:to="/path/参数值"
- 获取:this.$route.params.参数名
13.2 编码路由
程序式导航是指使用JavaScript代码来实现路由导航,通常在组件中进行。这种方式适用于需要在逻辑中动态控制导航的场景。
查询参数 :
使用 $router.push()
实现导航:
my(){
//路由跳转---编码式路由
//简写版:
//this.$router.push("/my?name=zhangsan&age=18")
//完整版
this.$router.push({
path: "/my",
query:{
name:"张三",
age:88
},
})
}
接受:
created() {
this.name=this.$route.query.name;
this.age=this.$route.query.age;
}
动态路由参数:
使用
$router.push()
实现导航:
//动态路由参数--简介版
// this.$router.push("/my/zcj")
this.$router.push(
{
// path:"/my", //表示路由的path的值
name:"My", //表示路由的名称
params:{
key:"wzy"
}
}
)
//path不能和params配合使用。 name可以和params配合使用
接受参数 :
//create()
created() {
this.name=this.$route.params.key;
// this.name=this.$route.query.name;
// this.age=this.$route.query.age;
}
13.3 总结
编程式导航,如何跳转传参?
1. path路径跳转 :
query传参:
this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
this.$router.push({
path: '/路径',
query: {
参数名1: '参数值1',
参数名2: '参数值2'
}
})
动态路由传参:
this.$router.push('/路径/参数值')
this.$router.push({
path: '/路径/参数值'
})
2.name命名路由跳转:
query
传参:
this.$router.push({
name: '路由名字',
query: {
参数名1: '参数值1',
参数名2: '参数值2'
}
})
动态路由传参 (需要配动态路由):
this.$router.push({
name: '路由名字',
params: {
参数名: '参数值',
}
})
14. 跨域问题
跨域问题:从一个域通过ajax访问另一个域。这里就会出现跨域问题。
域的不同
: 1. ip
不同
2.
端口号不同
3.
协议不同。
如何解决跨域
:
1.
第一种前端解决。
2.
第二种后端解决。
后端解决:
第一种
:
使用注解: 在
controller
使用
@CrossOrigin
第二种
:
跨域配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
//放行的ip
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return new CorsFilter(source);
}
}