「课件」原创 => Vue2 基础【转载请标明出处】
第一章·什么是 Vue
Vue(发音/vjuː/,类似于"view")是一套用于构建用户界面的渐进式JavaScript框架。它是一种轻量级、灵活的框架,专注于视图层(以至于在早期甚至都不去集成异步请求的技术),但是它可以很容易地让开发者自己去集成到其他库或已有的项目中。Vue由尤雨溪(Evan You)于2014年创建,并在开源社区(如GitHub)中得到广泛的支持和应用。
Vue的主要特点包括:
- 渐进式框架:当我们说一个框架是"渐进式的"时,意味着你可以逐步地、按需地使用这个框架的功能,而不需要一次性全部采用。这就好比你去自助餐厅,可以选择携盘走,一次性把所有想吃的菜都拿上,也可以慢慢地逐一挑选,根据自己的需求一步一步来。其实这也得益于组件化的思想。
这将为开发者提供更大的灵活性和选择权。你可以根据项目的需求,按照自己的步伐,逐步地引入和使用框架的各个功能,而不用感到被迫一次性采用所有特性。这使得框架更容易被新项目采用,也方便老项目逐步升级。
-
双向数据绑定: Vue使用双向数据绑定机制,当数据变化时,视图会自动更新,而当用户与界面进行交互时,数据模型也会自动更新。简单来说就是前端页面的数据变化时,js 那里的数据模型也会变化,而数据模型变化时,前端页面上展示的数据也会变化。一方变,则另一方肯定也变!
-
组件化: Vue将界面拆分为独立的组件,每个组件具有自己的状态和行为。组件化使得代码更容易理解、维护和复用。
前端组件化: 在前端开发中,组件化更强调用户界面层面的独立性和重用性。一个页面可以由多个独立的组件组成,每个组件负责一个特定的功能或展示一部分内容。常见的前端框架,如Vue.js、React、Angular等,都支持组件化开发。
后端模块化: 在后端开发中,模块化更强调系统架构层面的封装和接口定义。后端应用可以被划分为多个模块,每个模块负责一部分功能,通过定义清晰的接口来进行通信。常见的后端框架和设计模式,如Spring框架、Node.js的模块系统等,都支持模块化开发。
总的来说,组件化和模块化是软件开发中通用的概念,但在不同层面和领域中的应用会有一些差异。这两种概念都有助于提高代码的可维护性、可重用性,并降低系统的复杂性。
- 虚拟DOM: Vue使用虚拟DOM技术,通过在内存中维护一个虚拟的DOM树,然后通过比对算法(DIFF)找出最小化的变更,从而提高性能与之直接操作DOM的速度相靠近。
- 指令: Vue提供了丰富的指令(Directives)系统,例如
v-if
、v-for
、v-bind
等,用于简化模板中需要实现的一些操作。 - 生态系统: Vue配备了一个强大的生态系统,包括官方维护的插件、路由(Vue Router)、状态管理(Vuex)等,以及丰富的第三方库和工具(Axios)
- 易学易用: Vue的API设计简单直观,容易学习和上手,适用于初学者和有经验的开发者。
Vue通常与现代前端开发工具和构建系统(如Webpack)一起使用 否则,每次都自己去手动搭建,好像有点儿不好。。 以便更好地支持模块化开发和构建。它在构建交互性、动态和高性能的用户界面方面非常强大,因此成为了很多开发者选择的框架之一。可以说现在就是主流,而且前端技术迭代和适应是很快的!2024年 很多企业就已经 大面积采用 Vue3 技术了。
1.1 虚拟 DOM
首先,我们从浏览器的组成来说。
浏览器一般由七个模块组成,User Interface(用户界面)、Browser engine(浏览器引擎)、Rendering engine(渲染引擎),后面讲到 Vue 组件文件的时候,还会介绍 Vue 对象中提供的 render 函数,用来把提供过来的 虚拟DOM 实际渲染!、Networking(网络)、JavaScript Interpreter(JS 解释器)、UI Backend(UI 后端)、Date Persistence(数据持久化存储)
其中渲染引擎 负责解析DOM文档和CSS规则并将内容排版到浏览器中显示有样式的界面,也有人称之为排版引擎 浏览器内核其实说的也是它。
而 JS 引擎是用来解释执行JS脚本的模块,如 chrome的V8 引擎、JavaScriptCore
所以当我们通过 JS 操作 DOM 的时候,实际上涉及到两个线程之间的通信,由此带来了一些性能上的损耗。这意味着频繁地操作 DOM,肯定是消耗资源较大的
- 实际渲染之前只对 JS 对象进行更改和处理
虚拟 DOM 是第一个优点
: 见名知意,虚拟DOM 即 虚拟的DOM,是将整个 文档的结构构建成一棵 虚拟的DOM树。每个虚拟的DOM主要包含三个属性,即 tag、props、children。根据这棵非常细节的树,我们可以进行实际的渲染。
- diff 算法,进而提高了 效率 (改善了 虚拟 DOM 效率逊于原生 JS 的弊端)
这是第二个优点
: 虽然看似很高大上,但实际上 虚拟 DOM 技术,无非也是要去渲染实际的 DOM,而且还要对其 进行 更改。所以我们就得引入 优秀的算法,来检查 前后的差异,然后 尽最最大限度地减少DOM操作以及DOM操作带来的排版与重绘损耗,从而才可能提高性能! 所以,所以,所以。如果是简单的项目,就没必要用什么 Vue 了 ~,因为 只有在一些特殊场景或复杂的情况下,虚拟 DOM 技术的性能才比 原生 JS 要好。比如说需要操作修改的 DOM 太多,太杂了。你自己甚至都不知道哪个需要改,哪个不需要。但是 你用 虚拟DOM 的 diff 算法,就能给你飞快的匹配出来哪里有差异。
- 基于 JS 所以跨平台
1.2 双向数据绑定
Vue实现双向绑定的核心机制是基于其响应式系统。下面简要说明Vue实现双向绑定的主要步骤:
- 响应式数据: Vue通过
Object.defineProperty
方法劫持(或拦截)对象的属性,将对象的属性转化为“响应式的”,即当属性值发生变化时,能够触发相关的操作。这一步骤实现了数据的观察和依赖追踪。
let obj = { // 比如声明一个 obj 对象
counter: 0
};
let value = obj.counter; // 把这个值拿到
// 用 Object.defineProperty 进行劫持
Object.defineProperty (obj, 'counter', {
get() {
return value;
},
set(newValue) {
value = newValue;
console.log('Counter changed:', newValue);
}
});
obj.counter = 1; // 触发监听,打印 'Counter changed: 1'
// 如果是多个属性:
let obj = {
prop1: 1,
prop2: 2
};
function defineReactiveProperty(target, property) {
let value = target[property];
Object.defineProperty(target, property, {
get() {
return value;
},
set(newValue) { // 数据的 setter 方法
value = newValue;
console.log(`${property} 变化了:`, newValue); // 这里可以是 Watcher 监听,来提示构建虚拟DOM和渲染的方法,数据变化了
}
});
}
// 遍历属性并设置监听
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
defineReactiveProperty(obj, key);
}
}
obj.prop1 = 3; // 输出:prop1 变化了: 3
obj.prop2 = 4; // 输出:prop2 变化了: 4
// 由于多个属性的时候 Object.defineProperty 可能会比较费劲,所以可以使用 Proxy 代理
let obj = {
prop1: 1,
prop2: 2
};
let handler = {
set(target, property, value) {
console.log(`${property} 变化了:`, value);
return Reflect.set(target, property, value);
}
};
let proxy = new Proxy(obj, handler);
proxy.prop1 = 3; // 输出:prop1 变化了: 3
proxy.prop2 = 4; // 输出:prop2 变化了: 4
- 模板编译: Vue 使用模板编译器将模板转化为渲染函数。在模板中,可以使用
v-model
指令来创建表单
的双向绑定。例如:
<input v-model="message">
v-model
指令是 Vue.js 提供的一个用于实现表单元素与 Vue 实例数据双向绑定的指令。它的作用是将表单控件的值与 Vue 实例中的数据进行关联,实现数据的自动同步。
注意哟,你这个标签,你这个文件,都是要先经过 模版编译器去处理的。
- 生成渲染函数: 模板编译之后,会生成一个渲染函数(后期会接触到的 render() 函数)。这个渲染函数负责将数据和模板结合起来,生成实际的DOM元素。
- 生成Watcher(监听器): 在渲染函数执行时,Vue会创建一个Watcher对象。Watcher的作用是在数据发生变化时,触发相应的更新操作。
- 绑定DOM事件: 对于
v-model
指令,Vue会在生成的DOM元素上绑定input
事件。当用户在输入框中输入内容时,触发input
事件。 - 数据变更触发更新: 当用户输入内容导致数据变化时,由于响应式数据的特性,触发了数据的
setter
方法。这会通知Watcher对象,表示数据发生了变化。说白了就是监听到了。 - Watcher通知更新: Watcher接收到数据变化的通知后,会执行相应的更新操作。这可能涉及到重新计算虚拟DOM树,比对前后的变化,然后更新实际的DOM元素 再次进行渲染。
- 实现双向绑定: 在这个过程中,由于数据的变化是通过响应式系统中的
setter
方法通知的,而v-model
指令绑定了input
事件,因此在数据变化时,触发了对应的DOM元素的更新,实现了双向绑定。简单来说,就是我们这个监听,是通过响应式系统的 setter 方法进行通知作为前提的,那么你无论这个数据怎么变的(无论是前端界面上,我们改动数据会触发Vue擅自绑定的事件,去更改 data 里面的值。还是说我们在 Vue 的 js 代码那里直接进行更改。)它都会触发 Watcher 监听,然后都会 创建一个新的 虚拟DOM树,再去进行比对之后,也都会进行实际的DOM渲染,这可不就是所谓的双向数据绑定嘛。。。
1.3 什么是 CDN
CDN(Content Delivery Network)是一种通过分布在全球各地的服务器来提高网络内容传输速度和性能的网络架构。CDN通过在离用户更近的服务器上存储和提供内容,减少了数据传输的距离,从而加速了内容的加载和呈现。比如,我家是沈阳大街的,那你的服务器啊~ 要是就在沈阳,那可就得劲儿 了 ~
这个玩意其实在早期的时候,就有很多人想搞!大家想一想,如果你想获取到一个网络资源,它存储位置的服务器距离你很近的话。那岂不是妙哉呀 ~ 特别是有墙的限制的时候。
举个例子:GitHub 的访问问题,至今都不太友好。就说我们后面用 vue-init 去构建 vue2 项目的时候,由于 CMD 不走代理,可能你设置完代理也没啥太大软用 ~ 所以你只能去 配置本地的 Host 解析文件,然后让我们 能够不FQ的情况下,正常访问 github,至此才能 不卡在 download template 这样的描述上.... 我其实呢,当时就觉得很恼火。然后察觉到这个脚手架也是真的挺方便的,而且固定不变,基本上是不会变化什么内容的。索性就大概花了 3 ~ 4 小时(毕竟第一次 开发 npm 包)开发了一个不需要经过代理、不需要设置 Host 文件,就可以使用的 脚手架工具。原理很简单,我非常暴力的把用 vue-cli 生成的那些项目模版,都上传到 我个人 Gitee 上面了。然后下载这些模版的时候,就从我的 Gitee 仓库里面下载就完事了。国内开源社区,所以肯定是秒下!
npm install mqyvue2-cli -g
mqyv2 list # 查看支持的模版
mqyv2 init 项目名 # 默认下载 webpack-simple
mqyv2 init 项目名 模版名 # 指定项目模版去下载
CDN 通常是用来远程引入 一些 前端用到的资源文件,现在目前 都习惯使用 cdn 的方式远程导入一些资源。
比如:bootstrap.css
vue.js
都是如此。
1.4 MVVM 模式
如果说 SSM 的整合,是搞定了WEB开发中后端的便捷性。那么 Vue + 各种模版 + 各种第三方库 就可以搞定前端的便捷性。
MVC 模式:M(model)+ V(view)+ C(controller)
MVVM 模式:M(model) + V (view) + VM(viewmodel)
viewmodel:是连接视图和数据的中间件(而 Vue.js 就是 viewmodel 层的实现者之一)
第二章·常用指令
2.0 插值表达式
当你在 Vue.js 模板中需要显示动态数据时,你可以使用插值表达式。插值表达式会将 Vue 实例中的数据绑定到 HTML 中,使得页面能够根据数据的变化而动态更新。
插值表达式使用双大括号 {{ }}
包裹要显示的变量或表达式。例如:
<div id="app">
<p>{{ message }}</p>
</div>
在这个例子中,{{ message }}
是一个插值表达式,它会被 Vue.js 解析为 Vue 实例中名为 message
的数据。当 message
的值发生变化时,页面上对应的文本内容也会随之更新。
在 Vue 实例中,你需要定义一个名为 message
的数据,并将其挂载到 Vue 实例上:
new Vue({
el: '#app',
data: {
message: 'Hello, Vue.js!'
}
});
现在,当页面加载时,插值表达式 {{ message }}
会被替换为 Hello, Vue.js!
,并显示在页面中。如果你稍后更新了 message
的值,比如 message
被修改为 'Welcome to Vue.js!'
,那么页面上相应的文本内容也会更新为新的值。
总之,插值表达式是 Vue.js 中用于显示动态数据的一种简洁而强大的方式,它使得页面能够根据数据的变化而实时更新,从而实现了响应式的用户界面。
- 与条件语句结合:
<p>{{ isLogged ? 'Welcome, User!' : 'Please log in.' }}</p>
2.1 v-bind:标签属性
v-bind:标签属性
:可以绑定 标签上的任何属性
:标签属性
:v-bind:标签属性 的缩写形式 ...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用 v-bind 绑定 href 属性 -->
<a v-bind:href="url">Visit Vue.js Website</a>
<a :href="url">Visit Vue.js Website</a>
{{url}}
</div>
</body>
<script>
new Vue({
el: '#app',
data: {// 定义一个变量来存储链接地址
url: 'https://vuejs.org/'
// 诶?如果 bind 属性那里用到的也是 data 里面定义的属性,那么不就代表着 {{data}} 插值表达式与它是一样的数据表示了嘛
}
});
</script>
</html>
你看到的 v-bind
被称为指令,指令带有前缀 v-
2.2 v-model (表单元素专属)
v-model
能轻松实现表单输入和应用状态之间的双向绑定。
实际上绑定的是表单元素的 value
属性以及与其相关的 input
事件。具体来说,v-model
在不同类型的表单元素上会绑定不同的属性:
输入框(text、textarea):
<input type="text" v-model="message">
总体来说,v-model
会在不同的表单元素上绑定相应的属性,并通过相应的事件来实现数据的双向绑定。这使得在表单元素的值发生变化时,相关的数据也会跟着变化,反之亦然。
不知道大家会不会意识到一个问题:这样子频繁的变。。是不是影响性能呀?如果想个稳妥的办法,怎么解决呢?别着急,我们后面会学到一个 修饰符直接就解决这个问题。
2.3 事件绑定:v-on:标签的事件
v-on
是 Vue.js 中用于监听 DOM 事件的指令。它可以在 Vue 实例中绑定一个或多个事件监听器,并在触发这些事件时执行相应的 Vue 实例方法或者内联 JavaScript 表达式。
2.3.1 基本用法:
v-on
指令的用法有两种:缩写 @事件
- 监听事件并执行方法:
<button v-on:click="handleClick">Click me</button>
<script>
new Vue = {
el: "#app",
data: {
},
methods: {
handleClick() {
alert("点击了按钮")
}
}
}
</script>
这个例子中,handleClick
是 Vue 实例中的一个方法,当按钮被点击时,Vue 将调用 handleClick
方法。
- 内联 JavaScript 表达式:
<div id="app">
<button v-on:click="alert('Button clicked')">Click me</button>
<button @click="flag = !flag"> <!--你内联你的,哈哈 ~ 我被vue绑定,当然也可以用 vue 的数据-->
</div>
<script>
new Vue({
el:"#app",
data: {
flag: true
}
})
</script>
这个例子中,内联 JavaScript 表达式 alert('Button clicked')
会在按钮被点击时执行。
2.3.2 事件修饰符
v-on
指令还支持事件修饰符,用于对事件进行更精细的控制:
.stop
:阻止事件继续传播。即不会向外层标签,继续触发事件(冒泡效应,即子标签触发的了事件,会冒泡连续的向外触发事件。)
<div v-on:click="parentClick">
<button v-on:click.stop="childClick">Click me</button>
</div>
在这个例子中,当点击按钮时,按钮的点击事件会被触发,但是点击事件不会向上传播到父元素 div
,因为我们使用了 .stop
修饰符,它阻止了事件的进一步传播。因此,parentClick
方法不会被调用。
.prevent
:阻止事件的默认行为。就是标签本身可能默认就有一些功能行为,但是用该修饰符就可以阻止掉!
<form v-on:submit.prevent="submitForm">
<button type="submit">Submit</button>
</form>
在这个例子中,当表单提交按钮被点击时,submitForm
方法会被调用,并且使用了 .prevent
修饰符来阻止表单的默认提交行为,即页面不会刷新或跳转到指定的 URL。
.capture
:使用事件捕获模式。这会使得事件触发从外到内扩散!
<div @click.capture="divHandler">
<button @click="btnHandler">点击</button>
</div>
.self
:只在事件发生在该元素本身时触发处理函数。你们随便折腾,我不参与。
<div @click.self="divHandler" style="background: red;">
<button @click="btnHandler">点击</button>
</div>
.once
:事件只触发一次。.passive
:指示滚动事件的默认行为是否应该立即执行,而不会等待执行事件处理程序。
.passive 修饰符通常用于提高页面滚动性能。当你在滚动时,浏览器会执行默认的滚动行为(例如,滚动页面或元素)并且执行你添加的滚动事件处理程序。然而,有些情况下,如果滚动事件处理程序内部没有执行任何阻止滚动的操作,可以告诉浏览器立即执行默认的滚动行为,而不用等待 JavaScript 的执行结果。
在 Vue 中,你可以使用
.passive
修饰符来声明一个滚动事件处理程序,并告诉浏览器在调用事件处理程序之前立即执行默认的滚动行为。这可以提高滚动性能并避免不必要的延迟。
<div id = "app">
<div @scroll.passive="handleScroll">
<!-- Your scrollable content here -->
</div>
</div>
<script>
new Vue( {
methods: {
handleScroll() {
// 滚动事件处理逻辑,有了.passive 就不会去等待它处理完,会先去执行默认的滚动行为
}
}
})
</script>
在这个例子中,当页面滚动时,handleScroll
方法会被调用。通过使用 .passive
修饰符,浏览器可以立即执行默认的滚动行为,而不用等待 JavaScript 的处理。
2.4 v-once(我个人 => 戏称 "Vue 常量")
v-once
声明插值表达式的数据绑定只用一次,不会再继续更新!
2.5 v-html、v-text
v-html = "变量/属性"
:可以内嵌 html 代码
v-text = "变量/属性"
:只能内嵌纯字符串文本
<div id = "app">
<div>
<!-- 使用 v-html 渲染 HTML 代码 -->
<div v-html="htmlContent"></div>
<hr>
<!-- 使用 v-text 渲染纯文本字符串 -->
<div v-text="textContent"></div>
</div>
</div>
<script>
new Vue({
data() {
return {
htmlContent: '<h1>Hello, <em>Vue.js</em>!</h1>',
textContent: 'Hello, Vue.js!'
};
}
})
</script>
在这个例子中,htmlContent
包含了一个包含 HTML 标签的字符串,而 textContent
只是一个纯文本字符串。使用 v-html
指令时,Vue.js 将会解析 htmlContent
中的 HTML 代码,并将其作为实际的 HTML 元素进行渲染;而使用 v-text
指令时,Vue.js 将会将 textContent
视为纯文本字符串,并将其直接显示在页面上。
第三章·其它常用的修饰符
常用的按键修饰符和鼠标修饰符可以用于 Vue 中的事件处理:
3.1 按键修饰符:
.enter
:回车键.tab
:Tab 键.delete
:删除键(不是 Backspace).esc
:Esc 键.space
:空格键.up
:向上箭头键.down
:向下箭头键.left
:向左箭头键.right
:向右箭头键
3.2 系统修饰符:
.ctrl
:Ctrl 键.alt
:Alt 键.shift
:Shift 键.meta
:Meta 键(在 Windows 键盘上是 Windows 键,在 Mac 键盘上是 Command 键)
3.3 鼠标修饰符:
.left
:鼠标左键.right
:鼠标右键.middle
:鼠标中键
这些修饰符可以与事件一起使用,例如:
<button @click.enter="submitForm">提交</button><!-- 这个用的最多吧,哈哈 ~ -->
<input @keydown.ctrl.83="save"> <!-- 按下 Ctrl + S 键保存 -->
<div @mousedown.right="showContextMenu">右键点击显示上下文菜单</div>
3.4 .number
修饰符
转数值修饰符是指 Vue.js 中的 .number
修饰符,它用于将用户输入的值转换为数字类型。当你在表单元素上使用 v-model
时,如果想确保绑定的值是一个数字,可以在输入框上使用 .number
修饰符。
<div id = "app">
<input type="text" v-model.number="age">
</div>
<script>
new Vue( {
el:"#app",
data() {
return {
age: 0 // age 将始终是一个数字
};
}
});
</script>
3.5 .lazy
修饰符
.lazy
是 Vue.js 中用于 表单元素的修饰符之一,它通常用于延迟触发 v-model
的更新,直到用户进行特定的交互操作(例如失去焦点或按下回车键)。这有助于提高用户体验,特别是在处理输入框中的大量文本时。
使用 .lazy
修饰符时,Vue.js 将等待特定的交互操作后再更新绑定的数据,而不是在每次输入时都立即更新。这样可以减少更新频率,从而提高性能。
<div id = "app">
<input type="text" v-model.lazy="message">
</div>
<script>
new Vue({
el:"#app",
data() {
return {
message: ''
};
}
});
</script>
第四章·计算属性与watch监控
4.1 计算属性
有一些函数返回完一个 结果之后,其实就不需要再去调用了。所以为了提高效率,就发明了 计算属性!
简单来说:计算属性指的是把计算的结果缓存起来放到了与方法同名的属性里面。注意这个同名属性里面的值是缓存机制的。即只要 该值的来源并没有发生变化,那么就不会重新计算。(例如:来源是 data 中的数据,然突然 这个数据变化了,那么这个计算属性就会再次调用这个同名方法,去获取这个变化的数据,然后赋值给同名的属性。 )
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{getCurrentTime}}
</div>
</body>
<script>
var app = new Vue({
el: "#app",
computed:{
getCurrentTime:function (){
return new Date().getTime(); // 这个对象如果我们能拿到的话,然后能让它发生改变,那么 computed 也会重新计算。但是我觉得 拿不到,毕竟你这里是 直接 new 的。都没有用变量去接收。
}
}
})
</script>
</html>
4.2 重新计算
如果是返回的 data 中的属性,那么 data 属性值一变,也就是依赖的值变化了。那么计算属性就会重新计算
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button type="button" @click = "spanClick()">点击</button>
{{getCurrentTime}}
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data:{
date: new Date().getTime()
},
methods: {
spanClick:function(){
this.date = new Date().getTime()
console.log("更新了 data 中的 date")
}
},
computed:{
getCurrentTime:function (){
return this.date; // 来源值变化,那么就会重新计算
}
}
})
</script>
</html>
4.3 watch 监控
用脚趾盖去想,都知道 Vue 肯定支持这种监控的玩法。因为 watch 去实现 双向数据绑定的核心也是监控。
由于,我们可能 在某些时候,被 Vue 管理的变量/属性 发生变化时,不一定只是做 单纯的 双向数据绑定,可能还会有一些其他的 处理操作。所以我们 需要有这样的 watch 监控!这个其实就是 AOP 思想了,方便我们做切片编程呀。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{str}}
<input type="text" v-model="str">
</div>
</body>
<script>
var vue = new Vue({
el: "#app",
data:{
str : "hello world"
},
watch: {
// 监听 str 这个数据
str:function (newValue, oldValue){
console.log("str 发生变化了,放心我监控着呢 ~");
console.log("oldValue => " + oldValue)
console.log("newValue => " + newValue)
}
}
});
</script>
</html>
第五章·流程控制语句
5.0 <template>
在 Vue 中,<template>
标签是一个特殊的占位符,用于包裹一段 HTML 代码,但它不会在渲染最终的 HTML 结构中留下任何痕迹。换句话说,<template>
标签在渲染时会被忽略,只起到了组织结构和作用域的作用。
与之相比,使用 <div>
标签包裹模板内容也是可以的,但会在最终的渲染结果中可能会生成额外的 <div>
元素,这就可能对样式和布局产生影响。因此,为了避免不必要的 DOM 结构,使用 <template>
标签更为合适。
简单来说,如果你用 div 包裹,然后确定了它的内部内容全部需要渲染,最后就可能会 把 外层这个没jb用的 div 渲染上。(如果这个 div 确实没用的话。。。)但是,你用 template 的话,就不会出现这样的问题,它只会渲染 包裹的内容。
5.1 分支语句
5.1.1 if 家族
- v-if:条件成立,那么该标签就会生成
- v-else-if:一般与 v-if 在其上,搭配着使用。会进而的判断第二个条件,如果上一个标签判断的条件成立了,也不会走这一条判断。
- v-else:前面的条件都不成立的时候,我们会用到它。
- v-show:实际上就是让该元素的 display 样式属性设为 none,起到了隐藏的效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.9/vue.js"></script>
<body>
<div id="app">
<div v-if="flag">if成立</div>
<div v-else-if="flag1">else if 成立</div>
<div v-else>前面所有条件都不 成立</div>
<button @click = "flag = !flag">点击</button>
<button v-show="false" @click = "flag1 = !flag1">点击1</button>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
flag: true,
flag1: false
}
})
</script>
</html>
当使用 Vue.js 来进行条件渲染时,<template>
标签通常用于包裹需要根据条件进行显示或隐藏的一组元素。下面是一个简单的例子:
<template>
<div>
<h2>条件渲染示例</h2>
<button @click="toggleShow">Toggle Show</button>
<template v-if="show">
<p>This content is conditionally rendered.</p>
<p>It will be displayed when the 'show' data property is true.</p>
</template>
</div>
</template>
<script>
export default {
data() {
return {
show: false
};
},
methods: {
toggleShow() {
this.show = !this.show;
}
}
};
</script>
5.1.2 switch
在 Vue 中,你可以使用 v-switch
指令来实现类似 switch-case
的逻辑。虽然 Vue 模板中并没有原生的 switch-case
结构,但可以通过 v-switch
指令来模拟它的功能。下面是一个简单的示例:
<template>
<div>
<div v-switch="selectedOption">
<!--用 div 也可以,但是如果条件成列了,外层的 dib 就不会消失了,哈哈。-->
<template v-case="'option1'">
<p>选项1被选中</p>
</template>
<template v-case="'option2'">
<p>选项2被选中</p>
</template>
<template v-case="'option3'">
<p>选项3被选中</p>
</template>
</div>
</div>
</template>
<script>
export default {
data() {
return {
selectedOption: 'option2'
};
}
};
</script>
5.3 循环语句
注意,这里跟 我们学 Thymleaf 的时候一样,它的循环语句是要作用在需要 遍历生成的标签上的,而不是父亲标签。。否则就会造成父亲标签大量的遍历生产。哈哈哈 ~ 作用于谁很重要!
5.3.1 v-for
v-for
指令在 Vue.js 中用于遍历数组或对象,并生成对应数量的元素或组件。它的基本语法格式如下:
<div v-for="(item, index) in items" :key="index">
{{ item }}
</div>
(item, index)
: 这里的(item, index)
是解构的语法,用于声明循环变量。item
是数组或对象的当前元素,index
是当前元素的索引。你也可以只使用item
,不声明index
。items
: 这是被遍历的数组或对象。:key="index"
: 这是为每个循环生成的元素指定唯一的 key 值。这个 key 值用于帮助 Vue 识别每个元素,并提高性能。在遍历数组时,通常使用数组的索引作为 key 值。
下面是一个示例,演示了如何使用 v-for
遍历数组:
<div id="app">
<div v-for="(item, index) in items" :key="index">
{{ index }}: {{ item }}
</div>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
items: ['apple', 'banana', 'orange']
};
}
});
</script>
第六章·其它知识
6.1动态改变样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.small {
width: 100;
height: 100;
background-color: green;
}
.big {
width: 500px;
height: 500px;
background-color: green;
}
#redID {
width: 200px;
height: 200px;
background-color: red;
}
.www {
width: 700px;
height: 500px;
}
</style>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<body>
<div id="app">
<!--{类名:true} 这种方式大家可以记下,以前我们 css 没见过,这种方式可以选择 这个类名作为 该标签的类名。-->
<div v-bind:class="{small:flag}"></div>
<div :class = "className"></div>
<div :id = "idName">
<div :class = "[a,b]"><!--数组 多 class 样式-->
<button type="button" @click = "flag = !flag">点击</button>
</div>
</body>
<script>
var vue = new Vue({
el: "#app",
data:{
flag: false,
className: "big",
idName: "redID",
a: "www",
b: "big"
},
methods:{
haha:function (){
this.flag = !this.flag
}
}
})
</script>
</html>
6.2 键值对不能出现 短杠 -
有些时候,我们的 style 是有 类似于 background-color
这样的键
那么我们在用 VUE 的数据绑定的时候,只需要写成 首字母小写驼峰原则就可以了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.9/vue.js"></script>
<body>
<div id="app">
<!--看下方的写法-->
<!--background-Color VUE 的数据绑定中只能写成小驼峰原则的 backgroundColor-->
<div :style="{backgroundColor: bc}" class="mywidth"></div>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
bc: "blue"
}
})
</script>
</html>