前端笔记

@Trenchance 2025.03.01

[TOC]

HTML

标签

Html通过“标签”(或者说元素)来定义文本等。

Html标签是由尖括号括起来的关键字

1
2
<p>这是一个段落。</p>
<h1>这是一个标题</h1>

属性

HTML标签通常带有属性,这些属性提供了额外的信息或修改标签的行为。属性通常位于标签的开始部分,紧跟在标签名后面。属性由属性名和属性值组成,属性值通常用引号括起来。HTML属性的语法格式是:属性名="属性值"

1
<a href="https://www.example.com" target="_blank">访问示例网站</a>

块元素和行内元素

块元素是指那些在页面上占据一整行,并且通常会在它们的前后自动插入换行的元素。块元素会独占一行,后续的元素会另起一行显示。

行内元素是指那些在页面中不会占据整个行,它们只占据它们所需的空间,并且可以与同一行的其他元素并排显示。行内元素不会强制在它们的前后创建换行。

<div>(即 Division 的缩写)是一个块级元素,用来定义一个页面中的 块级区域。它本身不呈现任何视觉效果,但它作为容器帮助将内容分组,通常用于页面布局和结构划分。

<div> 主要用作页面内容的容器,帮助组织和分组不同部分,特别是在布局设计中。

<span> 是一个 行内元素,主要用于对文本或其他小范围的内容进行分组和样式调整。它通常不会对布局产生影响,只是用于容器和样式应用。

表单

是通过 <form> 标签来实现的。

1
2
3
4
5
6
<form action="URL" method="POST/GET">
<!-- 表单控件 -->
<input type="text" name="username" placeholder="用户名">
<input type="password" name="password" placeholder="密码">
<input type="submit" value="提交">
</form>

CSS选择器

CSS 选择器是用于选取 HTML 元素并应用样式的模式。它是 CSS 样式表的基础,通过选择器来确定需要应用样式的元素。在实际开发中,选择器用于定位 HTML 文档中的元素,以便可以对其进行样式控制。下面是对各种常见 CSS 选择器的详细解释。

1. 基础选择器

(1)元素选择器(Type Selector)

元素选择器通过元素的名称来选中 HTML 元素。例如:

1
2
3
p {
color: red;
}

这个选择器会选中所有 <p> 标签,并将其文本颜色设置为红色。

(2)类选择器(Class Selector)

类选择器通过元素的 class 属性来选中元素,类名以 . 开头。一个元素可以有多个类,类选择器可以选中所有具有指定类名的元素。

1
2
3
.button {
background-color: blue;
}

这个选择器会选中所有 class="button" 的元素,并设置其背景颜色为蓝色。

(3)ID 选择器(ID Selector)

ID 选择器通过元素的 id 属性来选中一个特定的元素,ID 以 # 开头。ID 应该是唯一的,每个 ID 在一个页面中只能出现一次。

1
2
3
#header {
font-size: 20px;
}

这个选择器会选中 id="header" 的元素,并设置其字体大小为 20px。

(4)通用选择器(Universal Selector)

通用选择器使用星号(*)表示,选中所有元素。通常用于应用一些全局样式。

1
2
3
4
* {
margin: 0;
padding: 0;
}

这个选择器会选中页面中的所有元素,并将它们的外边距和内边距都设置为 0。

2. 组合选择器

(1)后代选择器(Descendant Selector)

后代选择器通过空格( )连接多个选择器,选中某个元素的所有后代元素。它选中的元素可以是目标元素的子元素、孙子元素等。

1
2
3
div p {
color: green;
}

这个选择器会选中所有在 <div> 内的 <p> 标签,并将它们的文本颜色设置为绿色。

(2)子元素选择器(Child Selector)

子元素选择器使用 > 符号,选中某个元素的直接子元素。

1
2
3
ul > li {
list-style-type: square;
}

这个选择器会选中所有作为 <ul> 直接子元素的 <li> 元素,并将其列表样式设置为方形。

(3)相邻兄弟选择器(Adjacent Sibling Selector)

相邻兄弟选择器使用 + 符号,选中紧接在某个元素后面的同级元素。

1
2
3
h2 + p {
font-weight: bold;
}

这个选择器会选中紧接在 <h2> 后面的 <p> 元素,并将其字体设置为加粗。

(4)通用兄弟选择器(General Sibling Selector)

