渐进式框架-VUE

渐进式框架-VUE

Wreckloud_雲之残骸 Lv3

Vue 是一款用于 构建用户界面渐进式 的 JavaScript 框架
官方网站:https://cn.vuejs.org

  • 构建用户界面: 基于数据就能渲染出用户看到的界面
  • 渐进式: 循序渐进. 不需要把所有的组件、语法全部学习完毕才可以使用 Vue. 可以需要什么用什么.
  • 框架: 是一套完整的项目解决方案,用于快速构建项目.

VUE 只需要具备基础的 HTMLJavaScript 知识即可快速上手!

总的来说, VUE 主要的工作是通过调用预定义的 JS 组件, 快速将数据渲染到页面上.
并且确保当数据变化时, 网页能够自动更新.

入门案例

1). 准备工作

  • 准备一个 HTML 文件, 在其body中引入 VUE 模块. 引入模块化的 js 时, 需要设置 type="module" , 浏览器才能正确识别其为模块化的 js.
  • 创建 VUE 程序的应用实例, 控制试图元素
  • 准备元素(div), 交给 VUE 控制
1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="app">

<!-- Vue 将在这里控制这个元素 -->

</div>
<script type="module">
// 引入 VUE 模块
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
// 创建 VUE 应用实例
createApp({

}).mount('#app'); // 将 VUE 应用实例挂载到 id 为 'app' 的元素上
</script>

JavaScript

模块化 JavaScript 是一种代码组织方式, 它允许我们将代码分割成独立的模块, 每个模块都有自己的功能和作用域.
这种方式有助于代码的维护和复用.

这三步准备工作, 是使用 Vue 的必要操作, 是固定步骤.

