Vue-基础-前端
本文最后更新于:2021年3月24日 下午
信息
Vue
(读音 /vjuː/
) 是一套用于构建用户界面的渐进式框架
与其它大型框架不同的是,Vue
被设计为可以自底向上逐层应用Vue
的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合
- 渐进式
指你可以让已有的项目,一点一点的用来Vue
取代实现,不用担心Vue
框架的排它性
一些框架可能会强制你使用它的一些东西,使得这个框架与其它框架难以集成到一起- 组件化应用
组件系统是Vue
的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用
安装
Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性
直接用 <script>
CDN引入
对于制作原型或学习,你可以这样使用最新版本
1 |
|
对于生产环境,我们推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:
1 |
|
NPM
在用 Vue
构建大型应用时推荐使用 NPM
安装。NPM
能很好地和webpack
打包器配合使用
1 |
|
对不同构建版本的解释
在 NPM
包的 dist/
目录会找到很多不同的 Vue.js
构建版本
UMD | CommonJS | ES Module (基于构建工具使用) |
ES Module (直接用于浏览器) |
|
---|---|---|---|---|
完整版 | vue.js | vue.common.js | vue.esm.js | vue.esm.browser.js |
只包含运行时版 | vue.runtime.js | vue.runtime.common.js | vue.runtime.esm.js | |
完整版 (生产环境) | vue.min.js | vue.esm.browser.min.js | ||
只包含运行时版 (生产环境) | vue.runtime.min.js |
- 完整版:同时包含编译器和运行时的版本。
- 编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。
- 运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。基本上就是除去编译器的其它一切。
版本类型说明
- UMD:UMD 版本可以通过
<script>
标签直接用在浏览器中- CommonJS:CommonJS 版本用来配合老的打包工具
webpack 1
- ES Module:为打包工具提供的 ESM
- 为诸如
webpack 2
提供的现代打包工具
ESM 格式被设计为可以被静态分析,所以打包工具可以利用这一点来进行“tree-shaking”并将用不到的代码排除出最终的包。
为这些打包工具提供的默认文件 (pkg.module
) 是只有运行时的 ES Module 构建 (vue.runtime.esm.js
)- 为浏览器提供的 ESM (2.6+)
用于在现代浏览器中通过<script type="module">
直接导入
浏览器调试插件Vue Devtools
Github: https://github.com/vuejs/vue-devtools#vue-devtools
寻找对应自己浏览器版本的调试插件安装即可
Hello World
创建一个HTML
文件,在文件中引入Vue
的CDN来使用Vue
1 |
|
HTML中设置一个标签用于显示数据
编写模板代码
1 |
|
Vue.js
的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统
这样就已经成功创建了第一个 Vue
应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue
在背后做了大量工作
现在数据和 DOM
已经被建立了关联,所有东西都是响应式的。
要怎么确认呢?打开你的浏览器的控制台 (就在这个页面打开),并修改 app.message 的值
你将看到上例相应地更新
注意我们不再和 HTML
直接交互了
一个 Vue
应用会将其挂载到一个 DOM
元素上 (对于这个例子是 #app
) 然后对其进行完全控制。那个 HTML
是我们的入口,但其余都会发生在新创建的 Vue
实例内部
其它的绑定
除了文本插值,我们还可以像这样来绑定元素 attribute
1 |
|
1 |
|
这里我们遇到了一点新东西。你看到的 v-bind attribute
被称为指令。指令带有前缀 v-
,以表示它们是 Vue
提供的特殊 attribute
。它们会在渲染的 DOM 上应用特殊的响应式行为
在这里,该指令的意思是:“将这个元素节点的 title attribute
和 Vue
实例的 message property
保持一致”
类似的,这个内容也是响应式的
条件
控制切换一个元素是否显示
1 |
|
1 |
|
在控制台输入 app3.seen = false
,你会发现之前显示的消息消失了。
这个例子演示了我们不仅可以把数据绑定到 DOM
文本或 attribute
,还可以绑定到 DOM
结构
循环
v-for
指令可以绑定数组的数据来渲染一个项目列表
1 |
|
1 |
|
输入
事件监听器
可以用 v-on
指令添加一个事件监听器,通过它调用在 Vue
实例中定义的方法
1 |
|
1 |
|
注意在 reverseMessage
方法中,我们更新了应用的状态,但没有触碰 DOM
所有的 DOM
操作都由 Vue
来处理,你编写的代码只需要关注逻辑层面即可
双向绑定
Vue
提供了 v-model
指令,它能轻松实现表单输入和应用状态之间的双向绑定
1 |
|
1 |
|
组件
组件系统是 Vue
的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用
在 Vue
里,一个组件本质上是一个拥有预定义选项的一个 Vue
实例。在 Vue
中注册组件很简单:
1 |
|
1 |
|
附带的观察整个流程(并非是运行流程),便于理解
<script>
初始化
- 声明自定义的组件
<todo-item>
- 初始化数据
groceryList
HTML
里的<todo-item>
v-for
遍历groceryList
中拿到数据,命名为item
- ``v-bind:todo=”item”相当于
组件.todo = item
todo-item
根据定义的template
计算出内容回填
尽管这只是一个刻意设计的例子,但是我们已经设法将应用分割成了两个更小的单元。
子单元通过prop
接口与父单元进行了良好的解耦
现在可以进一步改进 <todo-item>
组件,提供更为复杂的模板和逻辑,而不会影响到父单元
Vue实例
每个 Vue
应用都是通过用 Vue
函数创建一个新的 Vue
实例开始的
1 |
|
虽然没有完全遵循 MVVM 模型,但是 Vue
的设计也受到了它的启发。因此在文档中经常会使用 vm
(ViewModel
的缩写) 这个变量名表示 Vue
实例
当创建一个 Vue
实例时,你可以传入一个选项对象。这个篇章主要描述的就是如何使用这些选项来创建你想要的行为。作为参考,你也可以在 API 文档 中浏览完整的选项列表
一个 Vue
应用由一个通过 new Vue
创建的根 Vue
实例,以及可选的嵌套的、可复用的组件树组成
举个例子,一个 todo 应用的组件树可以是这样的:
1 |
|
所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象 (一些根实例特有的选项除外)
数据与方法
当一个 Vue
实例被创建时,它将 data
对象中的所有的 property
加入到 Vue
的响应式系统中
当这些 property
的值发生改变时,视图将会产生“响应”,即匹配更新为新的值
1 |
|
当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时就已经存在于 data
中的 property
才是响应式的
也就是说如果你在创建以后再去添加一个新的
property
,比如:
1 |
|
那么对
b
的改动将不会触发任何视图的更新
如果你知道你会在晚些时候需要一个 property
,但是一开始它为空或不存在,那么你需要设置一些初始值,以确保它是响应式的
1 |
|
冻结
Object.freeze()
会阻止修改现有的 property
,也意味着响应系统无法再追踪变化
1 |
|
1 |
|
前缀$
除了数据 property
,Vue
实例还暴露了一些有用的实例 property
与方法。它们都有前缀 $
,以便与用户定义的 property
区分开来
1 |
|
可以在 API 中查阅到完整的实例 property
和方法的列表
生命周期
生命周期钩子
每个Vue
实例在被创建时都要经过一系列的初始化过程
例如,需要设置数据监听、编译模板、将实例挂载到
DOM
并在数据变化时更新DOM
等
同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会
比如 created
钩子可以用来在一个实例被创建之后执行代码:
1 |
|
也有一些其它的钩子,在实例生命周期的不同阶段被调用。如 mounted
、updated
和 destroyed
生命周期钩子的 this
上下文指向调用它的 Vue
实例
注意:不要在选项
property
或回调上使用箭头函数比如
created: () => console.log(this.a)
vm.$watch(‘a’, newValue => this.myMethod())。因为箭头函数并没有
this
,this
会作为变量一直向上级词法作用域查找,直至找到为止
这经常导致Uncaught TypeError: Cannot read property of undefined
或Uncaught TypeError: this.myMethod is not a function
之类的错误
生命周期图例
图例上说明了可以使用的钩子函数(红框红字)与生命周期过程
以后遇到问题可以作为参考
模板语法
Vue.js
使用了基于 HTML
的模板语法,允许开发者声明式地将 DOM
绑定至底层 Vue
实例的数据
所有 Vue.js
的模板都是合法的 HTML
,所以能被遵循规范的浏览器和 HTML
解析器解析
在底层的实现上,Vue
将模板编译成虚拟 DOM
渲染函数。结合响应系统,Vue
能够智能地计算出最少需要重新渲染多少组件,并把 DOM
操作次数减到最少
插值
顾名思义,就是往HTML
中插入一些内容,以填充页面
普通文本 - “Mustache”语法 (双大括号)
向HTML中插入变量的值
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值
- 无法对元素属性使用
- 插入的HTML内容不会被当做元素,只会当做普通字符串
1 |
|
Mustache
标签将会被替代为对应数据对象上 msg property
的值
无论何时,绑定的数据对象上 msg property
发生了改变,插值处的内容都会更新
插值固定 - v-once 指令
用于影响插值,在此指令范围内的文本插值后不会因其原本变量值改变而改变
1 |
|
HTML内容 - v-html 指令
用于插入HTML内容
双大括号会将数据解释为普通文本,要插入HTML内容,需要用这个v-html 指令
1 |
|
这个 span
的内容将会被替换成为 property
值 rawHtml
,直接作为 HTML(忽略解析 property
值中的数据绑定)
注意,你不能使用 v-html
来复合局部模板,因为 Vue
不是基于字符串的模板引擎。反之,对于用户界面 (UI),组件更适合作为可重用和可组合的基本单位
你的站点上动态渲染的任意
HTML
可能会非常危险,因为它很容易导致XSS 攻击
。请只对可信内容使用HTML
插值,绝不要对用户提供的内容使用插值
元素属性插值 - v-bind 指令
用于绑定内容与目标元素的属性
Mustache 语法
不能作用在 HTML attribute
上,遇到这种情况应该使用 v-bind 指令
1 |
|
对于布尔 attribute
(它们只要存在就意味着值为 true
),v-bind
工作起来略有不同
1 |
|
如果isButtonDisabled
的值是 null
、undefined
或 false
,则 disabled attribute
甚至不会被包含在渲染出来的 <button>
元素中
JavaScript 表达式
实际上,对于所有的数据绑定,Vue.js
都提供了完全的 JavaScript
表达式支持
1 |
|
这些表达式会在所属 Vue
实例的数据作用域下作为 JavaScript
被解析。有个限制就是,每个绑定都只能包含单个表达式
下面的例子都不会生效
- 是语句,不是表达式
{{ var a = 1 }}
- 流控制也不会生效,请使用三元表达式
{{ if (ok) { return message } }}
模板表达式都被放在沙盒中,只能访问一些特定的全局变量,如 Math
和 Date
你不应该在模板表达式中访问用户定义的全局变量
指令
指令 (Directives) 是带有 v-
前缀的特殊 attribute
指令 attribute
的值预期是单个 JavaScript
表达式 (v-for 是例外情况,稍后我们再讨论)
指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
参数
一些指令能够接收一个“参数”,在指令名称之后以冒号表示
例:
v-bind
指令可以用于响应式地更新HTML attribute
1 |
|
在这里 href
是参数,告知 v-bind
指令将该元素的 href attribute
与表达式 url
的值绑定
例:
v-on
指令,它用于监听 `DOM 事件
1 |
|
在这里参数是监听的事件名
动态参数
可以用方括号括起来的 JavaScript
表达式作为一个指令的参数
例:
1 |
|
如果你的 Vue 实例有一个 data property attributeName,其值为 “href”,那么这个绑定将等价于 v-bind:href
这里的 attributeName
会被作为一个 JavaScript
表达式进行动态求值,求得的值将会作为最终的参数来使用
同样地,你可以使用动态参数为一个动态的事件名绑定处理函数:
例:
1 |
|
当 eventName
的值为 “focus” 时,v-on:[eventName]
将等价于 v-on:focus
约束
对动态参数的值的约束
- null
动态参数预期会求出一个字符串,异常情况下值为null
这个特殊的null
值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。
对动态参数表达式的约束
特殊符号约束
动态参数表达式有一些语法约束,因为某些字符,如空格和引号,放在HTML attribute
名里是无效的例:
1
2<!-- 这会触发一个编译警告 -->
<a v-bind:['foo' + bar]="value"> ... </a>变通的办法是使用没有空格或引号的表达式,或用计算属性替代这种复杂表达式
大小写约束
在DOM
中使用模板时 (直接在一个HTML
文件里撰写模板),还需要避免使用大写字符来命名键名,因为浏览器会把attribute
名全部强制转为小写例:
1
2
3
4
5<!--
在 DOM 中使用模板时这段代码会被转换为 `v-bind:[someattr]`。
除非在实例中有一个名为“someattr”的 property,否则代码不会工作。
-->
<a v-bind:[someAttr]="value"> ... </a>修饰符
修饰符 (modifier) 是以半角句号
.
指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用
event.preventDefault()
1
<form v-on:submit.prevent="onSubmit">...</form>
缩写
v-
前缀作为一种视觉提示,用来识别模板中Vue
特定的attribute
Vue
为v-bind
和v-on
这两个最常用的指令,提供了特定简写
v-bind 缩写
1 |
|
v-on 缩写
1 |
|
它们看起来可能与普通的 HTML
略有不同,但 :
与 @
对于 attribute
名来说都是合法字符,在所有支持 Vue
的浏览器都能被正确地解析
它们不会出现在最终渲染的标记中
计算属性和侦听器
计算属性
模板表达式 与 计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的
在模板中放入太多的逻辑会让模板过重且难以维护
1 |
|
在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量
message
的翻转字符串
当你想要在模板中多包含此处的翻转字符串时,就会更加难以处理
对于任何复杂逻辑,你都应当使用计算属性
计算属性
1 |
|
1 |
|
这里声明了一个 “计算反转的vm.message
字符串的函数” 传入到 计算属性 reversedMessage
提供的函数将用作 property
vm.reversedMessage
的 getter
函数
计算属性 reversedMessage
的结果是响应式的
reversedMessage
的值始终取决于vm.message
的值
你可以像绑定普通 property
一样在模板中绑定计算属性Vue
知道 vm.reversedMessage
依赖于 vm.message
,因此当 vm.message
发生改变时,所有依赖 vm.reversedMessage
的绑定也会更新
而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性
的 getter
函数是没有副作用 (side effect
) 的,这使它更易于测试和理解
计算属性的 setter
计算属性默认只有 getter
,不过在需要时你也可以提供一个 setter
1 |
|
运行 vm.fullName = 'John Doe'
时,setter
会被调用
因此vm.firstName
和 vm.lastName
也会相应地被更新。
计算属性缓存 与 方法
你可能会想到:通过 在表达式中调用方法 来达到和 计算属性 同样的效果
1 |
|
1 |
|
两种方式的最终结果确实是完全相同的
不同的是 计算属性
是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值
只要 message
还没有发生改变,多次访问 reversedMessage
计算属性会立即返回之前的计算结果,而会再次执行函数
可能造成的问题
下面的计算属性
将不再更新,因为Date.now()
不是响应式依赖
1 |
|
计算属性 | 方法 | |
---|---|---|
更新结果 | 依赖更新时更新 否则从缓存中得到上次的计算结果 |
每次运行都更新 |
资源消耗 | 小 | 大 |
速度 | 较快 | 较慢 |
计算属性 vs 侦听属性
Vue
提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性(watch
)
但通常计算属性
能够取代 命令式的 watch
回调,并且让代码更优美
例:姓更变 或 名更变 时 自动计算全名
1 |
|
此处用
watch
实现
1 |
|
此处用
计算属性
实现
1 |
|
对比而言,
计算属性
的代码就优美很多
侦听器
Vue
通过 watch
选项提供了一个更通用的方法,来响应数据的变化
当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
例:异步
Ajax
请求
1 |
|
使用 watch
选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的
1 |
|
除了 watch
选项之外,还可以使用命令式的 vm.$watch
API
Class 与 Style绑定
操作元素的 class
列表和内联样式是数据绑定的一个常见需求。它们都是 attribute
,所以可以用 v-bind
处理它们
在将 v-bind
用于 class
和 style
时,Vue.js
做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组
绑定 HTML Class
对象语法
多字段设置
可以传给 v-bind:class
多个字段,以动态地切换 class
1 |
|
v-bind:class
指令也可以与普通的 class
attribute
共存,最终得到的结果会是它们拼接在一起的样子
多字段来动态切换Class
1 |
|
会得到这样的渲染结果
static activate
类似的,这样设置的样式是响应式的,如果修改isActive
与hasError
设置的内容也会相应的做出改变
单对象
与上面的多个字段类似,可以在一个对象中设置多个属性(作为字段),来进行class
的切换
单个对象来动态切换class
1 |
|
会得到和上面的例子一样的的结果
数组语法
可以把一个数组传给 v-bind:class
,以应用一个 class
列表
数组来动态切换class
1 |
|
最终渲染结果为
class="active text-danger"
你可以在数组中填入表达式,但这会造成内容的不美观,不建议那样做
绑定内联样式 style
v-bind:style
的对象语法十分直观——看着非常像 CSS
,但其实是一个 JavaScript
对象CSS property
名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名
多字段设置style
1 |
|
最终得到的
style="color: red; font-size: 30px;"
对象设置Style
类似的,v-bind:style
可以在一个或多个对象中设置属性(作为字段),来进行style
的设置
单个对象设置 style
1 |
|
得到的结果与上个例子一致:
style="color: red; font-size: 30px;"
对于希望设置多个对象到元素上时,需要用数组括起来
多个对象设置 style
1 |
|
得到的结果与上个例子一致:
style="color: red; font-size: 30px;"
自动添加前缀
当 v-bind:style
使用需要添加浏览器引擎前缀的 CSS property
时,如 transform
,Vue.js
会自动侦测并添加相应的前缀
多重值
可以为 style
绑定中的 property
提供一个包含多个值的数组,常用于提供多个带前缀的值,这样写只会渲染数组中最后一个被浏览器支持的值
包含多个值的 preoperty 数组
1 |
|
如果此处浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex
条件渲染
v-if 与 v-else
v-if
指令用于条件性地渲染一块内容
这块内容只会在指令的表达式返回 truthy
值的时候被渲染
v-else
指令来表示 v-if
的 “else 块”v-else
元素必须紧跟在带 v-if
或者 v-else-if
的元素的后面,否则它将不会被识别
v-if
与v-else
的基本使用方式
1 |
|
依旧,这个渲染是响应式的,而且在状态发生改变之前,页面上不会有多余的元素(并不是hide,而是完全没有)
v-if 与 v-for 一起使用
不推荐同时使用 v-if
和 v-for
。请查阅风格指南以获取更多信息
当 v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级。请查阅列表渲染指南以获取详细信息。
v-else-if
v-else-if
,顾名思义,其作用就相当于马上在else
后接一个if
判断
类似于 v-else
,v-else-if
也必须紧跟在带 v-if
或者 v-else-if
的元素之后
v-else-if
的使用方式
1 |
|
用 key 管理可复用的元素
Vue
会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染 这么做除了使 Vue
变得非常快之外,还有其它一些现象
尽可能复用:用户在不同的登录方式之间切换
1 |
|
切换 loginType
将不会清除用户已经输入的内容
两个模板都使用了相同的元素<input>
。因为vue
总是希望尽可能复用,这个元素不会被替换掉(此处仅替换了它的 placeholder
属性)
这会造成一些问题,一般切换输入类型都需要将已输入内容清空,而这里没清
如果不希望vue
最大程度复用,那么可以为元素添加key
属性
需要注意,key
属性需要一个唯一值
独立的key:用户在不同的登录方式之间切换
1 |
|
在设置了key
后,模板内容会被重新渲染后才放到页面上。所以输入的内容消失了
v-show
另一个用于根据条件展示元素的选项是 v-show
指令
用法与 v-if
类似,都是表达式返回 truthy
值的时候被渲染
不同的是带有 v-show
的元素始终会被渲染并保留在 DOM
中v-show
只是简单地切换元素的 CSS property display
注意,v-show
不支持 <template>
元素,也不支持 v-else
v-show
的使用
1 |
|
v-if 对比 v-show
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS
进行切换。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销 因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好
列表渲染
v-for 对应数组
可以用 v-for
指令基于一个数组来渲染一个列表v-for
指令需要使用 item in items
形式的特殊语法,其中 items
是源数据数组,而 item
则是被迭代的数组元素的别名
v-for
对应数组到元素v-for
还支持一个可选的第二个参数,即当前项的索引
1 |
|
v-for 对应对象
可以用 v-for
来遍历一个对象的 property
1 |
|
维护状态
当 Vue 正在更新使用 v-for
渲染的元素列表时,它默认使用“就地更新”的策略
如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染
这个默认的模式是高效的,但是只适用于 不依赖子组件状态 或 临时 DOM 状态 (例如:表单输入值) 的列表渲染输出
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
attribute:
1 |
|
建议尽可能在使用 v-for
时提供 key
attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升
因为它是 Vue 识别节点的一个通用机制,key
并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途
不要使用对象或数组之类的非基本类型值作为
v-for
的key
。请用字符串或数值类型的值
更多 key attribute 的细节用法请移步至 key 的 API 文档
数组更新检测
变更方法
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新
这些被包裹过的方法包括:
- push()、pop()
- shift()、unshift()
- splice()
- sort()
- reverse()
你可以打开控制台,然后对前面例子的 items 数组尝试调用变更方法。比如 example1.items.push({ message: 'Baz' })
替换数组
变更方法,顾名思义,会变更调用了这些方法的原始数组
相比之下,也有非变更方法,例如 filter()
、concat()
和 slice()
。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组:
1 |
|
这并不会导致 Vue 丢弃现有 DOM 并重新渲染整个列表。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作
注意事项
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。深入响应式原理 中有相关的讨论
显示过滤/排序后的结果
有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组
例如:
1 |
|
在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法:
1 |
|
在 v-for 中使用值范围
v-for
可以接受整数,这种情况下,它会把模板重复对应次数
1 |
|
在 <template>
上使用 v-for
类似于 v-if,你也可以利用带有 v-for 的 <template>
来循环渲染一段包含多个元素的内容。比如:
1 |
|
v-for 与 v-if 一同使用
注意:不推荐在同一元素上使用 v-if 和 v-for
当它们处于同一节点,v-for
的优先级比 v-if
更高
这意味着 v-if
将分别重复运行于每个 v-for
循环中
当你只想为部分项渲染节点时,这种优先级的机制会十分有用
例:只渲染未完成的 todo
1 |
|
事件处理
监听事件
可以用 v-on
指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码
1 |
|
事件处理方法
许多事件处理逻辑会更为复杂,把 JavaScript 代码直接写在 v-on
指令中是不可行的v-on
可以接收一个需要调用的方法名称
示例:
1 |
|
内联处理器中的方法
除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法
1 |
|
有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法
1 |
|
事件修饰符
在事件处理程序中调用 event.preventDefault()
或 event.stopPropagation()
是非常常见的需求
尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节
为了解决这个问题,Vue.js 为 v-on
提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的
.stop
.prevent
.capture
.self
.once
.passive
1 |
|
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生
因此,用 v-on:click.prevent.self
会阻止所有的点击,而 v-on:click.self.prevent
只会阻止对元素自身的点击
注意:不要把
.passive
和.prevent
一起使用,因为.prevent
将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive
会告诉浏览器你不想阻止事件的默认行为
按键修饰符
Vue 允许为 v-on
在监听键盘事件时添加按键修饰符:
1 |
|
你可以直接将 KeyboardEvent.key
暴露的任意有效按键名转换为 kebab-case 来作为修饰符
1 |
|
在上述示例中,处理函数只会在 $event.key
等于 PageDown
时被调用
表单输入绑定
基础用法
你可以用 v-model
指令在表单 <input>
、<textarea>
及 <select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素
尽管有些神奇,但 v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理
注意:
v-model
会忽略所有表单元素的value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源
你应该通过 JavaScript 在组件的 data 选项中声明初始值
v-model
在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
text 和 textarea 元素使用 value
property 和 input
事件
checkbox 和 radio 使用 checked
property 和 change
事件
select 字段将 value
作为 prop 并将 change
作为事件
注:对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model
不会在输入法组合文字过程中得到更新。如果你也想处理这个过程,请使用 input
事件
文本
1 |
|
多行文本
1 |
|
在文本区域插值 (
<textarea>{{text}}</textarea>
) 并不会生效,应用v-model
来代替
复选框
对于单个复选框,可以绑定到布尔值中
1 |
|
对于多个复选框,可以绑定到同一个数组中
1 |
|
1 |
|
单选按钮
1 |
|
1 |
|
选择框
单选时
1 |
|
1 |
|
注意:如果
v-model
表达式的初始值未能匹配任何选项,<select>
元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发change
事件。因此,更推荐像上面这样提供一个值为空的禁用选项
多选时 (绑定到一个数组):
1 |
|
1 |
|
值绑定
对于单选按钮,复选框及选择框的选项,v-model
绑定的值通常是静态字符串 (对于复选框也可以是布尔值)
1 |
|
但是有时我们可能想把值绑定到 Vue 实例的一个动态 property 上,这时可以用 v-bind
实现,并且这个 property 的值可以不是字符串
1 |
|
1 |
|
这里的
true-value
和false-value
attribute 并不会影响输入控件的value
attribute,因为浏览器在提交表单时并不会包含未被选中的复选框
如果要确保表单中这两个值中的一个能够被提交,(即“yes”或“no”),请换用单选按钮
单选按钮绑定
1 |
|
1 |
|
选择框选项绑定
1 |
|
1 |
|
修饰符
.lazy
默认情况下,v-model
在每次input
事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加lazy
修饰符,从而转为在change
事件_之后_进行同步:1
2<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">.number
如果想自动将用户的输入值转为数值类型,可以给v-model
添加number
修饰符:1
<input v-model.number="age" type="number">
这通常很有用,因为即使在
type="number"
时,HTML 输入元素的值也总会返回字符串。如果这个值无法被parseFloat()
解析,则会返回原始的值.trim
如果要自动过滤用户输入的首尾空白字符,可以给v-model
添加trim
修饰符:1
<input v-model.trim="msg">
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!