通用兄弟选择器使用 ~ 符号,选中某个元素后面所有同级的元素,而不一定是紧接的元素。

1
2
3
h2 ~ p {
color: gray;
}

这个选择器会选中所有位于 <h2> 元素后面的同级 <p> 元素,并将它们的文本颜色设置为灰色。

3. 属性选择器

属性选择器可以根据元素的属性及其值来选中元素。

(1)选中具有某个属性的元素

1
2
3
a[href] {
color: blue;
}

这个选择器会选中所有具有 href 属性的 <a> 元素,并将其文字颜色设置为蓝色。

(2)选中具有特定属性值的元素

1
2
3
input[type="text"] {
border: 1px solid black;
}

这个选择器会选中所有 type="text"<input> 元素,并为它们添加黑色边框。

(3)选中属性值包含某个子串的元素

1
2
3
a[href^="https"] {
color: green;
}

这个选择器会选中所有 href 属性以 “https” 开头的 <a> 元素,并将其文字颜色设置为绿色。

1
2
3
a[href$=".jpg"] {
border: 1px solid red;
}

这个选择器会选中所有 href 属性以 “.jpg” 结尾的 <a> 元素,并为它们添加红色边框。

1
2
3
a[href*="example"] {
font-weight: bold;
}

这个选择器会选中所有 href 属性包含 “example” 的 <a> 元素,并将其文字加粗。

4. 伪类选择器(Pseudo-classes)

伪类选择器用于选中元素的特殊状态,例如鼠标悬停、获得焦点等。

(1)**:hover**

当鼠标悬停在元素上时,触发该伪类。

1
2
3
a:hover {
color: red;
}

这个选择器会选中所有 <a> 元素,当鼠标悬停时,将它们的颜色设置为红色。

(2)**:active**

当元素被激活(例如,按钮被点击)时,触发该伪类。

1
2
3
button:active {
background-color: gray;
}

这个选择器会选中所有 <button> 元素,当它们被点击时,将背景颜色设置为灰色。

(3)**:focus**

当元素获得焦点时,触发该伪类。通常用于表单输入框。

1
2
3
input:focus {
border-color: blue;
}

这个选择器会选中所有 <input> 元素,当它们获得焦点时,将边框颜色设置为蓝色。

(4)**:first-child**

选中父元素的第一个子元素。

1
2
3
ul li:first-child {
font-weight: bold;
}

这个选择器会选中 <ul> 中的第一个 <li> 元素,并将其文字加粗。

(5)**:last-child**

选中父元素的最后一个子元素。

1
2
3
ul li:last-child {
margin-bottom: 0;
}

这个选择器会选中 <ul> 中的最后一个 <li> 元素,并将其下边距设置为 0。

5. 伪元素选择器(Pseudo-elements)

伪元素用于选中元素的特定部分,比如第一个字母、前后内容等。

(1)**::before**

用于在元素内容之前插入内容。

1
2
3
p::before {
content: "→ ";
}

这个选择器会在每个 <p> 元素的内容前添加一个箭头符号。

(2)**::after**

用于在元素内容之后插入内容。

1
2
3
p::after {
content: " ←";
}

这个选择器会在每个 <p> 元素的内容后添加一个箭头符号。

(3)**::first-letter**

选中元素的第一个字母。

1
2
3
4
p::first-letter {
font-size: 2em;
color: red;
}

这个选择器会将每个段落的第一个字母设置为红色并放大。

(4)**::first-line**

选中元素的第一行文本。

1
2
3
p::first-line {
font-weight: bold;
}

这个选择器会将每个段落的第一行文本加粗。

6. 组合选择器

(1)多个选择器

多个选择器之间用逗号分隔,表示对多个元素应用相同样式。

1
2
3
h1, h2, h3 {
font-family: Arial, sans-serif;
}

这个选择器会选中所有 <h1><h2><h3> 元素,并将其字体设置为 Arial。

(2)选择器组的优先级

当多个选择器作用于同一元素时,选择器的优先级(权重)决定哪个样式生效。一般来说,ID 选择器优先级高于类选择器和元素选择器。

CSS盒子模型

盒子模型

![](C:\Users\30516\Pictures\Screenshots\屏幕截图 2025-02-28 171516.png)

(1)内容(Content)

  • 内容区域是实际显示的元素内容,如文本、图片、视频等。
  • 内容的大小由元素的 widthheight 属性决定。

