注意:文中的 vm 为 var vm = new Vue()
,可以在内外部通过vm
引用,也可以在内部通过this
指向
内在
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data
选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty
把这些属性全部转为 getter/setter
。
-
Object.defineProperty
是 ES5 中一个无法 shim 的特性,这也就是 Vue 仅支持IE9及以上版本浏览器的原因。 - 因此初始化实例时不在data中的属性不会自动转换为响应式。且Vue 不允许动态添加根级响应式属性。在初始化实例前应声明所有根级响应式属性,即使为空。
Vue 在更新 DOM 时是异步执行的。在每一个事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。为了在数据更新后等待dom也更新完成,可以使用Vue.nextTick(callback)
或vm.$nextTick()
指令 (Directives)
通常带有 v- 前缀,通过:
传入参数 , 通过.
添加修饰符 , 其值(如有)应为单个 JavaScript 表达式。(且可访问到Date
,Math
等特定的全局变量)指令的职责是,将表达式值的变化更新作用于 DOM。不同于angular.js,在vue中指令和组件是完全不同的两个概念。
- v-text 更新元素的 textContent。
- v-once 仅进行首次插值
- v-show
- v-if / v-else-if / v-else
- v-for
- v-model
- v-html 请勿对用户提供的内容使用该指令,易导致xss攻击
- v-slot 提供具名插槽或需要接收 prop 的插槽。
- v-bind 操作dom属性,可缩写为
:
。对于布尔型特性 ,由于只要出现就意味着值为 true,因此若为null
、undefined
或false
,vue直接不渲染该属性。 - v-on 监听dom事件,可缩写为
@
。- 从 2.6.0 开始,可以用方括号传入字符串或null作为指令参数。字符串不能有空格和引号,且会自动转为小写。null可用于移除绑定。
...
...
- v-pre 对其中的
{{...}}
不进行编译 - v-cloak 这个属性会保持在元素上直到关联实例结束编译。
[v-cloak] {
display: none;
}
...
{{ message }}
计算属性 和 侦听器
定义计算属性 和 侦听器时,均不应使用箭头函数
计算属性
计算属性应处于computed
中,每当计算属性的相关响应式依赖发生改变,则重新求值。
直接在模板语法中执行函数也可以达成该效果,但需注意的是,函数每当页面发生渲染时,都会重新执行,因此性能开销会大于计算属性。好处在于非响应式依赖变更时,函数值也会随着页面渲染而更新。
页面第一次加载时,两个值相同。
若str
发生更新,两值同步更新。
若trigger1
更新,此时页面重新渲染,{{computedFun()}}
更新,而{{computedData}}
不变。
若trigger2
更新,两值都不变。
{{computedData}}
{{computedFun()}}
{{trigger1}}
data:{
str : "当前时间是:",
trigger1 : false,
trigger2 : false
},
computed: {
computedData: function () {
return this.str + new Date()
},
computedData2: vm => vm.str + new Date()
},
methods: {
computedFun(){
return this.str + new Date()
}
}
侦听器
侦听器可以达到与计算属性相同的效果
需要监听对象某个属性时,可以直接将对象.属性
作为key,或将deep
设为true
watch: {
str: function (val,oldVal) {
this.watchedData = val + new Date()
},
str2: "someMethod",
"obj.key": function (val,oldVal) {
...
},
obj2: {
handler: "someMethod",
deep: true,//该回调会在被侦听的对象的任何 property 改变时触发,不论嵌套多深
immediate: true//侦听绑定后(created之前)立刻生效,此时old值为undefined,新值为data中值
}
}
侦听器每次只能侦听一个值,如果需要同时侦听多个,可配合computed
使用
computed: {
tempData: function () {
const { param1 , param2 } = this;
return { param1 , param2 }
}
},
watch: {
tempData: function (val) {
...
}
}
计算属性的getter和setter
计算属性默认为getter方法,也可以给予一个包含get和set方法的对象,当主动设置计算属性值时就会触发setter
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
Class与Style
class有两种绑定方式
- 对象语法
:class="{ 'className' : true , 'className2' : false}"
(值为 truthy 即可,不一定需要为true) - 数组语法
:class="[ 'className1' , 'className2' ]"
注:对自定义添加的class,和该组件本身根元素的class,会取并集
style也有两种绑定方式
- 对象语法
:style="{ 'background-color' : 'red', fontSize: 15 + 'px' }"
- 数组语法
:style="[{ 'background-color' : 'red' }],[{ fontSize: 15 + 'px' }]"
注:对需要加浏览器前缀的CSS属性,vue会自动检测并添加,如transform
条件渲染
值为 truthy 即可,不一定需要为true
v-if / v-else-if / v-else
- 用key管理可复用的元素
- 可以用template当做不可见的包裹元素,并在上面使用 v-if。
注:不要把 v-if 和 v-for 同时用在同一个元素上。(因 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,因此每当页面渲染时不管数组是否发生变化都进行了一次map,不利于性能。)
v-show
v-show不支持template, 有较高的初始渲染开销和较低的切换开销。
列表渲染
- 支持 (均可以为计算属性或一个方法的返回值)
- 数组
- 对象
- 整数(会把模板重复对应次数)
- 建议使用key追踪每个节点的身份
- 类似
v-if
也可以用来循环渲染一段包含多个元素的内容。
v-for="item in items" 或 v-for="item of items"
v-for="(item, index) in items"
v-for="(value, name, index) in object"
通过以下方式变更数组/对象无法触发视图更新
- 利用索引直接设置一个项时,例如:vm.items[index] = newValue
- 修改数组的长度时,例如:vm.items.length = newLength
- 对象属性的新增或删除
- 利用 Object.assign() 或 _.extend() 直接赋值
可通过以下方法解决
Vue.set(vm.target, attrToChange, newValue)
vm.$set(vm.target, attrToChange, newValue)
数组也可以通过splice
方法解决
vm.items.splice(indexOfItem, 1, newValue)
vm.items.splice(newLength)
另外如使用Object.assign()
或 _.extend()
时,参考如下
Object.assign(vm.userProfile, {age: 27}) //无效
vm.userProfile = Object.assign({}, vm.userProfile, {age: 27}) //有效
组件列表
- 组件上使用
v-for
时,必须传入key
- 迭代数据不会自动传入组件,需要依赖prop
事件处理
- 通过
$event
可以把原生DOM事件传入方法
事件修饰符
修饰符可以串联,且其顺序决定了逻辑代码的顺序
- .stop 阻止继续传播
- .prevent 阻止默认事件
- .capture 添加事件监听器时使用事件捕获模式
- .self 仅当 event.target 是自身时触发,不会被子元素触发
- .once 仅执行一次
- .passive (2.3.0 新增) 对应
addEventListener
中的passive
选项,可以提升移动端的性能。会覆盖.prevent
。
按键修饰符
可以将 KeyboardEvent.key
暴露的任意有效按键名转换为 kebab-case 来作为修饰符。如.enter , .tab , .delete (捕获“删除”和“退格”键) , .esc , .space , .up , .down , .left , .right, .ctrl, .alt, .shift, .meta(windows键或command键)
以及鼠标按键.right , .left, .middle
也可以通过config.keyCodes
自定义按键修饰符
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
- 2.5.0 新增
.exact
修饰符
允许控制由精确的系统修饰符组合触发的事件
表单输入
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用 value 属性和 input 事件;
- checkbox 和 radio 使用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
通常情况下v-model 绑定的值是静态字符串或布尔值,但如果使用v-bind:value
则也可以传入其他类型
复选框
单个复选框可绑定到布尔值,或通过true-value
和false-value
绑定其他属性。多个复选框时则可通过value绑定到数组
...
checked : false
toggle : "no"
checkedNames: []
修饰符
- .lazy 在“change”时而非“input”时更新
- .number 将输入值转为number类型
- .trim 自动过滤收尾空白字符