2). 数据驱动视图

  • 准备数据.
  • 通过插值表达式渲染页面. 插值表达式的写法: {{...}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="app">
<!-- 使用插值表达式将 message 的值渲染到页面上 -->
<h1>{{ message }}</h1>
</div>
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
createApp({
data(){ // data() 是VUE内置的函数
return{ // 将其中的对象返回
message: 'Hello Vue'
}
}
}).mount('#app');
</script>

插值表达式

插值表达式是一种模板语法, 常见于许多现代前端框架和库中.
插值表达式用于将 JavaScript 表达式的值嵌入到 HTML 模板中, 这种语法允许你将动态数据渲染到静态的 HTML 结构中.

入门案例完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue-快速入门</title>
</head>
<body>
<div id="app">
{{message}}
</div>

<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
createApp({
data(){
return {
message: 'Hello Vue'
}
}
}).mount('#app')
</script>
</body>
</html>

核心指令

VUE 的指令是作用在 HTML 标签中带有 v- 前缀的特殊属性.
例如在 <p></p> 标签中使用 VUE 的指令:

1
<p v-xxx="....">.....</p>
指令 作用
v-for 列表渲染,遍历容器的元素或者对象的属性
v-bind 为 HTML 标签绑定属性值,如设置 href , css 样式等
v-if/v-else-if/v-else 条件性的渲染某元素,判定为 true 时渲染,否则不渲染
v-show` 根据条件展示某元素,区别在于切换的是 display 属性的值
v-model 在表单元素上创建双向数据绑定
v-on 为 HTML 标签绑定事件

v-for

列表渲染, 遍历容器的元素或者对象的属性.

1
<tr v-for="(item,index) in items" :key="item.id">{{item}}</tr>

参数:

  • items 为遍历的数组
  • item 为遍历出来的元素
  • index 为索引/下标,从 0 开始 ;可以省略,省略 index 语法: v-for = "item in items"

key:

  • 作用:给元素添加的唯一标识,便于 vue 进行列表项的正确排序复用,提升渲染性能
  • 推荐使用 id 作为 key(唯一),不推荐使用 index 作为 key(会变化,不对应)

注意:遍历的数组,必须在 data 中定义; 要想让哪个标签循环展示多次,就在哪个标签上使用 v-for 指令。

v-bind

动态为 HTML 标签绑定属性值,如设置 href,src,style 样式等。

1
2
3
4
5
<!-- v-bind:属性名="属性值" -->
<img v-bind:src="item.image" width="30px">

<!-- 简化写法 :属性名="属性值" -->
<img :src="item.image" width="30px">

由于之前的插值表达式无法在标签内使用, 因此想在标签内达到插值表达式的效果, 只能只用这个指令.

另外, v-bind 所绑定的数据同插值表达式, 必须在 data 中定义/或基于 data 中定义的数据而来.

v-if

基于条件判断, 来控制创建或移除元素节点(条件渲染). 要么渲染这个元素,要么删除这个元素.

适用于 不频繁切换的场景.

类似于编程语言的流程控制语法, 同理的, 可以配合 v-else-if / v-else 进行链式调用条件判断.

1
2
3
4
5
6
 <!-- v-if="表达式",表达式值为 true-显示;false-隐藏 -->
<td>
<span v-if="emp.job === '1'">班主任</span>
<span v-else-if="emp.job === '2'">讲师</span>
<span v-else>其他</span>
</td>

v-show

类似于 v-if 这两类指令,都是用来控制元素的显示与隐藏的.

区别于 v-if , 是基于 CSS 样式 display 来控制显示与隐藏. 无论条件是否成立, 都会渲染. 然后才会判断其显示还是隐藏.

适用于 频繁切换显示隐藏的场景.

1
2
3
4
5
6
7
8
<!-- v-show="表达式",表达式值为 true-显示;false-隐藏 -->
<td>
<span v-show="emp.job === '1'">班主任</span>
<span v-show="emp.job === '2'">讲师</span>
<span v-show="emp.job === '3'">学工主管</span>
<span v-show="emp.job === '4'">教研主管</span>
<span v-show="emp.job === '5'">咨询师</span>
</td>

v-model

在表单元素上使用,双向数据绑定。可以方便的 获取设置 表单项数据

1
2
<!-- v-model="变量名" -->
<input type="text" id="name" v-model="serachForm.name">

双向数据绑定

是指 Vue 中的数据变, 会影响视图中的数据展示 . 视图中的输入的数据变化, 也会影响 Vue 的数据模型 .

注意:v-model 中绑定的变量, 必须在 data 中定义.

  • 为员工列表案例的搜索栏的表单项,绑定数据:
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
<body>
<!-- 搜索表单区域 -->
<form class="search-form" action="#" method="post">
<input type="text" name="name" placeholder="姓名" v-model="searchEmp.name" />
<select name="gender" v-model="searchEmp.gender">
<option value="">性别</option>
<option value="1"></option>
<option value="2"></option>
</select>
<select name="job" v-model="searchEmp.job">
<option value="">职位</option>
...
<option value="5">咨询师</option>
</select>

<button type="submit">查询</button>
<button type="reset" class="clear">清空</button>
</form>

<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
createApp({
data() {
return {
// 定义 v-model 绑定的变量
searchEmp: {
name: '',
gender: '',
job: ''
},
empList: [
表单数据;
}
]
}
}
}).mount('#container')
</script>

</div>

</body>

v-on

为 html 标签绑定事件 (添加事件监听)

1
2
3
4
5
<!-- v-on:事件名="方法名" -->
<input type="button" value="点我一下试试" v-on:click="handle">

<!-- 简写为 @事件名="…" -->
<input type="button" value="点我一下试试" @click="handle">

定义的 handle 函数,同之前提到的指令, 也需要在 Vue 应用实例创建的时候创建出来,在 methods 定义, 其与 data 平级.

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
<body>

<div id="container">

<!-- 表单区域 -->
<form class="search-form">

<button type="button" @click="search">查询</button>
<button type="button" @click="clear">清空</button>
</form>

</tbody>
</table>

<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
createApp({
data() {
...;
},
// 此处声明函数
methods: {
search() {
console.log(this.searchEmp)
},
clear() {
this.searchEmp = {
name: '',
gender: '',
job: ''
}
}
}
}).mount('#container')
</script>

</div>

</body>

注意: methods 函数中的 this 指向 Vue 实例,可以通过 this 获取到 data 中定义的数据。

完整案例

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tlias智能学习辅助系统</title>
<style>
body {
margin: 0;
}

/* 顶栏样式 */
.header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #c2c0c0;
padding: 20px 20px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

/* 加大加粗标题 */
.header h1 {
margin: 0;
font-size: 24px;
font-weight: bold;
}

/* 文本链接样式 */
.header a {
text-decoration: none;
color: #333;
font-size: 16px;
}

/* 搜索表单区域 */
.search-form {
display: flex;
align-items: center;
padding: 20px;
background-color: #f9f9f9;
}

/* 表单控件样式 */
.search-form input[type="text"], .search-form select {
margin-right: 10px;
padding: 10px 10px;
border: 1px solid #ccc;
border-radius: 4px;
width: 26%;
}

/* 按钮样式 */
.search-form button {
padding: 10px 15px;
margin-left: 10px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}

/* 清空按钮样式 */
.search-form button.clear {
background-color: #6c757d;
}

.table {
min-width: 100%;
border-collapse: collapse;
}

/* 设置表格单元格边框 */
.table td, .table th {
border: 1px solid #ddd;
padding: 8px;
text-align: center;
}

.avatar {
width: 30px;
height: 30px;
object-fit: cover;
border-radius: 50%;
}

/* 页脚版权区域 */
.footer {
background-color: #c2c0c0;
color: white;
text-align: center;
padding: 10px 0;
margin-top: 30px;
}

.footer .company-name {
font-size: 1.1em;
font-weight: bold;
}

.footer .copyright {
font-size: 0.9em;
}

#container {
width: 80%;
margin: 0 auto;
}
</style>
</head>
<body>

<div id="container">
<!-- 顶栏 -->
<div class="header">
<h1>Tlias智能学习辅助系统</h1>
<a href="#">退出登录</a>
</div>

<!-- 搜索表单区域 -->
<form class="search-form">
<input type="text" name="name" placeholder="姓名" v-model="searchEmp.name" />
<select name="gender" v-model="searchEmp.gender">
<option value="">性别</option>
<option value="1"></option>
<option value="2"></option>
</select>
<select name="job" v-model="searchEmp.job">
<option value="">职位</option>
<option value="1">班主任</option>
<option value="2">讲师</option>
<option value="3">学工主管</option>
<option value="4">教研主管</option>
<option value="5">咨询师</option>
</select>
<button type="button" @click="search">查询</button>
<button type="button" @click="clear">清空</button>
</form>

<table class="table table-striped table-bordered">
<thead>
<tr>
<th>姓名</th>
<th>性别</th>
<th>头像</th>
<th>职位</th>
<th>入职日期</th>
<th>最后操作时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(emp, index) in empList" :key="index">
<td>{{ emp.name }}</td>
<td>{{ emp.gender === 1 ? '男' : '女' }}</td>
<td><img :src="emp.image" alt="{{ emp.name }}" class="avatar"></td>
<td>
<span v-if="emp.job === '1'">班主任</span>
<span v-else-if="emp.job === '2'">讲师</span>
<span v-else-if="emp.job === '3'">学工主管</span>
<span v-else-if="emp.job === '4'">教研主管</span>
<span v-else-if="emp.job === '5'">咨询师</span>
</td>
<td>{{ emp.entrydate }}</td>
<td>{{ emp.updatetime }}</td>
<td class="btn-group">
<button class="edit">编辑</button>
<button class="delete">删除</button>
</td>
</tr>
</tbody>
</table>

<!-- 页脚版权区域 -->
<footer class="footer">
<p class="company-name">江苏传智播客教育科技股份有限公司</p>
<p class="copyright">版权所有 Copyright 2006-2024 All Rights Reserved</p>
</footer>

<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
createApp({
data() {
return {
searchEmp: {
name: '',
gender: '',
job: ''
},
empList: [
{ "id": 1,
"name": "谢逊",
"image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/4.jpg",
"gender": 1,
"job": "1",
"entrydate": "2023-06-09",
"updatetime": "2024-07-30T14:59:38"
},
{
"id": 2,
"name": "韦一笑",
"image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg",
"gender": 1,
"job": "1",
"entrydate": "2020-05-09",
"updatetime": "2023-07-01T00:00:00"
},
{
"id": 3,
"name": "黛绮丝",
"image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/2.jpg",
"gender": 2,
"job": "2",
"entrydate": "2021-06-01",
"updatetime": "2023-07-01T00:00:00"
}
]
}
},
methods: {
search() {
console.log(this.searchEmp)
},
clear() {
this.searchEmp = {
name: '',
gender: '',
job: ''
}
}
}
}).mount('#container')
</script>

</div>

</body>
</html>

Vue 生命周期

vue 的生命周期 是 vue 对象从创建到销毁的过程.
其完整的生命周期如下图所示:

vue 的生命周期包含 8 个阶段., 每触发一个生命周期事件, 会自动执行一个生命周期方法, 这些生命周期方法也被称为 钩子方法.

状态 阶段周期
beforeCreate 创建前
created 创建后
beforeMount 挂载前
mounted 挂载完成
beforeUpdate 更新前
updated 更新后
beforeDestroy 销毁前
destroyed 销毁后

其中我们需要重点关注的是 mounted,其他的我们了解即可。

mounted

挂载完成,Vue 初始化成功,HTML 页面渲染成功。以后我们一般用于页面初始化自动的 ajax 请求后台数据

那我们要想在页面加载完毕,就查询出员工列表,就可以在 mounted 钩子函数中,发送异步请求查询员工数据了。

具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  methods: {
async search() {
//基于axios发送异步请求,请求https://web-server.itheima.net/emps/list,根据条件查询员工列表
const result = await axios.get(`https://web-server.itheima.net/emps/list?name=${this.searchForm.name}&gender=${this.searchForm.gender}&job=${this.searchForm.job}`);
this.empList = result.data.data;
},
clear() {
this.searchForm= {
name: '',
gender: '',
job: ''
}
this.search();
}
},
mounted() {
this.search();
}
}).mount('#container')
  • 标题: 渐进式框架-VUE
  • 作者: Wreckloud_雲之残骸
  • 此记初现于 : 2024-11-24 18:04:40
  • 此记变迁于 : 2024-11-28 12:29:42
  • 链接: https://www.wreckloud.com/2024/11/24/猎识印记-领域/软件工程/前端/渐进式框架-VUE/
  • 版权声明: 本幽影记采用 CC BY-NC-SA 4.0 进行许可。
影踪语