(2)内边距(Padding)

  • 内边距是内容与边框之间的空间。它控制内容与边框之间的距离。
  • 内边距可以设置四个方向的值:上、右、下、左,或者使用简写来设置统一的值。
  • 内边距不会影响元素的实际宽度和高度,但它会增加元素的占用空间。

(3)边框(Border)

  • 边框是围绕内容和内边距的线条,通常用于给元素添加边框效果。
  • 可以单独设置每个边的边框宽度、样式和颜色,或者使用简写方式设置统一的值。

(4)外边距(Margin)

  • 外边距是元素与其他元素之间的空间,控制元素之间的距离。
  • 外边距也可以设置四个方向的值:上、右、下、左,或者使用简写方式设置统一的值。

JS

基础

变量:var let const,使用 let 声明的变量具有块级作用域,即它仅在代码块内部有效

函数:需要被调用才会执行

1
2
3
4
5
function add(a, b) {
return a + b;
}

console.log(add(2, 3)); // 输出 5

事件

直接在 HTML 元素的属性中写入 JavaScript 代码进行事件处理

1
<button onclick="alert('按钮被点击了!')">点击我</button>

或者

1
2
3
4
5
6
7
<button onclick="click_event()">这是一个点击事件按钮</button>
<script>
// 点击事件
function click_event() {
alert('点击事件触发了');
}
</script>

DOM

DOM 提供了一种结构化的方式来访问和操作 HTML 或 XML 文档,使得网页的内容、结构和样式都可以通过脚本语言进行动态地修改。

DOM 将网页看作一个树状结构,其中每个网页元素(如标签、文本、属性)都是一个节点。树的每个节点表示文档的一个部分,节点之间通过父子关系(Parent-Child)连接起来。

1
2
3
4
5
6
7
8
9
10
<html lang="en">
<head>
<meta charset="UTF-8">
<title>示例页面</title>
</head>
<body>
<h1>欢迎来到我的网站!</h1>
<p>这里是内容。</p>
</body>
</html>

DOM 结构树可能如下所示:

1
2
3
4
5
6
7
8
Document
└── html
├── head
│ ├── meta
│ └── title
└── body
├── h1
└── p

HTML 是静态的,定义网页的结构。

DOM 是动态的,表示网页的结构和内容,可以通过 JavaScript 进行访问和操作。

JavaScript 可以通过 DOM 提供的 API 来访问和修改 HTML 元素、属性、文本等内容,从而使网页具有动态行为。

DOM操作

访问元素:

1
2
let heading = document.getElementById('title'); // 返回具有指定 id 属性值的元素。id 在文档中是唯一的。
let elements = document.getElementsByClassName('myClass'); // 返回具有指定类名的所有元素,返回的是一个类数组对象(NodeList)。

修改元素内容:

1
2
3
4
5
6
let element = document.getElementById('myId');
element.textContent = '新的文本内容'; // 修改文本内容
let element = document.getElementById('myId');
element.innerHTML = '<span>新的 HTML 内容</span>'; // 修改 HTML 内容
let element = document.getElementById('myId');
element.innerText = '新的文本内容'; // 修改文本内容,区别在于样式影响

事件处理:

**addEventListener(type, listener)**:

  • type:事件类型,如 'click''mouseover' 等。
  • listener:事件处理函数,事件触发时会执行。
1
2
3
4
let button = document.getElementById('myButton');
button.addEventListener('click', function() {
alert('按钮被点击');
});

Vue入门

初步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://unpkg.com/vue@latest"></script>
</head>
<body>
<div id="app">
<input v-model.lazy="text">
<p>{{ text }}</p>
</div>

<script>
const app = {
data() {
return {
text: 'Hello Vue!'
}
}
};

Vue.createApp(app).mount('#app');
</script>

</body>
</html>

{{ text }} 就是 Vue 用来把数据(这里是 text 变量)显示出来的方式。

其中,<input v-model="text">v-model可以简单理解为一种属性

Vue.createApp(app).mount('#app');中app为传入的对象,而mount函数传入的是一个简单的选择器,类似CSS选择器,#app中#代表id选择器

input中的v-model属性设置为data函数中对象的属性,也就是text

还可以改为<input v-model.lazy="text">,呈现不同效果

GPT的解释:

<input v-model="text">:这是一个文本框。当你在这个框里输入内容时,Vue 会自动把你输入的内容保存到一个变量中,这个变量叫做 text。而且,输入框会自动更新显示 text 变量的内容。也就是说,输入框和 text 变量之间有一个“自动同步”的关系——你输入什么,它就记录什么,text 的值发生变化,输入框也会变化。v-model 是 Vue 的一个功能,它让输入框和 text 变量之间保持同步。

<p>{{ text }}</p>:这里是一个段落,它会显示 text 变量的内容。{{ text }} 就是 Vue 用来把数据(这里是 text 变量)显示到页面上的方式。也就是说,text 变量里保存的内容会自动显示在这个段落里。

const app = {}:这就是我们定义 Vue 应用的地方。app 里边放了我们想让 Vue 管理的数据和一些操作。

data():这个部分是用来定义我们想让 Vue 管理的“数据”。这里我们定义了一个数据叫做 text,它的初始值是 'Hello Vue!'。你可以理解为这是一个变量,存放着一些内容(这里是文字)。

Vue.createApp(app):这一步是告诉 Vue 创建一个应用,并且让它使用我们刚刚定义的 app

.mount('#app'):这一步是将 Vue 应用“挂载”到网页上 id="app" 的地方(就是我们前面提到的 <div id="app">),让 Vue 能在这个地方显示和管理内容。

属性绑定,事件绑定,条件渲染,列表渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue 示例</title>
<script src="https://unpkg.com/vue@latest"></script>
</head>
<body>
<div id="app">
<!-- 属性绑定 -->
<h1 :style="{ color: headingColor }">这是一个动态的标题</h1>

<!-- 条件渲染 -->
<button @click="toggleParagraph">显示/隐藏段落</button>
<p v-if="isVisible">这是一个可以显示和隐藏的段落!</p>

<!-- 列表渲染 -->
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>

<!-- 事件处理 -->
<button @click=![屏幕截图 2025-03-02 140054](C:\Users\30516\Pictures\Screenshots\屏幕截图 2025-03-02 140054.png)"changeHeadingColor">改变标题颜色</button>
</div>

<script>
const app = {
data() {
return {
headingColor: 'blue', // 标题的颜色
isVisible: true, // 控制段落的显示与隐藏
items: [ // 渲染一个包含多个项的列表
{ id: 1, name: 'Vue.js' },
{ id: 2, name: 'JavaScript' },
{ id: 3, name: 'CSS' }
]
}
},
methods: {
toggleParagraph() {
this.isVisible = !this.isVisible; // 切换段落的显示与隐藏
},
changeHeadingColor() {
// 改变标题颜色
this.headingColor = this.headingColor === 'blue' ? 'red' : 'blue';
}
}
};

Vue.createApp(app).mount('#app');
</script>
</body>
</html>

Vue Cli

下载与使用

下载可以搜csdn即可,也可以直接【1天搞定SpringBoot+Vue全栈开发】 https://www.bilibili.com/video/BV1nV4y1s7ZN/?p=10&share_source=copy_web&vd_source=85bef9e6ee0eb95b52f30b868049555d

先安装node.js,cd到你的项目目录,然后npm install -g @vue/cli或者npx @vue/cli create my-project,配置完成之后,npm run serve即可启动。

vue cli给我们创建的目录如下

![](C:\Users\30516\Pictures\Screenshots\屏幕截图 2025-03-02 140054.png)

其中package.json类似于pom.xml,src就是写代码的目录。

其中main.js为程序的入口文件

运行的方法:在vscode的终端下npm run serve,如下图所示:

![](C:\Users\30516\Pictures\Screenshots\屏幕截图 2025-03-02 140418.png)

组件

首先是组件的概念

Vue 组件是 Vue.js 中的核心概念之一,它是 Vue 应用的构建块。组件可以让我们把一个复杂的应用拆分成多个小的、可复用的部分

Vue 最常用的组件形式是单文件组件。每个组件存在一个 .vue 文件中,包含 <template><script><style> 三个部分

创建一个组件就相当于创建一个标签,比如下面的<HelloWorld msg="Welcome to Your Vue.js App"/>,这就是HelloWorld组件,HelloWorld组件的代码位于components目录下,有一个叫做HelloWorld.vue的vue文件。

例如App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
name: 'App',
components: {
HelloWorld
}
}
</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>

那么组件如何使用呢?

我们观察到在App.vue中,存在下面的代码

首先我们需要import导入,然后需要注册,导入和注册都在<script>标签下完成

