梦入琼楼寒有月,行过石树冻无烟

函数


函数(function)是将一个对象转化成另外一个对象的规则,假设出f(x)=x^2,那么就会定义出一个函数f,他会将任何数变为自己的平方,假设你将f(2)=4的时候,那么f作为函数是被引用f(2)所对应的数值是4,这样的道理在计算机中也依然运用。


之后我们将f(x)=x^2修改为g(x)=x^2,我们可以把x看作变量,我们可以随便的赋值,在定义域中,仅仅可以包含一个大于或等于零的数值,我们通常将这类数称之为:“非负数”。

定义域

例如我们新建一个函数g(-1/2)他的定义域是非负数,而f(-1/2)=1/4,但是 g(-1/2)没有被定义,值得注意的是,函数g拒绝他非定义域中的一切数值,但是由于gf有类似的数据,换而言之可以说g的数据是基于f得来的,且还拒绝非负数外的数据,所以自然而然要比函数 f小一点,且函数g是由限制f的定义域所产生的。

对于定义域,目前我们将h(x)=x,那么假设h的定义域是所有动物的集合,那么这样我们就可得到h(马)=4,其中马的数值是4,因为所有动物的腿都是非负数,所以函数 h上的都是所有非负整数的集合

一个函数必须给每一个有效的输入指定唯一的输出,为了印证这个道理,首先我们假设你有一只狗狗,他的名字叫 one,他每次吃饭的时候都会吐出来,one 将食物变成了很恶心的东西,我们此时尅通过使用 j(x)=onex是 one 每次吐出的颜色,其中x的定义域是one每次吃的食物集合,而上域是一切有可能输出的颜色集合。

为了使得遵守一个函数必须给每一个有效的输入指定唯一输出,我们假设 one吃了面包,吐的时候是黑色的,如果有时候吐的是黑色,有时候吐的是白色就不符合这个定理。

值域

对于值域,我们只需要注意到当我们输入的时候,他是定义域,而当他输出的时候,他是一个值域,值域虽然是上域的子集,但值域与上域的区别就是,上域是可能输出的集合,而值域确实实际上输出的集合。

函数的区间表述法

区间(interval),假设函数上域R包含了所有有可能输出的集合,那么定义与也有肯能会和上域R差不多。就像是{x:2 ≤ x < 5}这样的连通区间,而他的本质意思是介于2和5之间的所有数,包括2,但不包括5(”≤” 可以包括 “x = 2”,也可以包括小于”2”以下的数,但”<”只能包括小于”5”的数,不能包含”5”),因此为了让数学的表示更加简洁,出现了区间表示法。

闭区间

区间表述法主要分为(a,b)代表了开区间以及[a,b]表示闭区间,其中闭区间是指a ~ b端点间的所有实数,并包括 a,b。如 [2,5]代表了所有介于 “2” 和 “5” 之间的实数集合,同时也包括了 2 and 5,按照开头的表述方法就是 x:2 ≤ x ≤ 5

开区间

开区间,主要表示不想包括的,通常也必须以[]表示,假设(2,5)及表示介于“2” 和 “5” 之间的所有实数集合,但不包含“2”和“5”,按照开头的表示方法就是x:2 < x < 5

半开区间

半开区间主要就是闭区间开区间的一种集合,将他们分别混合组成为(2,5]那么将会表述介于2和5之间的所有实数,但不包括”2”,只包括小于“2”的数,包括“5”和以下的实数。,按照开头的表述方法就是x:2 < x ≤ 5

那将半开区间换过来就是[5,2)表述出介于2和5之间的所有实数,但不包括”5”,包括“2”,也就是咱一开始的表述方法[x:2 ≤ x < 5]

主要表述无穷大(infinite)假设(2,∞)那么将会表示出大于 2 但不包括”2”的所有实数,当然也可以用-∞来表示出无穷小,也可以配合半开区间使用,例如:[a,∞)则表示出大于”2”且包括”2”的所有实数

什么是微积分

微积分(Calculus)主要分为微分(Differentiation)以及积分(Integration),重点研究包括了极限、函数、切线、积分、微分及其应用。通常积分用于计算曲线面积,微分用于计算瞬时速度(物理瞬时速度,即近似值)。

常用符号

通常的情况下,微分会通过使用dx/dy等进行代替,其中d源于拉丁语中的差(Differentia)的地一个字母。

而积分符号,会通过使用 来进行代替,他也是拉丁语中总和(Summa)的第一个字母所拉长的效果。

pinia 基础

pinia overview

Pinia 是一个适用于 Vue2~3 的跨组件共享状态维持项目,与 vuex、bus 等原理类似,但都比前者简单高效许多,在 2019 年 11 年重新被设计使用,其维护团队为 Vuejs。

特点在于更加容易调试,可以使得 store 出现在其他组件中并使用,以及在不重新加载页面的情况下修改 store 共享数据,并保持现有状态,同时占用空间小的特点。

1
反观 Vuex 和专注于兄弟组件之间通信的 Bus 相比,Pinia 根据简单和[官方](https://github.com/vuejs/pinia)团队维护等特点深受开发人员喜爱。

Store

首先,Pinia 拥有和 Vuex 类似的特性及功能(毕竟是同类型项目),而 Store 的定义主要是可以让该数据被所有组件共享。

在本文中,我们主要通过 vue-cli 来构建 vue3 project,并使用 vue add vue-cli-plugin-pinia 来添加 pinia 支持。

之后可以在 src/store/ 下看到其自动帮我们所创建的 pinia store,之后我们可以重命名或者直接在此基础上进行开发,来进行共享数据。

同时他也会在 mian.js 文件下为我们引入 pinia 并使用,返回给 Vue。

在使用的时候,你需要记得,在 store 目录下的共享数据内的方里,默认的会为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { defineStore } from 'pinia'  

export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
getters: {
double: state => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})

