一、vue 的简介
1.1 使用 JQuery 的复杂性问题
- 使用 JQuery 进行前后端分离开发,既可以实现前后端交互 (ajax) ,又可以完成数据渲染
- 存在的问题: JQuery 需要通过 HTML 标签拼接、DOM 节点操作完成数据的显示,开发效率低且容易出错,渲染效率较低
- vue 是继 JQuery 之后的又一优秀的前端框架:专注于前端数据的渲染 ———— 语法简单、渲染效率高
1.2 VUE 简介
1.2.1 前端框架
-
前端三框架:HTML、CSS、JavaScript
- HTML 决定网页结构
- CSS 决定显示效果
- JavaScript 决定网页功能 (交互、数据显示)
-
UI 框架:(只提供样式、显示效果)
- Bootstrap
- amazeUI
- Layui
-
JS 框架:
- JQuery (JQuery UI)
- React
- angular
- nodejs ---- 后端开发
- vue 集各种前端框架的优势发展而来
1.2.2 MVVM
项目结构经历的三个阶段:
后端 MVC :可以理解为单体结构,流程控制是由后端控制器来完成
前端 MVC :前后端分离开发,后端只负责接收响应请求
MVVM是MVC的增强版,实质上和MVC没有本质区别,只是代码的位置变动而已
MVVM 前端请求后端接口,后端返回数据,前端接收数据,并将接收到的数据设置为 “VM”,HTML 从 vm 取值
- M model 数据模型,指的是后端接口返回的数据
- V view 视图
- VM ViewModel 视图模型 数据模型与视图之间的桥梁,后端返回的 model 转换前端所需的 vm,视图层可以直接从 vm 中提取数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rKmhc58L-1675781372002)(vue-study.assets/MVVMPattern.png)]
Model-View-ViewModel —— 概念图
二、 vue 入门使用
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
2.1 vue 的引入
-
离线引用:下载 vue 的 js 文件,添加到前端项目,在网页中通过 script 标签引用 vue.js 文件
-
CDN 引用:
直接使用在线 CDN 的方式引入
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
2.2 入门案例 – Hello World
文本:数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
{ {message}}
-
创建一个 HTML 文件
-
引入 vue.js 文件
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
-
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 引入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app-1">
从 0 开始: {
{message}}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-1',
data: {
message: 'Hello World!'
}
})
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W5MaJ4bx-1675781372004)(vue-study.assets/image-20211205165420235.png)]
Mustache 标签将会被替代为对应数据对象上 message
property 的值。无论何时,绑定的数据对象上 message
property 发生了改变,插值处的内容都会更新。
三、 vue 的语法
3.1 基本类型数据和字符串
<div id="app-2">
{
{code}}
从 0 开始: {
{message}}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-2',
data: {
code: 1_3_3,
message: 'Hello World!'
}
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vvaW6r9U-1675781372006)(vue-study.assets/image-20211205212337929.png)]
3.2 对象类型数据
- 支持 ognl 语法
<div id="app-3">
学号:{
{stu.stuNum}} <br />
姓名:{
{stu.stuName}} <br />
性别:{
{stu.stuGender}} <br />
年龄:{
{stu.stuAge}}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-3',
data: {
stu: {
stuNum: '10001',
stuName: '张三',
stuGender: 'M',
stuAge: 20
}
}
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u2TWdI3y-1675781372007)(vue-study.assets/image-20211205215759140.png)]
3.3 条件 v-if
v-if : 用来控制切换一个元素是否显示 (底层控制是 DOM 元素,操作 DOM)
注:在浏览器中网页打开这个文件 F12,从标签上可以看到没有 stu.stuGender == 'F'
对应的元素。即条件不成立,网页不会渲染该 DOM,连标签都不会有。
<div id="app-4">
学号:{
{stu.stuNum}} <br />
姓名:{
{stu.stuName}} <br />
性别:
<label v-if="stu.stuGender == 'M'">
男
</label>
<label v-if="stu.stuGender == 'F'">
女
</label>
<br />
年龄:{
{stu.stuAge}}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-4',
data: {
stu: {
stuNum: '10001',
stuName: '张三',
stuGender: 'M',
stuAge: 20
}
}
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HAkfuksF-1675781372009)(vue-study.assets/image-20211205220747989.png)]
3.4 循环 v-for
v-for
指令基于一个数组来渲染一个列表。在
v-for
块中,我们可以访问所有父作用域的 property。v-for
还支持一个可选的第二个参数,即当前项的索引。
<div id="app-5">
<table border="1" cellspacing="0" width="400">
<tr>
<th>序号</th>
<th>学号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr v-for="(stu, index) in stus">
<td>{
{index + 1}}</td>
<td>{
{stu.stuNum}}</td>
<td>{
{stu.stuName}}</td>
<td>
<table v-if="stu.stuGender == 'M'">
男
</table>
<table v-if="stu.stuGender == 'F'">
女
</table>
</td>
<td>{
{stu.stuAge}}</td>
</tr>
</table>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-5',
data: {
stus: [
{
stuNum: '10001',
stuName: '张三',
stuGender: 'M',
stuAge: 20
},
{
stuNum: '10002',
stuName: '李四',
stuGender: 'M',
stuAge: 23
},
{
stuNum: '10003',
stuName: '郑红',
stuGender: 'F',
stuAge: 19
}
]
}
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dN40pYyJ-1675781372010)(vue-study.assets/image-20211205222910734.png)]
3.5 绑定标签属性 v-bind
- v-bind:属性名 缩写:
:属性名
<div id="app-6">
<input type="text" v-bind:value="message">
<hr /><br />
<table border="1" cellspacing="0" width="400">
<tr>
<th>序号</th>
<th>学号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
<tr v-for="(stu, index) in stus">
<td>{
{index + 1}}</td>
<td>{
{stu.stuNum}}</td>
<td><img height="30" :src="stu.stuImg" /> </td>
<td>{
{stu.stuName}}</td>
<td>
<table v-if="stu.stuGender == 'M'">
男
</table>
<table v-if="stu.stuGender == 'F'">
女
</table>
</td>
<td>{
{stu.stuAge}}</td>
</tr>
</table>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-6',
data: {
message: 'Hello World!!',
stus: [
{
stuNum: '10001',
stuName: '张三',
stuGender: 'M',
stuAge: 20,
stuImg: 'img/1.jpg'
},
{
stuNum: '10002',
stuName: '李四',
stuGender: 'M',
stuAge: 23,
stuImg: 'img/2.jpg'
},
{
stuNum: '10003',
stuName: '郑红',
stuGender: 'F',
stuAge: 19,
stuImg: 'img/3.jpg'
}
]
}
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AwvsVbWv-1675781372011)(vue-study.assets/image-20211205224219915.png)]
3.6 表单标签的双向绑定 v-model
- 只能使用在表单输入标签
- v-model:value 可以简写为 v-model
<div id="app-7">
<input type="text" v-model="message">
<hr /><br />
双向绑定:{
{message}}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-7',
data: {
message: 'Hello World!!'
}
})
</script>
四、vue 实例
每个使用 vue 进行数据渲染的网页文档都需要创建一个 vue 实例 — — ViewModel
4.1 vue 实例的生命周期
vue 实例生命周期 — — vue 实例从创建到销毁的过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IS1xMdjp-1675781372012)(vue-study.assets/lifecycle.png)]
- 创建 vue 实例 (初始化 data,加载 el)
- 数据挂载 (将 vue 实例 data 中的数据渲染到网页 HTML 标签)
- 重新渲染 (当 vue 的 data 数据发生变化,会重新渲染到 HTML 标签)
- 销毁实例
创建对象 ---- 属性初始化 ---- 获取属性值 ----- GC 回收
4.2 钩子函数
为了便于开发者在 vue 实例生命周期的不同阶段进行特定的操作,vue 在生命周期四个阶段的前后分别提供了一个函数,这个函数无需开发者调用,当 vue 实例到达生命周期的指定阶段会自动调用对应的函数。
<div id="app-8">
<label v-once>{
{message}}</label><br />
<label>{
{message}}</label><br />
<input type="text" v-model="message">
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-8',
data: {
message: 'Hello World!!'
},
beforeCreate: function () {
// 1. data 初始化之前执行,不能操作 data
},
create: function () {
// 2. data 初始化之后执行,模板加载之前,可以修改 / 获取 data 中的值
console.log(this.message);
// this.message = 'Hello World!! create()';
},
beforeMount: function () {
// 3. 模板加载之后,数据初始渲染(挂载)之前,可以修改 / 获取 data 中的值
// this.message = 'Hello World!! beforeMount';
},
mounted: function () {
// 4. 数据初始渲染(挂载)之后,可以对 data 中的变量进行修改,但是不会影响 v-once 的渲染
// this.message = "Hello World!! mounted";
},
beforeUpdate: function () {
// 5. 数据渲染之后,当 data 中的数据发生变化触发重新渲染,渲染之前执行此函数
console.log("---" + this.message);
this.message = 'Hello World!! beforeUpdate';
},
update: function () {
// 6. data 数据被修改之后,重新渲染到页面之后
// this.message = "Hello World!! update";
},
beforeDestroy: function () {
// 7. 实例销毁之前
},
destroy: function () {
// 8. 实例销毁之后
}
})
</script>
五、 计算属性和侦听器
5.1 计算属性
data 中的属性可以通过声明获得,也可以通过在 computed 计算属性的 getter 获得
特性:计算属性所依赖的属性值发生变化会影响计算属性的值同时发生变化
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app-9">
<input type="text" v-model="message1"><br />
<input type="text" v-model="message2"><br />
{
{message3}}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-9',
data: {
message1: 'Hello',
message2: 'World'
},
computed: {
message3: function () {
return this.message1 + this.message2;
}
}
})
</script>
</body>
</html>
5.2 侦听器
侦听器,就是 data 中属性的侦听器,当 data 中的属性值发生变化就会触发侦听器函数的执行
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app-10">
<input type="text" v-model="message1"><br />
<input type="text" v-model="message2"><br />
{
{message3}}
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-10',
data: {
message1: 'Hello',
message2: 'World',
message3: 'Hello World'
},
watch: {
message1: function () {
this.message3 = this.message1 + this.message2;
},
message2: function () {
this.message3 = this.message1 + this.message2;
}
}
})
</script>
</body>
</html>
六、class 与 style 绑定
6.1 class 绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.my-style1 {
width: 200px;
height: 100px;
background: orange;
}
.my-style2 {
border-radius: 10px;
}
.my-style3 {
width: 200px;
height: 100px;
background: black;
}
</style>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app-11">
<!-- 如果 message1 为 true, 就加载 my-style1,如果 message2 为 true, 就加载 my-style2 -->
<div :class="{'my-style1': message1, 'my-style2' : message2}">
</div><hr />
<!-- 为 class 属性加载多个样式名 -->
<div :class="[booleanValue1, booleanValue2]">
</div><hr />
<!-- 如果 message3 为 true, 则 class = 'my-style3',否则 class = 'my-style1'
如果在三目运算中使用样式名则需要加单引号,不加单引号则表示从 data 变量中获取样式名
-->
<div :class="[message3 ? 'my-style3' : 'my-style1']">
</div>
<div :class="[message1 ? booleanValue1 : booleanValue3]"></div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-11',
data: {
message1: true,
message2: true,
message3: true,
booleanValue1: "my-style1",
booleanValue2: "my-style2",
booleanValue3: "my-style3"
}
})
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dD7yvtv6-1675781372015)(vue-study.assets/image-20211206164317378.png)]
6.2 style 绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app-12">
<!-- 当使用 v-bind 绑定内联样式时:
1. 使用 {} 定义 style 样式,才能获取 data 的值, {} 要遵循 JSON 格式
2. {} 中不在使用 style 样式属性名 “font-size”, 而要使用对应的 js 属性名
border-style-width --- borderStyleWidth
-->
<div v-bind:style="{color: colorName, fontSize: fontsize + 'px' }">
Hello World!
</div>
<!-- 我们可以直接为 style 属性绑定一个 data 中定义好的内联样式的字符串 -->
<div v-bind:style="myStyle1">
Hello World!!
</div>
<!-- 我们可以直接为 style 属性绑定一个 data 中定义好的内联样式的对象 -->
<div v-bind:style="myStyle2">
Hello World!!!
</div>
<!-- 我们可以在同一个 style 属性通过数组引用多个内联样式的对象 -->
<div v-bind:style="[myStyle2, myStyle3]">
Hello World!!!!
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-12',
data: {
colorName: "yellow",
fontsize: "40",
myStyle1: "color: orange; font-size: 50px",
myStyle2: {
color: "blue",
fontSize: "60px"
},
myStyle3: {
textShadow: "orange 3px 3px 5px"
}
}
})
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JPCJ0Ov4-1675781372016)(vue-study.assets/image-20211206170540492.png)]
七、条件与列表渲染
7.1 条件渲染
条件判断语句:
v-if
v-else-if
v-else
7.1.1 v-if
v-if
指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app-13">
<h3 v-if="code == 1">Hello :可以看到</h3>
<h3 v-if="flag">flag 为 true, 可以看到</h3>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-13',
data: {
code: 1,
flag: false
}
})
</script>
</body>
</html>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vG3XqOEB-1675781372017)(vue-study.assets/image-20211206171347121.png)]
7.1.2 v-else
v-else
指令来表示v-if
的“else 块”
<div id="app-13">
<!-- v-else 标签需要紧跟在 v-if 的标签之后,中间不能有其他标签, 否则它将不会被识别 -->
<h3 v-if="code == 1">Hello :可以看到</h3>
<h3 v-else>World :可以看到</h3>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-13',
data: {
code: 1
}
})
</script>
7.1.3 v-else-if
<div id="app-13">
分数 {
{code}}
对应的等级:
<h3 v-if="code >= 90">优秀</h3>
<h3 v-else-if="code >= 80">良好</h3>
<h3 v-else-if="code >= 70">中等</h3>
<h3 v-else-if="code >= 60">及格</h3>
<h3 v-else>挂科</h3>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-13',
data: {
code: 85
}
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iRrwxXXH-1675781372018)(vue-study.assets/image-20211206173017480.png)]
7.1.4 v-show
v-show
:同样用于根据条件展示元素。从功能上 v-show 与 v-if 作用是相同的,只是渲染过程有区别。
v-if 与 v-show 的区别:
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。- 相比之下,
v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。 - 一般来说,
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show
较好;如果在运行时条件很少改变,则使用v-if
较好。
7.2 列表渲染
编码过程中,发现网页出现报错:
Uncaught Error: Bootstrap's JavaScript requires jQuery at bootstrap.min.js:6
解决方法:在引进JQuery文件时,将其放在 bootstrap 前面即可。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app-14">
<ul>
<li v-for="c in categories">
<a :href="'query?cid=' + c.cid">{
{c.cname}}</a>
</li>
</ul>
<table class="table table-bordered">
<tr>
<th>学号</th>
<th>照片</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>操作</th>
</tr>
<template v-for="(s, index) in stu">
<tr :id="'tr' + s.stuNum">
<td>{
{s.stuNum}}</td>
<td>
<img height="30" :src="s.stuImg" />
</td>
<td>{
{s.stuName}}</td>
<td>
<!-- {
{s.stuGender == 'M' ? '男' : '女'}} -->
<img v-if="s.stuGender == 'M'" src="img/m.bmp">
<img v-else src="img/f.bmp">
</td>
<td>{
{s.stuAge}}</td>
<td>
<a class="btn btn-danger" :href="'stu/delete?cid=' + s.stuNum">删除</a>
<a class="btn btn-success" :href="'stu/update?cid=' + s.stuNum">修改</a>
</td>
</tr>
</template>
</table>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app-14',
data: {
categories:[
{
cid: 1,
cname: "华为"
},
{
cid: 2,
cname: "小米"
},
{
cid: 3,
cname: "OPPO"
},
{
cid: 4,
cname: "VIVO"
}
],
stu: [
{
stuNum: "10010",
stuImg: "img/1.jpg",
stuName: "Tom",
stuGender: "M",
stuAge: 20
},
{
stuNum: "10011",
stuImg: "img/2.jpg",
stuName: "Joker",
stuGender: "M",
stuAge: 21
},
{
stuNum: "10012",
stuImg: "img/3.jpg",
stuName: "Ling",
stuGender: "F",
stuAge: 20
},
{
stuNum: "10013",
stuImg: "img/1.jpg",
stuName: "Jack",
stuGender: "F",
stuAge: 18
},
]
}
})
</script>
</body>
</html>