1
2
3
4
5
6
7
8
9
10
<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
name: "App",
components: {
HelloWorld,
},
};
</script>

自己创建一个组件

首先在components目录下面,创建一个Hello.vue

1
2
3
4
5
6
7
<template>
<h1>hello</h1>
</template>

<script></script>

<style></style>

然后在App.vue中导入

1
2
3
4
5
6
7
8
9
10
<script>
import Hello from "./components/Hello.vue";

export default {
name: "App",
components: {
Hello,
},
};
</script>

最后在App.vue中使用这个组件

1
2
3
4
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<Hello></Hello>
</template>

怎么执行的?

在main.js中,我们把App.vue导入进来,并挂载到id=app的标签中,我们注意到public文件夹下的index.html中就存在这句话<div id="app"></div>

Props 属性传递

假如我们创建一个Movie组件

1
2
3
4
5
6
7
8
9
10
11
<template>
<div>
<h1>666</h1>
</div>
</template>

<script>
export default {
name: "Movie",
};
</script>

注意到这里有export default,这里面放的是属性,一个组件导出的属性可以在被导入的时候使用,我们在App.vue导入了Movie,那么就可以使用Movie.name这样的属性。

接下来介绍props:自定义的属性。**props** 是 Vue 中用于组件间传递数据的机制,它允许父组件向子组件传递数据。例如

Movie.vue

1
2
3
4
5
6
7
8
9
<script>
export default {
name: "Movie",
props: ["title"],
data: function () {
return {};
},
};
</script>

App.vue

1
2
3
<div id="app">
<Movie title="666"></Movie>
</div>

现在,让我们实现更加复杂的功能

以下是示例代码:

Hello.vue

1
2
3
4
<template>
<h3>hello</h3>
</template>

Movie.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
<h1>{{ title }}</h1>
<span>{{ rating }}</span>
<button @click="fun">点击收藏</button>
</div>
</template>

<script>
export default {
name: "Movie",
props: ["title", "rating"],
data: function () {
return {};
},
methods: {
fun() {
alert("收藏成功");
},
},
};
</script>

App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<template>
<div id="app">
<Movie
v-for="movie in movies"
:key="movie.id"
:title="movie.title"
:rating="movie.rating"
></Movie>
<Hello></Hello>
</div>
</template>

<script>
import Movie from "./components/Movie.vue";
import Hello from "./components/Hello.vue";
export default {
name: "App",
data: function () {
return {
movies: [
{ id: 1, title: "The Shawshank Redemption", rating: 9.3 },
{ id: 2, title: "The Godfather", rating: 9.2 },
{ id: 3, title: "Pulp Fiction", rating: 9.1 },
],
};
},
components: {
Movie,
Hello,
},
};
</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>

使用第三方组件

以element-ui为例

https://element.eleme.cn/#/zh-CN

注意,你所安装的依赖全部位于node_modules文件夹,如果这个文件夹被删了,通过package.json还是可以重新下载的,直接在项目目录下npm install即可,他会找到package.json自己下载依赖。

具体代码可以在”D:\File\Cworks4\learn-vue\component-demo”找到

Vue 组件生命周期

Vue 组件的生命周期大致可以分为三个阶段:

  1. 创建阶段:在组件被实例化和挂载之前。
  2. 更新阶段:当组件的 dataprops 改变时,组件重新渲染。
  3. 销毁阶段:组件不再需要时被销毁。

生命周期钩子函数,例如:

1
2
3
created() {
console.log('created');
}

实例创建完成后触发。

你需要将钩子函数写在 datamethodscomputed 等同级的位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Vue 2 组件
export default {
data() {
return {
message: 'Hello Vue!'
};
},
created() {
console.log('组件已创建!'); // 在组件创建后调用
},
mounted() {
console.log('组件已挂载!'); // 在组件挂载后调用
},
updated() {
console.log('组件已更新!'); // 在组件数据更新后调用
},
destroyed() {
console.log('组件已销毁!'); // 在组件销毁后调用
},
methods: {
// 定义方法
changeMessage() {
this.message = 'Hello, World!';
}
}
};

Axios

Axios 作为一个基于 Promise 的 HTTP 客户端,提供了很多相较于原生 JavaScript fetch 方法更为便捷、功能强大的功能。

安装npm install axios

在main.js中进行导入,或者在组件里导入都可以,直接import axios from "axios";