我们需要记得导出的方法,也就是 useCounterStore 之后在组件中直接 import { useCounterStore } from "@/stores/index" 这么引用,然后在 setup() 语法糖下赋值给 store

1
2
3
4
5
6
7
  setup() {  
const store = useCounterStore()
return {
store,
}
},
})

这之后在 template 下,就可以通过插值 {{ store.count }} 来直接进行使用了。

1
这在官方文档关于定义 Store 中有详细的描述:“并且它需要一个唯一的名称,作为第一个参数传递”

State

StateStores 所定义的中心部分,也就是共享数据\状态的起点,在 PInia 中会被定义为返回初始的状态函数:

1
2
3
4
5
6
7
8
9
import { defineStore } from 'pinia'  

export const useTabStore = defineStore('tab', {
state: () => ({
/*
return {Array}
*/
rowItems: []
})

Getters & Actions

Actions

在此之前,我们需要知道,getters 是被动获取,也就是说需要有组件取调用这个方法。而 Actions 则是可以实现在文章开头,Pinia 所说的特性之一:”Stores appear in components where they are used”,即可以在组件中实现将组件的数据,传入到 State 中。

1
需要注意的是,在一般情况下,Vuex、和 Bus 很难去解决组件和组件之间的传值,需要通过 emit,props 等方法,先将兄弟组件的数据传给父组件,父组件再将数据传给兄弟组件,以此来实现传值。

在组件传值之前,我们首先需要在 store 下定义参数,准备接受组件所传来的数据,并之后传给 state() 下的共享状态变量 rowItems:

1
2
3
4
5
6
7
8
9
10
11
12
13
import { defineStore } from 'pinia'  

export const useTabStore = defineStore('tab', {
state: () => ({
/*
return {Array} */ rowItems: []
}),
actions: {
addItem(name) {
this.rowItems.push(name)
},
},
})
1
在真实的开发环境中,一般先定义 ```state``` 下的共享变量,再去定义 ```actions```,之后才是 ```getters```

上述 Code 中,我们主要通过 this.rowItems.push 方法,来将获取到的 name 参数传递给 state,之后 getters 来获取 state 下的共享数据/状态变量。

下面,我们需要通过在传递数据的组件内,引入 import { useTabStore } from "@/stores";,之后按照 setup() 语法糖:

1
2
3
4
5
6
7
8
export default defineComponent({  
setup (props, {emit}) {
const tab = useTabStore()
return {
tab
}
},
})

由于我们是按照 setup() 语法糖的 Vue3 的写法,那么基本上数据是在 setup() 下的 return 来进行编写,我们需要做的就是通过 tab.addItem(value) 将数据传递给 stores,之后就完成了组件的传递。

Getters

可以理解为获得数据,他与 ```state``` 所定义的数据/状态是完全等价的,且处于被动,也就是说可以通过组件访问 ```getters``` 所关联的 ```state``` :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

```js
import { defineStore } from 'pinia'

export const useTabStore = defineStore('tab', {
state: () => ({
/*
return {Array} */ rowItems: []
}),
getters: {
items: (state) =>
state.rowItems.reduce((items, item) => {
console.log({name: item},'{name: item}')
items.push({name: item})
return items
}, []),
},
actions: {
addItem(name) {
this.rowItems.push(name)
console.log(name,'->>>>>>YES')
},
},
})

在上述的 Code 中,我们首先在 state 先定义共享状态 rowItems 变量,当获取数据的时候,我们需要他可以循环遍历,那么就通过 reduce之后 方法来按照数组的顺序来进行返回。

然后通过 push 方法将元素添加至数组的末尾,最后返回 items 变量,这是通过 actions 所获取到的数据并输出。

在数据的获取部分,我们需要在组件中同样引入 import { useTabStore } from "@/stores/index",然后按照 setup() 语法糖的写法:

1
2
3
4
5
6
7
8
export default defineComponent({  
setup (props, {emit}) {
const tab = useTabStore()
return {
tab
}
},
})

之后通过 template 的模板语法以及 v-forv-bind 就可以完成共享数据的循环输出:

1
2
3
<li v-for="item in store.items" :key="item.name">  
{{ item.name }}
</li>

vue and axios

Get or Post

在上一个章节中我们了解到 Axios 是一个基于 Promise 的网络请求库,通常运用在 node.js 中,使得可以完成在原来之前传统开发环境下的 ajax,在此之前,我们还需要通过下述命令完成安装和添加的操作:

1
npm install axios

在安装完成后,我们需要在自己的 Vue 项目中添加 axios 来作为库并进行使用,可以通过 vue add axisoexport default 中定义如下方法:

1
vue add axios

然后在 .vue 文件下 script 元素中的 export default 方法中增加 created() 方法中,以此来调入接口,之后通过:

1
2
3
4
5
created() {
axios.get('').then(function (res) {
console.log(resp)
})
}

通过上述的 code 来请求 api,并输出全部响应到的数据后,我们就可以通过在之前请求相应的数据中进行单个解析:

1
2
3
4
5
6
created() {
const _this = this
axios.get('').then(function (res) {
_this.tableData = res.data.content
})
}

除了上述方法外,我们还可以使用下述方法来进行实现其同样的效果,但主要的区别就是在于代码的可视性。

1
2
3
4
5
6
axios({
method: 'get',
uri: 'API'
}).then(function(res) {
console.log(res)
})

假设你如果要发送 POST 请求,那么我们可以将上述的 Code 改为下述示例:

1
2
3
4
5
6
7
8
axios({
method: 'post',
uri: 'uri',
name: 'administrator',
pass: '123456789'
}).them(res => {
console.log(res)
})

需要注意的是,在上述 POST 请求中,userpass 是 API 中需要我们所传入的信息,当然,这些可以根据实际情况自行进行调整。

1
在 ```created``` 方法中写入 Axios 是为了在加载时第一时间获取到数据,如果是需要触发才会发生的事件,那么建议你在 ```methods``` 方法中定义一个方法事件。

在上述的 code 中,我们首先通过 _this 来解决作用域的问题,并通过 axios 的解析目标 API 所相应的数据(data) 下的 content Key,然之后就需要在数据表格中写入:

1
2
3
4
5
data() {
return {
tableData: null
}
}

由于我们拿到的是数组数据,我们可以通过在其组件外在套一件 template 并通过 v-for 指令来进行循环输出,在此之后,我们就可以通过翻阅 Axios 的官方文档,来满足我们大部分的需求。

Backage

在正常的开发环境中,一般情况下我们很少会直接去使用 Axios 来直接去写入到方法中,更多的情况是定义一个实例 来满足请求(request)\响应(response)拦截器(interceptors) ,这通常被称之为《封装》

在此之前,我们需要在当前的 Vue 项目中率先构建出一个封装目录,可以在 src/request 目录也可以直接在根目录中新建一个 utils 目录进行封装。

实例 (Create)

之后还需要在此目录中创建两个 .js 文件,分别为 request.jsapi.js 两个,并在 request.js 中定义一个实列:

1
2
3
4
5
6
7
import axios from 'axios'

const instance = axios.create({
baseURL: "",
timeout: 10000
headers: {'X-Custom-Header': 'foobar'}
})

在上一段 Code 中, baseURL 是我们 API 的基础 URI,举个例子,假设我的 API 是 https://axios-http.com/zh/docs/instance ,那么 baseURL 就是 https://axios-http.com

而之后的两个参数就是 timeout 超时时间的设置以及 headers 请求头的加入。

拦截器 (Interceptors)

拦截器的定义主要分为 request & response 即请求和相应的拦截,因为 Axios 是基于 promise 上构建的,Code 如下:

1
2
instance.interceptors.request.use(callback, callback)
instance.interceptors.response.use(callback, callback)

在上述的拦截器中,所返回的 callback 中,第一个代表成功,而第二个表示错误的拦截,是不是很像 Promise,现在,我们在此基础上再次进行编写:

1
2
3
4
5
6
7
8
9
10
11
instance.interceptors.request.use(config => {
//
}, er r=> {
return Promise.reject(err)
})

instance.interceptors.response.use(res = > {
return res;
}, err => {
return Promise.reject(err)
})

在上述 Code 中,在请求中,如果有特定需要你可以在 config 中来进行添加你的 Code,这会在请求的同时发送出去,而之后的响应在没有特定需要的情况下,可以直接返回响应即可。

同样的你也可以在这里编写一个处理响应的 Code 在返回,这都根据你的项目需要来进行编写。

1
export default instance;

最后,我们需要通过 Node 所提供的 Model 概念来将我们的实例导出,然后在 api.js 中进行使用

封装

之后在 api.js 文件中,需要引入我们刚刚全部导出的封装,来将他整体引入:

1
import request from '@/request/request.js'

由于我们已经引入了之前的 request.js 实例,之后我们需要在当前文件中写入需要的 API 进行请求:

1
export const GetUser = () => request.get('uri');

而之后的使用我们可以在之前的 .vue 文件中,在 createdmethods 方法,定义一个参数,但在此之前我们还需要引入之前封装的 api.js 文件:

1
2
3
4
5
6
7
8
9
import { GetUser } from '@/request/api.js';

methods: {
UserLogin() {
GetUser().then(function(res) {
console.log(res)
})
}
}

通常 ,在少部分的情况下的功能需求会让我们在请求时加入一些参数,而封装之后的参数部分定义主要可以体现在 Post 请求的发送过程上:

1
export const PostUser = (params) => request.post('uri', params);

假设如果是 POST 方法的请求,那么我们可以在 .Vue 文件的 createdmethods 方法下同样和 Get 一样定义个参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { GetUser, PostUser } from '@/request/api.js';

methods: {
UserLogin() {
GetUser().then(function(res) {
console.log(res)
})
},
PostRegister() {
PostUser({
user: 'administrator',
pass: '123456789'
}).then(res => {
console.log(res)
})
}
}

通过对 axios 的实例封装使得我们可以通过上述 Code 非常简单的来实现对 API 的操作,通过 params 增加了 Code 的可读性和后期维护的成本。

vue and axios

Callbacks and Asynchronous

AXIOS 正如文档中所描述的,它是一个基于 promise用于因此 的网络请求库,即异步(async) 和 同步(await) 同时也在文档中描述了一段故事:

1
2
3
4
5
6
7
8
9
想象一下,你是一位顶级歌手,粉丝没日没夜的询问你什么时候发送新歌,为了从中解放,你承诺(promise)会在单曲发布的第一时间发给他们。你给了粉丝们一个列表。他们可以在上面填写他们的电子邮件地址,以便当歌曲发布后,让所有订阅了的人能够立即收到。即便遇到不测,例如录音室发生了火灾,以致你无法发布新歌,他们也能及时收到相关通知。

每个人都很开心:你不会被任何人催促,粉丝们也不用担心错过歌曲发行。

这是我们在编程中经常遇到的事儿与真实生活的类比:


1. 生产者代码,会做一些事并且需要一定时间,例如通过网络加载数据的 code;
2. 消费者代码,想要在生产者代码完成工作的第一时间就可获得回馈(也就是工作结果),可以理解为粉丝。

而 promise 就是将上述两者连接在一起的特殊 JavaScript 对象,使得可以立即获得相关信息,这也被称之为 “异步”,因为 Promise 是 AXOPS 的基础,所以本章也会从 Promise 开始来进行学习。

在此之前我们需要了解下 Promise 对象,他主要用于表示一个异步操作最终完成的结果,当然也会包含失败的结果值。

Callbacks

又被称之为或调参数,即将一个参数传递给另一个参数的过程被称之为回调,在 JavaScript 回调 (w3schools.com) 这一章节中您可以清除的了解到 callback 的主要用法。

抛出基础问题不谈,Callbacks 主要就针对 调用 两个字来进行深入,以及将参数带入函数中进行计算,完成后回调,这里 W3 的例子是:

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
<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Callbacks</h2>

<p>Do a calculation and then display the result.</p>

<p id="demo"></p>

<script>
function myDisplayer(something) {
document.getElementById("demo").innerHTML = something;
}

function myCalculator(num1, num2, myCallback) {
let sum = num1 + num2;
myCallback(sum);
}

myCalculator(5, 5, myDisplayer);
</script>

</body>
</html>

在上述的 code 中,myDisplayer 函数中的 something 参数被之后的 document…… 方法引入,之后 myCalculatornum1num2 参数通过 myCallback 回调给 sun,之后当 myCalculator 被调用时所添加的参数也会被解析到 sun 这个变量中进行计算,并将 myCalculator 函数绑定返回给 myDisplayer

Asynchronous

异步通常与 Callbacks 一起使用,同样在 w3 这一章节中所提供的例子使得我们可以快速了解 Asynchronous 和 Callbacks 一起使用的范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function myDisplayer(some) {  
document.getElementById("demo").innerHTML = some;
}

function getFile(myCallback) {
let req = new XMLHttpRequest();
req.open('GET', "mycar.html");
req.onload = function() {
if (req.status == 200) {
myCallback(this.responseText);
} else {
myCallback("Error: " + req.status);
}
}
req.send();
}

getFile(myDisplayer);

在异步的定位中,主要将与其他函数并行运行的函数为异步,结合上述的 Code 我们可以知道,getFilemyDisplayer 是同时执行的,这加快了网站加载的速度以及用户的体验。

同样是在 getFile 下的 myCallback 参数,之后该参数返回的则是当前的请求信息和错误,以至于最后如果 GET 请求成功的情况下可以获取到 mycar.html 的上下文信息。

Promise

在了解过回调(callbacks)和异步(Asyncchronous)之后,回归正题,Axios 主要是基于 Promise 来进行构建,那么 Promise 在通过一开始所介绍的 “故事” 内,我们知道,生产者代码需要一些时间,而消费者代码是可以得到反馈的。

Promise Object

1
2
3
4
5
6
7
8
9
10
11
12
let myPromise = new Promise(function(myResolve, myReject) {  
// "Producing Code" (May take some time)

myResolve(); // when successful
myReject(); // when error
});

// "Consuming Code" (Must wait for a fulfilled Promise)
myPromise.then(
function(value) { /* code if successful */ },
function(error) { /* code if some error */ }
);

JavaScript Promise Object 包含了上述中生产者带么和消费者代码的实现,当之后 Promise 执行时,他会调用两个回调方法,如果时结果值那么就 successful,否则 error,这也对应着 Promise Object 所支持的两个属性,状态和结果。

.then()

最终,Promise 会通过 .then() 来返回成功和失败的回调函数,他的概念主要还是 Promise Object 所支持的两个属性,更加详细的可以参考下 MDN 的 Promise.prototype.then() - JavaScript | MDN (mozilla.org) 详细了解具体原理。

最后总结一点是,如果 Promise 返回了一个值,那么 then 将会成为接受(accept)状态,没返回任何值,then 同样会返回接收状态,并将接受状态的回调参数设置为 undefined

假设抛出一个错误,那么 then 也会返回一个拒绝状态,并将错误信息回调到参数值中。但如果是一个接受的 Promise,那么 then 就会将状态设置为 fulfilled,反之则是 rejected

如果遇到一个未定状态(pending),那么 then 所返回的 Promise 也会是未定的,在 W3 中,同样给了我们一个非常简单的例子供我们进行理解:

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
<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Promise</h2>

<p id="demo"></p>

<script>
function myDisplayer(some) {
document.getElementById("demo").innerHTML = some;
}

let myPromise = new Promise(function(myResolve, myReject) {
let x = 0;

// some code (try to change x to 5)

if (x == 0) {
myResolve("OK");
} else {
myReject("Error");
}
});

myPromise.then(
function(value) {myDisplayer(value);},
function(error) {myDisplayer(error);}
);
</script>

</body>
</html>

在上述的 Code 中,同样的有两个最后的状态进行输出,一个是成功的而另一个则是错误的状态信息进行输出,通过 .then() 使得我们可以处理异步中的错误,以及成功返回的信息。

Async/Await

Async

在 async 和 await 还未出现之前,异步编程通常会苦恼当前的开发人员,但在 ECMAScript 2017 中,async/await 通过 promises 使得将异步的编写更加容易和方便,同时增加的阅读性。

我们可以将 async 和 await 拆分下来(虽然 await 离开了 async 些许并没有什么作用),async 可以理解为 promise 中的生产者代码:

1
2
3
4
async function hello() {
console.log("Hello,world!")
}
hello();

上述代码中的 async 同等与传统方法中的 function,之后,我们还需要配合 await 来进行使用。

Await

而之后的 await,他实际上就是 .then,只可以和 async 搭配进行使用,基于 promise 的函数之前。它会暂停代码在该行上,直到 promise 完成,然后返回结果值。在暂停的同时,其他正在等待执行的代码就有机会执行了:

1
2
3
4
5
async function hello() {
return greeting = await Promise.resolve("Hello");
};

hello().then(alert);

顾名思义,也就是在 await 的同时,他会来进行回调的调用,来代替之前我们之前直接一个函数来进行回调,同时他也完成了 then 的部分工作,使得 then 会减少使用。

Vue.js form at v-model

vue 的表单处理主要通过v-model指令,且仅仅限制于在<input>、<select>、<textarea>等HTML表单元素创建双向数据绑定。v-model可以根据HTML控件的类型来自动选取正确的方法来进行更新。

当使用输入法如中日韩等语言时,需要使用 value 绑定,而不是 v-model

需要值得注意的是v-model指令会忽略所有的表单value、checked、selected等属性的初始值,所以需在js内的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

| Name | Info |
| ---------------- | ---------------------------------- |
| text & textarea | 使用value 属性和input 事件 |
| checkbox & radio | 使用 checked 属性 和 change 事件 |
| select | 将以value 作为属性并和 change 事件 |


## Demo
### input
![](https://49812933408852955071488026628034-1301075051.cos.ap-nanjing.myqcloud.com/javascript/vue/vue%203.0/9.vue.js%20form%20at%20v-model.md/2277112239194.png)
当使用 ```v-model``` 绑定 message 属性的时候,通过 Mustache 表达式获取 message 属性值来达到双向绑定的效果。

> 在 ```<input>``` 元素中所设置的 value 默认值将不会被绑定,这是因为 ```v-model``` 指令会忽略所有表单元素的 value、checked、selected 属性的初始值,更或者说该指令只会获取 ```v-model``` 所绑定的 message 属性值。


```js
<ui id="app">
<input type="text" v-model="message" placeholder="echo" />
<p>{{message}}</p>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
message: null
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

checkbox

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<ui id="app">
<input type="checkbox" v-model="message" />
<label>This is message: {{message}}</label>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
message: false
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>
复选框 value 绑定

直接通过 checkbox 的 value 来写入 message 数组当中,当显示的时候也是以数组的形式进行处理。

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
<ui id="app">
<h2>JavaScript</h2>
<input type="checkbox" v-model="message" value="Vue" /><label>Vue</label>
<input type="checkbox" v-model="message" value="Jquery" /><label>Jquery</label>
<input type="checkbox" v-model="message" value="Ajax" /><label>Ajax</label>
<input type="checkbox" v-model="message" value="D3.js" /><label>D3.js</label>
<input type="checkbox" v-model="message" value="Lodash" /><label>Lodash</label>
<h2>Web</h2>
<input type="checkbox" v-model="message" value="Node.js"><label>Node.js</label>
<input type="checkbox" v-model="message" value="Java"><label>Java</label>
<input type="checkbox" v-model="message" value="PHP"><label>PHP</label>
<input type="checkbox" v-model="message" value="GO"><label>GO</label>
<h2>SQL</h2>
<input type="checkbox" v-model="message" value="MySQL"><label>MySQL</label>
<input type="checkbox" v-model="message" value="Redis"><label>Redis</label>
<input type="checkbox" v-model="message" value="SQL"><label>SQL</label>
<input type="checkbox" v-model="message" value="HBase"><label>HBase</label>
<input type="checkbox" v-model="message" value="ORACLE"><label>ORACLE</label>
<hr />
<p>This is message: {{message}}</p>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
message: []
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

radio


对于 radio 类型的 <input> 元素依然可以使用 value 对 message 进行双向的数据绑定

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
<ui id="app">
<h2>JavaScript</h2>
<input type="radio" v-model="message" value="Vue" /><label>Vue</label>
<input type="radio" v-model="message" value="Jquery" /><label>Jquery</label>
<input type="radio" v-model="message" value="Ajax" /><label>Ajax</label>
<input type="radio" v-model="message" value="D3.js" /><label>D3.js</label>
<input type="radio" v-model="message" value="Lodash" /><label>Lodash</label>
<h2>Web</h2>
<input type="radio" v-model="message" value="Node.js"><label>Node.js</label>
<input type="radio" v-model="message" value="Java"><label>Java</label>
<input type="radio" v-model="message" value="PHP"><label>PHP</label>
<input type="radio" v-model="message" value="GO"><label>GO</label>
<h2>SQL</h2>
<input type="radio" v-model="message" value="MySQL"><label>MySQL</label>
<input type="radio" v-model="message" value="Redis"><label>Redis</label>
<input type="radio" v-model="message" value="SQL"><label>SQL</label>
<input type="radio" v-model="message" value="HBase"><label>HBase</label>
<input type="radio" v-model="message" value="ORACLE"><label>ORACLE</label>
<hr />
<p>This is message: {{message}}</p>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
message: []
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

textarea

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<ui id="app">
<textarea v-model="message" placeholder="echo"></textarea>
<p>This is message: {{message}}</p>
<hr />
<p style="white-space: pre-line">This is message: {{message}}</p>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
message: null
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>
元素通常用于处理较多的文字输入,因此对他双向绑定可以使用 [white-space](https://developer.mozilla.org/zh-CN/docs/Web/CSS/white-space) 来处理用户的换行输入。
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

### select
![](https://49812933408852955071488026628034-1301075051.cos.ap-nanjing.myqcloud.com/javascript/vue/vue%203.0/9.vue.js%20form%20at%20v-model.md/1237909103084.png)

```js
<ui id="app">
<select v-model="message">
<option disabled value="">Select</option>
<option value="vue">Vue</option>
<option value="Jqery">Jquery</option>
</select>
<hr />
<p>This is message: {{message}}</p>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
message: ''
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

在上述的code当中,我们主要通过使用 value 来设置 option 被选择时的属性,此时 value 依然会写入 message,之后 <p> 元素对 message 进行数据绑定。

修饰符

在 vue中,自然而然的也为表单处理所加入了一些较为常用的修饰符,如.lazy、.number、.trim,他们分别对输入和输出进行提供了修改:

Name Info
.lazy 当输入完成时在同步信息
.number 将输入的值自动转换为 number类型
.trim 自动过滤首尾空白

.lazy

在未使用 .lazy 的情况下,<input> 所接受到触点事件将会记录我们所写入的信息,自然而然的也会传入到 message 属性中,而 .lazy 的主要作用就是当 <input> 触点事件结束时才开始将数据发送给 message

.trim

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

```js
<ui id="app">
<textarea v-model.trim="message" placeholder="start"></textarea>
<textarea v-model="trims" placeholder="start"></textarea>
<hr />
<p>This is message: {{message}}</p>
<p>This is message: {{trims}}</p>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
message: '',
trims: ''
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

.number

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

> 但需要输入头部数据是 number 类型,否则 ```.number``` 修饰符的作用不大

```js
<ui id="app">
<textarea v-model.number="message" placeholder="echo"></textarea>
<hr />
<p>This is message: {{message}}</p>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
message: ''
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

Vue.js events

v-on 的缩写为 @,其参数为 event即监听对应的事件是否被触发,这主要用法就是绑定事件监听器,事件的类型都由修饰符进行指定。也可监听鼠标、键盘等事件来运行相应的 JavaScript,如 v-on:click="methodName"@click="methodName"

@click

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ui id="app">
<button @click="counts +=1">Add 1</button>
<button @click="counts -=1">Remove 1</button>
<p>This is {{counts}}</p>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
counts: 0
}
}
})
const vm = app.mount('#app')
</script>

@click function

为应对更加复杂的业务环境,v-on 还提供调用 function 的支持,这会让 @click 的功能的监听更加的多样化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<ui id="app">
<button @click="add">Add</button>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
counts: 'Hey,v-on'
}
},
methods: {
add(event) {
alert('This is ' + this.counts)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

内链处理方法

鼠标左击处理也是通过内链直接调用的,所谓内链就是与html 标签元素写在一起即大多数都被称之为内链。

Vue 使用的是 $ 前缀来通过组件实例所暴露自己的内置 API,对于内部还提供了 _ 前缀。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ui id="app">
<button @click="echo('hey,world!',$event)">Add</button>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

修饰符

Name Info Full
click.stop 调用 event.stopPropagation() 阻止捕获和冒泡阶段中当前事件的进一步传播
click.prevent 调用 event.preventDefault() 阻止默认的点击事件执行
.capture 添加事件侦听器时使用capture(捕获) 模式
.self 只当事件从侦听器绑定元素本身触发时才进行回调
```.{keyCode keyAlias}``` 只当事件从特定键触发时才进行回调
.once 只触发一次回调
.left 只当点击鼠标左键时触发
.right 只当鼠标点击右键时触发
.middle 当鼠标中键时触发
.passive 以 { passive: true } 模式添加侦听器

事件的修饰符处理通常是调用 event.stoppPropagation() 方法来进行实现的,但只有纯粹的数据逻辑而不是处理 DOM 事件,因此 Vue v-on 指令提供了修饰符。

我们主要以 prevent 为例,监听其 submit 元素是否被触发,并组织默认的单击事件执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="app">
<form v-on:click.prevent="doThis">
<a :href="home">{{message}}</a>
</form>
</div>
<script>
var App = {
data() {
return {
message: 'Go Jiangxue Team',
home: 'https://www.jiangxue.team/'
}
}
}
Vue.createApp(App).mount("#app")
</script>

或者通过 v-on 的简写 @ 来实现没有表达式的阻止默认行为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="app">
<form @click.prevent>
<a :href="home">{{message}}</a>
</form>
</div>
<script>
var App = {
data() {
return {
message: 'Go Jiangxue Team',
home: 'https://www.jiangxue.team/'
}
}
}
Vue.createApp(App).mount("#app")
</script>

可参考下 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
<!-- 方法处理器 -->
<button v-on:click="doThis"></button>

<!-- 动态事件 -->
<button v-on:[event]="doThis"></button>

<!-- 内联语句 -->
<button v-on:click="doThat('hello', $event)"></button>

<!-- 缩写 -->
<button @click="doThis"></button>

<!-- 动态事件缩写 -->
<button @[event]="doThis"></button>

<!-- 停止冒泡 -->
<button @click.stop="doThis"></button>

<!-- 阻止默认行为 -->
<form @submit.prevent></form> / <form @click.prevent></form>

<!-- 阻止默认行为,没有表达式 -->
<form @click.prevent></form>

<!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>

<!-- 键修饰符,键别名 -->
<input @keyup.enter="onEnter" />

<!-- 点击回调只会触发一次 -->
<button v-on:click.once="doThis"></button>

<!-- 对象语法 -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>

@click

众所周知,Jquery 很多方法都需要使用鼠标事件,如鼠标单击事件,而vue 在2.2.0版本中,也增加了一个鼠标按钮修饰符,还比 Jq 的更加简单便捷:

Name Img
.left
.right
.middle

例如可以监听鼠标的 right事件来返回一个消息,当然你也可以监听 .middle 滚轮中键点击等:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ui id="app">
<button @click.right="echo('hey,world!',$event)">Add</button>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

@keyup

v-on 指令并不仅仅支持鼠标的事件操作,还支持按键,这在官方文档中也被称之为按键修饰符,通过监听键盘事件,在v-on指令中共支持了 9 个按键修饰符:

Name Img
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right

通过 Vue 的按键修饰符可以监听目前常用的按键事件来执行对应的操作,例如监听 tab 按键从而返回消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ui id="app">
<button @keyup.tab="echo('hey,world!',$event)">Add</button>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

系统修饰符

当然,vue的v-on指令还不仅仅以上这些,自然而然的还支持了系统修饰符,我们可以通过按下响应的按键触发监听器:

ID DA
.ctrl
.alt
.shift
.meta win 键 或 ⌘ 键

Vue 对几个系统按键提供了多个支持,以及多个按键(@keyup)或鼠标(@click)之间的组合监听,需要注意的是在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。在 Symbolics 键盘上,meta 被标记为“META”或者“Meta”。

比如下述的实例中,通过 ctrl@click 按键,当按下 ctrl 并点击该事件才会进行触发 echo 事件,或者通过 ctrl + enter 组合进行触发。

需要注意的是,修饰符键于常规的不同,当keyup事件一起使用的时候,修饰符键必须处于按下的状态,只有当按住tab的情况下释放其他案件,才能被触发,所以如果需要实现那种行为,可以尝试下使用 KeyCodes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<ui id="app">
<button @click.ctrl="echo('hey,world!',$event)">A</button>
<input @keyup.ctrl.enter="echo('hey,world!',$event)" />
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
}
},
methods: {
echo(message, event) {
alert(message)
if (event) {
alert('v-on:' + event.target.tagName)
}
}
}
})
const vm = app.mount('#app')
</script>

为了增强修饰符之间的组合使用,在 Vue 2.5.0 中还提供了 .exact 属性用于精准控制系统修饰符组合并合并触发事件:

1
2
3
4
5
6
7
8
<!-- 即使 AltShift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>

Vue.js v-for at list

array

Vue 的循环就是通过 v-for 指令得以实现,通常可以通过循环的方式来渲染一个列表对象。同样 v-for 指令还需使用 item in items 形式的特殊语法进行渲染:

通常 item 是被迭代数组的别名,而 items 则是数组的元数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ui id="app">
<li v-for="item in items">{{item.message}}</li>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
items: [
{message: 'This is one'},
{message: 'This is two'}
]
}
}
})
const vm = app.mount('#app')
</script>

父作用域属性

v-for 指令中,我们所有可以访问的父作用域属还支持可选的第二参数,主要用于索引和加入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<ui id="app">
<li v-for="(item, index) in items">{{index}}-{{item.message}}——{{message}}}</li>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
message: 'Hey,v-for',
items: [
{message: 'This is one'},
{message: 'This is two'}
]
}
}
})
const vm = app.mount('#app')
</script>

Object

除数组以外,v-for 指令同样支持对象的循环渲染以及父作用域属性的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ui id="app">
<li v-for="item in items">{{item}}</li>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
items: {
title: 'Start Vue 3.0',
author: 'lk.sun'
}
}
}
})
const vm = app.mount('#app')
</script>

父作用域

需要注意的是父作用域中的第二参数的格式和位置需要按照 value、name、index 的形式进行排序,否则在数据渲染的时候将会出现混乱。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ui id="app">
<li v-for="(value, name, index) in items">index: {{index}} - name: {{name}} - value: {{value}}</li>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
items: {
title: 'Start Vue 3.0',
author: 'lk.sun'
}
}
}
})
const vm = app.mount('#app')
</script>

维护状态

v-for 渲染的元素列表发生改变时,会默认使用 就地更新 测罗,如果数据被改变 vue 将不会移动 DOM 元素来匹配数据项的顺序,为了确保他们每个需渲染后索引位置正确,在节点中加入一个唯一的 key 属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ui id="app">
<li v-for="item in items" :key="item.id">{{item}}</li>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
items: {
title: 'Start Vue 3.0',
author: 'lk.sun'
}
}
}
})
const vm = app.mount('#app')
</script>

在官方文档中建议我们尽可能的时候 v-for 时可以提供 key 属性,除非遍历输出的 DOM 内容非常简单,或是希望可以减少性能上的提升。

数组的更新检测

变更方法

Id Name Info
1 push() 增加一个方法
2 pop() 从下往上突然的删除一个方法
3 shift() 从上往下删除一个方法
4 unshift() 从上方新加入一个方法
5 splice() splice()方法可用于添加、删除、替换数组内的值
6 sort() 用于排序方法
7 reverse() 主要用于排序倒序
8 filter() 过滤器或筛选
9 slice() 切片

假设我们需要增加一个新的数组,可以通过使用 push() 变更方法在控制台中直接使用 vm.items.push({message: 'A4TECH'}) 进行加入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ui id="app">
<li v-for="item in items">{{item.message}}</li>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
items: [
{message: 'LG'}
]
}
}
})
const vm = app.mount('#app')
</script>

过滤和排序

filter()

在 Vue 3.0 中,将 filters 属性移除并向变更方法中新增了一个 filter() 方法作为过滤器进行使用,在 Vue 2.x 中,开发者可以使用 filters 来处理通用的文本格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<h1>Bank Account Balance</h1>
<p>{{ accountBalance | currencyUSD }}</p>
</template>

<script>
export default {
props: {
accountBalance: {
type: Number,
required: true
}
},
filters: {
currencyUSD(value) {
return '$' + value
}
}
}
</script>

在 Vue 3.x 中可以通过使用 fliter() 来处理数组来进行过滤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<ui id="app">
<li v-for="item in evenNumbers" :key="item">{{item}}</li>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
numbers: [1, 2, 3, 4, 5, 6]
}
},
computed: {
evenNumbers() {
return this.numbers.filter(number => number % 2 === 0)
}
}
})
const vm = app.mount('#app')
</script>

sort()

除了 filter() 可以通过表达式进行过滤,还可以通过 sort 来对数组进行排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<ui id="app">
<li v-for="item in evenNumbers" :key="item">{{item}}</li>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
numbers: [1, 20, 2, 3, 4, 100]
}
},
computed: {
evenNumbers() {
return this.numbers.sort(sortNumbers)
}
}
})
function sortNumbers(a,b){
return a-b;
}
const vm = app.mount('#app')
</script>

slice().reverse()

Vue 不仅提供了一个排序的 sort() 方法,还提供了 reverse() 方法来进行逆转,但这需要 slice() 切片后重新进行排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
<ui id="app">
<li v-for="item in numbers.slice().reverse()" :key="item">{{item}}</li>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
numbers: [1, 2, 3, 4, 5]
}
}
})
const vm = app.mount('#app')
</script>

template at value

template 是一个字符串模板,用于组件的实例标记,木板将会替换所挂载元素的源 HTML,挂在的任何元素所有标记都会被忽略,因此通常可以使用 template 作为指令块进行使用,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ui id="app">
<template v-for="item in 10" :key="item">
<li>{{item}}</li>
</template>
</ui>
<script>
const app = Vue.createApp ({
data() {
return {
}
}
})
const vm = app.mount('#app')
</script>

这将会被渲染为以下 HTML 表达式:

1
2
3
4
<ul>
<li>...</li>
...
</ul>

Vue.js 条件渲染

v-if and v-else

Vue.js 为条件渲染提供了 v-if 以及 v-else 指令,其中 v-if 指令用于条件渲染一块内容,内容的表达式根据 truthy 值进行决定是否被渲染:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="app">
<p v-if="isMessage">{{message}}</p>
<p v-else="isMessage">This is v-else</p>
</div>
<script>
const app = Vue.createApp ({
data() {
return {
message: 'This is v-bind:style',
isMessage: false
}
}
})
const vm = app.mount('#app')
</script>

isMessage 属性的 truthy 值为 false 时,则会使用 v-else 进行代替,但为了之后适用与更加复杂的结构中 v-else 需要指定属性。

template

template 是一个字符串模板,用作组件(component) 实例标记,模板将会替代所挂载的元素内部 HTML(innerHTML)。

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
<style>
.error {
border: 1px solid red;
padding: 0.5em;
color: red;
}
</style>
<div id="app">
<template v-if="isMessage">
<p v-if="isMessage">{{message}}</p>
<p>hey,v-if</p>
</template>
<div v-else="isMessage" :class="{error: isErr}">
<p>This is v-else="isMessage"</p>
</div>
</div>
<script>
const app = Vue.createApp ({
data() {
return {
message: 'This is v-bind:style',
isMessage: false,
isErr: true
}
}
})
const vm = app.mount('#app')
</script>

v-show

v-show 之外,Vue 还提供了另一条用于展示元素的 v-show 指令,他于 v-if 相差甚微:

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
<style>
.error {
border: 1px solid red;
padding: 0.5em;
color: red;
}
.warn {
border: 1px solid #ffaa00;
padding: 0.5em;
color: #ffaa00;
}
</style>
<div id="app">
<div v-if="isMessage">
<p>hey,v-if is "true"</p>
</div>
<div v-else-if="isMessage === null" :class="{error: isErr}">
<p>This is isMessage ="null"</p>
</div>
<div v-else-if="isMessage === undefined" :class="{error: isErr}">
<p>This is isMessage ="undefined"</p>
</div>
<div v-else :class="{warn: isWarn}">
<p>hey,v-if is "false"</p>
</div>
<div v-show="isMessage">
<p>Hey,world!</p>
</div>
</div>
<script>
const app = Vue.createApp ({
data() {
return {
isMessage: false,
isErr: true,
isWarn: true
}
}
})
const vm = app.mount('#app')
</script>

但不同的是 v-show 元素始终会被渲染并保留 DOM 中,因此 v-show 只是简单的切换元素的 display 属性。

v-if 的区别是他不支持 <template> 元素也不支持 v-else 指令

是 “真正” 的条件渲染,他会在切换的过程中,条件块内的事件监听器或子组件将会适当的被摧毁和更新。
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


## v-else-if
该指令可以充当 ```v-if``` 的 ```else-if``` 块且可林需的使用,但必须紧跟 ```v-if``` 或 ```v-else-if``` 的元素之后:

```js
<style>
.error {
border: 1px solid red;
padding: 0.5em;
color: red;
}
.warn {
border: 1px solid #ffaa00;
padding: 0.5em;
color: #ffaa00;
}
</style>
<div id="app">
<div v-if="isMessage">
<p>hey,v-if is "true"</p>
</div>
<div v-else-if="isMessage === null" :class="{error: isErr}">
<p>This is isMessage ="null"</p>
</div>
<div v-else-if="isMessage === undefined" :class="{error: isErr}">
<p>This is isMessage ="undefined"</p>
</div>
<div v-else :class="{warn: isWarn}">
<p>hey,v-if is "false"</p>
</div>
</div>
<script>
const app = Vue.createApp ({
data() {
return {
isMessage: false,
isErr: true,
isWarn: true
}
}
})
const vm = app.mount('#app')
</script>
📖 more posts 📖