Vue官方文档笔记1——基础
Vue官方文档笔记1——基础
1. 介绍
2. Vue 实例
2.1 创建一个Vue实例
每个Vue应用都是通过vue函数传建一个新的实例开始:
1 | var vm= new Vue({ |
一个 Vue 应用由一个通过 new Vue
创建的根Vue实例
,以及可选的嵌套的、可复用的组件树组成;
2.2 数据与方法
当一个 Vue 实例被创建后,它向 Vue 的响应式系统中加入其 data 对象中能找到的所有属性,当这些属性的值变化时,视图将会产生“相应”,即匹配新的值;
若使用 Object.freeze()
,则会阻止修改现有的属性,意味着响应式系统无法追踪变化;
1 | var obj = { |
Vue 实例还暴露了一些有用的实例属性和方法,加以前缀 $
,以便与用户定义的属性区分开;
1 | var data = { a: 1 } |
2.3 实例生命周期钩子
每个Vue实例在被创建的时候要经过一系列的初始化过程,这个过程中会运行一些叫做 生命周期钩子
的函数,给用户在不同阶段加入自己代码的机会;
生命周期钩子的 this
上下文指向调用它的 Vue实例
;
注:不要在选项属性或回调上使用箭头函数;
例如:
1 | created: () => console.log(this.a) |
这是因为箭头函数是和父级上下文绑定在一起的,this 不会是如你所预期的 Vue 实例,系统会报错;
2.4 生命周期图示
3. 模板语法
Vue.js 使用了基于HTML 的模板语法,允许开发者声明式地将 DOM 绑定到底层Vue实例的数据;
在底层实现上,Vue将模板编译成虚拟 DOM 渲染函数;若你熟悉虚拟DOM且偏爱JavaScript原生力量,可以直接写渲染函数(render函数),使用JSX 的语法;
3.1 插值
- 文本:数据绑定的形式就是使用
“Mustache语法”
,采用双括号的文本插值;
或是通过v-once
指令,执行一次性插值,若数据改变,插值处的内容不会更新; - 原生 HTML:双大括号将数据解释为普通文本,非 HTML 代码,若要输出真正的 HTML, 则使用
v-html
指令;
特性:Mustache
语法不能作用在HTML特性上,则需要使用 v-bind
指令进行属性绑定,如title、src、disabled
等属性;
使用 JavaScript 表达式:对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持;
3.2 指令
指令是带有 v-
前缀的特殊特性,指令特性的预期是单个JavaScript 表达式(v-for 例外),指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM;
- 参数:位于指令名称之后以冒号表示;例:
v-on
指令:参数是监听的事件名;v-if
指令:根据表达式值的真假来插入/移除
元素;v-bind
指令:用于绑定 HTML 标签的属性,如href、img、title
等;
- 修饰符:以半角句号(
.
)指明的特殊后缀,用于指出一个指令应该以特殊方式绑定;
例如: .prevent
修饰符告诉 v-on
指令对于触发的事件调用 event.preventDefault()
,阻止默认事件:
1 | <form v-on:submit.prevent="onSubmit">...</form> |
3.3 缩写
v-bind
指令缩写为(:
);
1 | <!-- 完整语法 --> |
v-on
指令缩写为(@
):
1 | <!-- 完整语法 --> |
4.计算属性和侦听器
4.1 计算属性
基础例子:从该实例中,可以看出,计算属性用于复杂的逻辑中,只要 computed
钩子函数中声明的计算属性所依赖的值发生变化,那么该属性就会更新,而所有依赖该计算属性的绑定也会更新;
现在我们已经以声明的方式创建这种依赖关系:计算属性的 getter
函数是没有副作用的,使得它更易于测试和理解;
计算属性
Vsmethods方法
:- 将一个函数定义为一个方法或是一个计算属性,两种方式结构是完全相同的;
- 区别是:计算属性是基于他们的依赖进行缓存的;计算属性只有在它依赖发生变化时才会重新求值;而
methods
则是通过触发事件来调用的;
计算属性
Vs侦听属性
:- 侦听属性(
watch
)用于监测某个数据变化而触发,而计算属性原理是其数据依赖发生变化时才触发;
- 侦听属性(
- 计算属性的
setter
,例全名的例子:
1 | // ... |
4.2 侦听器
Vue 通过 watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的;
1 | <div id="watch-example"> |
5. Class与Style绑定
5.1 绑定 HTML class
- 对象语法:给
v-bind:class
传一个对象,可动态切换class,是由于数据属性的 truthiness;也可以在对象中传入更多属性来动态切换多个 class;
1 | // 1.可以在对象中传入更多属性来动态切换多个 class |
- 数组语法:
1 | // 1.可以把一个数组传给 `v-bind:class` |
- 用在组件上:
当在一个自定义组件上使用class
属性时,这些类将被添加到该组件的根元素上面。这个元素上已经存在的类不会被覆盖,用法和上面的用法一致;
5.2 绑定内联样式
v-bind:style
的对象语法其实是一个JavaScript
对象。CSS 属性名可以用驼峰式
(camelCase) 或短横线分隔
(kebab-case,记得用单引号
括起来) 来命名,如下:
1 | <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> |
- 或直接绑定到一个样式对象:
1 | <div v-bind:style="styleObject"></div> |
- 数组语法:
v-bind:style
的数组语法可以将多个样式对象应用到同一个元素上:
1 | <!-- baseStyles, overridingStyles 为样式对象,参考上面的styleObject --> |
- 自动添加浏览器引擎前缀的 CSS 属性时,如
transform
的-webkit- -moz- -o- -ms-
前缀; - 多重值:可从 2.3.0 起,可以为 style 绑定中的属性提供一个包含多个值的数组,常用于提供多个带前缀的值,例如:
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
6. 条件渲染
6.1 v-if 指令:
- 在
<template>
元素上使用v-if
条件渲染分组; v-else
:v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别;v-else-if
:充当 v-if 的“else-if 块”,可以连续使用;- 用
key
管理可复用的元素: Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染;而添加一个具有唯一值的key
属性,使得复用的元素是完全独立的,不要复用它们,
6.2 v-show 指令:根据条件展示元素的选项
v-show
的元素始终会被渲染并保留在 DOM 中, v-show
只是简单地切换元素的 CSS 属性 display: none/block;
;
6.3 v-if 对比 v-show:
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;v-show
元素总是会被渲染,并且只是简单地基于 CSS 进行切换;
6.4 v-if 与 v-for 一起使用
当 v-if
与 v-for
一起使用时,v-for
具有比 v-if
更高的优先级;尽量不一起使用
7. 列表渲染
7.1 用 v-for 把一个数组对应为一组元素
- v-for 指令需要使用
item in items
形式的特殊语法,items
是源数据数组并且item
是数组元素迭代的别名; - 在
v-for
块中,拥有对父作用域属性的完全访问权限; v-for
还支持一个可选的第二个参数为当前项的索引;- 可以用
of
替代in
作为分隔符,因为它是最接近 JavaScript 迭代器的语法;
7.2 一个对象的 v-for
用 v-for
通过一个对象的属性来迭代,也可以提供第二个的参数为键名,第三个参数为索引;
1 | <div v-for="(value, key) in object"> |
1 | new Vue({ |
7.3 key
尽可能在使用 v-for
时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升; 因为它是 Vue 识别节点的一个通用机制;
1 | <div v-for="item in items" :key="item.id"> |
7.4 数组更新检测
- 变异方法:Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。这些方法如下:
push()、pop()、shift()、unshift()、splice()、sort()、reverse()
; - 替换数组:
- 变异方法:会改变被这些方法调用的原始数组;
- 非变异 (non-mutating method) 方法,例如:
filter(), concat() 和 slice()
这些不会改变原始数组,但总是返回一个新数组,可以用新数组替换旧数组:
注意事项:由于 JavaScript 的限制,Vue 不能检测以下变动的数组:
- 当你利用索引直接设置一个项时,例如:
vm.items[indexOfItem] = newValue;
- 当你修改数组的长度时,例如:
vm.items.length = newLength;
解决上面第一类问题,以下两种方式都可以解决:
1 | // Vue.set |
解决上面第二类问题,你可以使用 splice
:
1 | vm.items.splice(newLength) |
7.5 对象更改检测注意事项
由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除;对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, key, value)
方法向嵌套对象添加响应式属性:
1 | Vue.set(vm.userProfile, 'age', 27)//或者使用 vm.$set 实例方法,它只是全局 Vue.set 的别名,格式一致 |
7.6 显示过滤/排序结果
有时我们想要显示一个数组的过滤或排序副本,而不实际改变或重置原始数据。在这种情况下,可以创建返回过滤或排序数组的计算属性,可以通过 filter
函数进行过滤,例如:
1 | <li v-for="n in evenNumbers">{{ n }}</li> |
1 | data: { |
计算属性不适用的情况下 (例如,在嵌套 v-for
循环中) 你可以使用一个 method
方法进行数据过滤;
1 | <li v-for="n in even(numbers)">{{ n }}</li> |
1 | data: { |
7.7 一段取值范围的 v-for
v-for
也可以取整数。在这种情况下,它将重复多次模板:
1 | <div> |
7.8 v-for on a <template>
利用带有 v-for
的 <template>
渲染多个元素;
7.9 v-for with v-if
当它们处于同一节点,v-for
的优先级比 v-if
更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中;
7.10 一个组件的 v-for
自定义组件里可以像任何普通元素一样用 v-for
;然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域,为了把迭代数据传递到组件里,我们要用 props
,例:
1 | <my-component |
不自动将 item 注入到组件里的原因是,这会使得组件与 v-for
的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用;
7.11 todo list 的完整例子:
1 | <div id="todo-list-example"> |
1 | Vue.component('todo-item', { |
8.事件处理
8.1 监听事件
v-on
指令:监听 DOM 事件,并在触发时运行一些 JavaScript 代码;
8.2 事件处理方法
v-on
可以接收一个需要调用的方法名称 ;(方法在 methods
中定义 );
8.3 内联处理器中的方法
v-on
还可以在内联 JavaScript 语句中调用方法;
1 | <div id="example-3"> |
1 | new Vue({ |
若需要在内联语句处理器中访问原始的 DOM 事件
,用特殊变量 $event
把它传入方法:
1 | <button v-on:click="warn('Form cannot be submitted yet.', $event)"> |
1 | // ... |
8.4 事件修饰符
在事件处理程序中调用 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
只会阻止对元素自身的点击;
Vue 2.1.4 新增:
1 | <!-- 点击事件将只会触发一次 --> |
Vue 2.3.0 新增: Vue 还对应 addEventListener
中的 passive
选项提供了.passive
修饰符:
1 | <!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 --> |
注:不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告;
8.5 按键修饰符
Vue 允许为 v-on
在监听键盘事件时添加按键修饰符,例如:
1 | <!-- 只有在 `keyCode` 是 13 / enter 时调用 `vm.submit()` --> |
全部的按键别名:.enter .tab .delete (捕获“删除”和“退格”键) .esc .space .up .down .left .right
;
可以通过全局 config.keyCodes
对象自定义按键修饰符别名:
1 | // 可以使用 `v-on:keyup.f1` |
8.6 系统修饰键
可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器:.ctrl .alt .shift .meta
;
注意:在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。
1 | <!-- Alt + C --> |
注意:修饰键与常规按键不同,在和 keyup
事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住 ctrl 的情况下释放其它按键,才能触发 keyup.ctrl
。而单单释放 ctrl 也不会触发事件。如果你想要这样的行为,请为 ctrl 换用 keyCode: keyup.17
;
8.7 .exact 修饰符
允许你控制由精确的系统修饰符组合触发的事件;例如:
1 | <!-- 即使 Alt 或 Shift 被一同按下时也会触发 --> |
8.8 鼠标按钮修饰符: .left、.right、.middle
这些修饰符会限制处理函数仅响应特定的鼠标按钮;
8.9 为什么在 HTML 中监听事件?
使用 v-on
有几个好处:
- 扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
- 因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
- 当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们。
9. 表单输入绑定
9.1 基础用法
v-model
指令可以在表单 <input> <textarea> <select>
元素上创建双向数据绑定,它会根据控件类型自动选取正确的方法来更新元素:
注意:v-model
会忽略所有表单元素的 value、checked、selected
特性的初始值,而总是将 Vue 实例
的数据作为数据来源。你应该通过 JavaScript 在组件的 data
选项中声明初始值;
9.2 文本示例:
1 | <input v-model="message" placeholder="edit me"> |
9.3 多行文本示例:
1 | <span>Multiline message is:</span> |
9.4 复选框示例:单个复选框,绑定到布尔值;
1 | <input type="checkbox" id="checkbox" v-model="checked"> |
9.5 文本示例:多个复选框,绑定到同一个数组;
1 | <div id='example-3'> |
1 | new Vue({ |
9.6 单选按钮示例:
1 | <div id="example-4"> |
9.7 选择框示例:
单选时:
1 | <div id="example-5"> |
多选时 (绑定到一个数组):
1 | <div id="example-6"> |
9.8 值绑定
对于单选按钮,复选框及选择框的选项,v-model
绑定的值通常是静态字符串 (对于复选框也可以是布尔值);如下所示:
1 | <!-- 当选中时,`picked` 为字符串 "a" --> |
我们可以用 v-bind
实现把值绑定到 Vue 实例的一个动态属性上,这个属性的值可以不是字符串;
1 | <!-- 单选按钮 --> |
1 | <!-- 选择框的选项 --> |
1 | // 当选中时: |
9.9 修饰符:
.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">
.trim
:自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:1
<input v-model.trim="msg">
9.10 在组件上使用 v-model
Vue 的组件系统允许你创建具有完全自定义行为且可复用的输入组件。这些输入组件甚至可以和 v-model
一起使用;
10. 组件基础
10.1 基本实例
组件是可复用的 Vue 实例,可以在一个通过 new Vue
创建的 Vue 根实例中,把这个组件作为自定义元素来使用;
1 | // 定义一个名为 button-counter 的新组件 |
1 | //在根实例中使用 |
10.2 组件的复用
组件可以任意次数复用,因为你每用一次组件,就会有一个它的新实例被创建;
注意:组件定义时, data
必须是一个函数,而不是一个对象,若 Vue 没有这条规则,点击一个组件的实例就可能会影响到该组件其它所有实例;
1 | data: function () { |
10.3 组件的组织及组件注册
组件是以一棵嵌套的组件树的形式来组织;为了能在模板中使用,组件必须先注册
以便 Vue 能够识别;
组件有两种组件的注册类型:全局注册和局部注册
;
- 全局注册:通过
Vue.component
全局注册例:1
2
3Vue.component('my-component-name', {
// ... options ...
}) - 局部注册:通过对象的形式创建组件,引入组件后在
component
属性中进行注册;
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue
) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中;
10.4 通过 Prop 向子组件传递数据
Prop
是在组件上注册的一些自定义特性,当一个值传递给一个 prop
特性的时候,它就变成了那个组件实例的一个属性;
例如通过父组件向子组件传递数据:
1 | <-- 在父组件中的创建的该子组件的实例上加入 title 属性 --> |
1 | //子组件在通过 Vue.componen 全局创建的时候,props属性中包含 title 属性,用于父组件的传值 |
一个组件默认可以拥有任意数量的
prop
,任何值都可以传递给任何prop
,在子组件的props
属性中接收父组件传递的数据;
10.5 单个根元素
每个组件<template>
必须只有一个根元素,将模板的内容包裹在一个父元素内,来修复这个问题;
10.6 通过事件向父级组件发送消息
- 方法1:父组件中加一个
postFontSize
数据属性(暂时不了解) - 方法2:调用内建的
$emit
方法并传入事件的名字,来向父级组件触发一个事件;例:在子组件中通过点击事件添加一个事件名,再在父组件中监听这个事件,来实现子组件向父组件数据传递:
1 | <!-- 子组件通过 $emit() 方法加入一个事件名 --> |
1 | //父组件上通过 v-on 指令来监听这个事件 |
同时$emit()
方法还可以给事件传递一个值,父组件中使用 $event
访问到这个值:
1 | <!-- 子组件通过 $emit() 方法加入一个事件名,并传一个值 --> |
1 | //父组件上通过 v-on 指令来监听这个事件,并通过 $event 访问到被抛出的这个值;如果这个事件处理函数是一个方法,可以将该值作为参数传入方法中使用 |
- 方法3:在组件上使用
v-model
传值,在输入控件中调用v-model
的原理如下:(此处没有弄懂)
1 | <input v-model="searchText" /> |
当用在组件上时,v-model
则会这样:
1 | <custom-input |
因而在组件内的 input 标签必须:将其 value 特性绑定到一个名叫 value 的 prop 上;在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出;
组件中使用的代码如下:
1 | //组件全局创建时 |
1 | <custom-input v-model="searchText"></custom-input> |
10.7 通过插槽分发内容
Vue 自定义的 <slot>
元素,只要在需要的地方加入插槽就行了;
1 | Vue.component('alert-box', { |
1 | <alert-box> |
10.8 动态组件:
通过 Vue 的 component
元素加一个特殊的 is
特性来实现:
1 | <!-- 组件会在 `currentTabComponent` 改变时改变 --> |
上述示例中,currentTabComponent
可以包括: 已注册组件的名字 或 一个组件的选项对象;
10.9 解析 DOM 模板时的注意事项
有些 HTML 元素,诸如 <ul> <ol> <table> <select>
,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li> <tr> <option>
,只能出现在其它某些特定的元素内部; Vue 中特殊的 is
特性给了我们一个变通的办法,例如:
1 | <!-- blog 为一个自定义组件 --> |
注意: 如果我们从以下来源使用模板的话,这条限制是不存在的:
- 字符串 (例如:
template: '...'
); - 单文件组件 (
.vue
); <script type="text/x-template">