一个示例的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 导入 axios
import axios from 'axios';

// 发送 GET 请求
axios.get('https://api.example.com/data')
.then(response => {
// 请求成功时,打印返回的响应数据
console.log(response.data);
})
.catch(error => {
// 请求失败时,打印错误信息
console.error('Error:', error);
});

// 发送 POST 请求
axios.post('https://api.example.com/login', {
username: 'admin',
password: '123456'
}) // 自动把请求体转为json格式
.then(response => {
// 请求成功时,打印返回的响应数据
console.log('Login Successful:', response.data);
})
.catch(error => {
// 请求失败时,打印错误信息
console.error('Error:', error);
});

跨域

同源是指网页的 协议域名端口 三者完全相同,两个 URL 是同源的,才会认为它们属于同一个源(origin)。这意味着它们可以相互进行请求和数据交换。

跨域是指从一个源(协议、域名和端口)向另一个源发起的请求。跨域请求违反了浏览器的同源策略,通常会受到浏览器的安全限制。

不同的协议,如从 http://example.comhttps://example.com 请求。

不同的域名,如从 http://example.comhttp://another-example.com 请求。

不同的端口号,如从 http://example.com:80http://example.com:3000 请求。

当你尝试发起跨域请求时,浏览器会阻止这个请求,除非服务器明确允许跨域访问。这就是 跨域资源共享(CORS) 的作用。

在Springboot配置CORS

有很多方法,可以全局,也可以在某个控制器上设置。

全局的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
public class WebConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
// 允许所有路径的跨域请求
registry.addMapping("/**")
.allowedOrigins("http://localhost:8081") // 允许从该源进行跨域请求
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法
.allowedHeaders("*") // 允许的请求头
.allowCredentials(true); // 允许发送 cookies
}
}

我们这里选择在某个控制器设置:Spring 提供了 @CrossOrigin 注解,它可以直接用于控制器方法或者类上

回到我们的项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
import Movie from "./components/Movie.vue";
import Hello from "./components/Hello.vue";
import Sheet from "./components/Sheet.vue";
import axios from "axios";
export default {
name: "App",
data: function () {
return {
movies: [
{ id: 1, title: "The Shawshank Redemption", rating: 9.3 },
{ id: 2, title: "The Godfather", rating: 9.2 },
{ id: 3, title: "Pulp Fiction", rating: 9.1 },
],
};
},
components: {
Movie,
Hello,
Sheet,
},
};
</script>

我们的App.vue中,data是自己定义的。在正常的项目中,data应该是从后端传递过来的,现在我们要做的就是把前后端联系起来。

首先需要注意一点,我们后端的spring服务器启动为8080端口,前端也是8080端口,因此需要修改后端的端口为8088。

在spring配置文件写server.port=8088

然后我们创建一个控制器:

1
2
3
4
5
6
7
8
9
@GetMapping("/movies")
public List<Movie> getMovies() {
// 创建一个包含电影数据的列表
return Arrays.asList(
new Movie(1, "The Shawshank Redemption", 9.3),
new Movie(2, "The Godfather", 9.2),
new Movie(3, "Pulp Fiction", 9.1)
);
}

修改前端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<script>
import axios from "axios";

export default {
data() {
return {
tableData: [],
};
},
created: function () {
axios.get("http://localhost:8088/movies").then((response) => {
this.tableData = response.data;
});
},
methods: {
// 处理选择变更
handleSelectionChange(val) {
this.selectedRows = val;
},
// 获取行的类名
getRowClassName(row, index) {
if (index % 2 === 0) {
return "even-row"; // 自定义偶数行的样式
} else {
return "odd-row"; // 自定义奇数行的样式
}
},
// 处理分页当前页变更
handleCurrentChange(val) {
this.currentPage = val;
// 这里可以根据分页请求新的数据
console.log("当前页:", val);
},
},
};
</script>

这样我们就可以把后端的数据显示在前端了。

注意,这里需要修改Sheet.vue的template部分,把表格每列,即el-table-column标签中的prop修改为我们的属性。

1
2
3
<el-table-column prop="title" label="标题" sortable></el-table-column>

<el-table-column prop="rating" label="评分"></el-table-column>

全局配置Axios

在main.js中导入

1
2
3
import axios from "axios";
axios.defaults.baseURL = "https://localhost:8088.com";
Vue.prototype.$http = axios;