来阅读和总结一下Vue官方文档吧~(平时自己不太清晰或者没有注意到的部分内容)
箭头函数里的this拿不到Vue实例对象: 因为箭头函数是和父级上下文绑定在一起的
所以不要出现以下错误的写法:
1 | created: () => console.log(this.a) |
v-once:指令只执行一次插值,数据变化时不更新。
v-html:不要对用户提供的内容使用插值,容易导致XSS攻击。
场景: 一个提交评论的功能,评论内容是v-html来展示的,用户提交一个可执行的script脚本用来窃取cookie,token,用户信息等等。其它用户查看该评论时v-html自动执行脚本,信息被窃取。
动态style:对象语法{}一个对象,动态切换class;数组语法[],多个class。vue.js会自动添加需要添加浏览器引擎前缀。
自定义组件上的class: 会添加到该组件根元素而不是覆盖。
动态style:
对象语法:
1 | // html |
数组语法:
1 | <div v-bind:style="[baseStyles, overridingStyles]"></div> |
浏览器前缀2.3.0+版本属性值可以是一个带前缀的数组,之后渲染最后一个值
1 | <div :style="{display: ['-webkit-box', '-ms-flexbox', 'flex']}"></div> |
v-if和template元素:
何时使用template:
- 当条件判断需要切换不同的元素时使用。template标签天生不可见,当需要对一些内容进行v-if条件判断时,可以在外层包裹template元素,减少dom层。
只是显示或隐藏同一个元素,直接在元素上v-if即可,或者外层包裹div
v-else
- v-else-if
需要紧跟在v-if后面,否则不识别。与条件判断语句逻辑相同
key管理元素复用:Vue默认复用已有元素,不会从头开始渲染,效率比较快。
- 给元素加上key属性:表示完全独立的元素,不复用。
终于知道为什么v-for要绑定key了,防止复用,唯一
v-show与v-if: 如果在允许时条件很少改变使用v-if较好,频繁的变化使用v-show较好。
- v-show: 只是改变display属性是否为none,一开始就会被渲染,每次都会被渲染;
- v-if: 只有当条件为真时才渲染,影响dom,销毁和重建
v-if 与 v-for一起使用时:v-for 优先级更高,v-if会重复运行于每个v-for循环中(类似于循环内部的if判断)
v-for: 记得动态绑定key
1
2
3
4
5
6
7
8
9
10
11
12
13<--数组-->
<ul id="example-1">
<li v-for="(item, index) in arr" :key="item.id">
{{ item.message }}
</li>
</ul>
<--对象-->
<ul id="example-2">
<li v-for="(value, key, index) in obj" :key="key">
{{key}} - {{value}} -{{index}}
</li>
</ul>
数组
- 会改变原数组的方法
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
- 不改变原数组的方法
- filter()
- concat()
- slice()
避免不必要的处理数据出现的bug(最近我自己就用sort又忘记它会改变原数组)
检测不到数组变化的情况
利用索引直接设置一个项时arr[index] = newValue;
解决:
this.$set(arr, index, newValue)
arr.splice(index, 1, newValue)
修改数组长度 arr.length = newLength;
解决:
arr.splice(newLength)
对象更改检测注意事项:检测不到对象属性的添加或删除
1 | <div>{{obj}}</div> |
v-for 和 template: 用于渲染多个元素的时候
1
2
3
4
5
6<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
事件
想要拿到event对象,传入特殊变量$event即可
v-on:click.prevent.self
会阻止所有的点击,而v-on:click.self.prevent
只会阻止对元素自身的点击。 (一直不太理解,下面这个图感觉解释的比较清楚)![](Vue-js官方文档温故小结\QQ截图20180809174430.png %}
事件修饰符.prevent :对应addEventListener 中的 passive 选项(解决移动端滑动,滚动卡顿而诞生的)
- 这个
.passive
修饰符尤其能够提升移动端的性能。 - 不要把
.passive
和.prevent
一起使用
- 这个
按键修饰符
ASCII码值
1
<input v-on:keyup.13="submit">
按键别名
- .enter
- .tab
- .delete
- .esc
- .space
- .up
- .down
- .left
- .right
可以通过全局
config.keyCodes
对象自定义按键修饰符别名:1
2// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112鼠标按钮修饰符2.2.0+
- .left
- .right
- .middle
表单
v-model 指令在表单 input、textarea 及 select 元素上创建双向数据绑定
- 修饰符
- .lazy: 原本v-model绑定的值是实时更新的,这个修饰符就是转变为change事件同步,change事件是失去焦点时触发。
- .number: 将输入的值转为数值。
- .trim: 过滤首尾空白字符
组件
基础组件的自动化全局注册:多个全局共用的基础组件时使用(暂时没有用到过,点击跳转官网)
- 组件上的事件修饰符.native: 可以监听组件根元素事件
- .sync修饰符: props传递的值是单向数据流,想父组件传递给子组件,子组件更新这个值,父组件也同步更新。这时可以使用.sync实现prop”双向绑定”。
slot插槽
匿名插槽: 父组件内容分发到插槽
具名插槽: 子组件slot插槽的name属性和父组件slot属性对应,分发到对应name的插槽
插槽默认内容:组建插槽内可以有默认内容,当父组件为这个插槽提供了内容,将被覆盖。
作用域: 父组件模板的内容都会在父组件作用域内编译,子组件模板的所有内容都会在子组件作用域内编译。
作用域插槽:可以从子组件获取数据的可复用插槽
写法:
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<!-- 组件 todo-list-->
<ul>
<li
v-for="todo in todos"
v-bind:key="todo.id"
>
<!-- 我们为每个 todo 准备了一个插槽,-->
<!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot :todo="todo" :arr="arr">
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>
<!-- 父组件使用组件 -->
<todo-list v-bind:todos="todos">
<!-- 将 `slotProps` 定义为插槽作用域的名字 -->
<template slot-scope="slotProps">
<!-- 为待办项自定义一个模板,-->
<!-- 通过 `slotProps` 为一个对象 插槽可以传入多个prop-->
<span v-if="slotProps.todo.isComplete">✓</span>
{{ slotProps.todo.text }}
<span> {{ slotProps.arr }} </span>
</template>
</todo-list>
<!-- slot-scope 使用结构赋值的写法 看起来更简洁一些-->
<todo-list v-bind:todos="todos">
<template slot-scope="{todo, arr}">
<span v-if="todo.isComplete">✓</span>
{{ todo.text }}
<span> {{ arr }} </span>
</template>
</todo-list>
动态组件:component 的is属性
1 | <component v-bind:is="currentTabComponent"></component> |
1 | components:{ |
结合keep-alive做缓存
1 | <keep-alive> |
异步组件:需要的时候才从服务器加载这个模块。
全局注册
1
2
3
4
5Vue.component(
'async-webpack-example',
// 这个 `import` 函数会返回一个 `Promise` 对象。
() => import('./my-async-component')
)局部注册
1
2
3components: {
'my-component': () => import('./my-async-component')
}2.3.0+新增异步组件函数返回对象属性:来处理加载状态
1
2
3
4
5
6
7
8
9
10
11
12
13const AsyncComponent = () => ({
// 需要加载的组件 (应该是一个 `Promise` 对象)
component: import('./MyComponent.vue'),
// 异步组件加载时使用的组件
loading: LoadingComponent,
// 加载失败时使用的组件
error: ErrorComponent,
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})
特殊情况: 一些需要对vue规则做一些小调整的特殊情况
访问根实例: $root (项目比较大时推荐vuex)
子组件访问父组件实例: $parent
访问子组件或子元素:给组件绑定ref,通过$ref访问,$refs在组件渲染完成之后生效,不是响应式
依赖注入:父组件通过provide提供变量及方法,子组件通过inject注入(依然推荐vuex)
1
2
3
4
5
6
7
8
9// 父组件
provide: function () {
return {
getMap: this.getMap,// 方法
mapInfo: this.mapInfo // 对象数据
}
}
// 子组件
inject: ['getMap', 'mapInfo']
事件侦听器:
- $on
- $once
- $off
循环引用
递归组件: 组件可以在自己的模板中调用自身,确保递归是条件性的,避免无限循环
1
2
3name: 'stack-overflow',
template: '<div><stack-overflow></stack-overflow></div>'
// 死循环,可以使用v-if条件判断
控制更新
强制更新:极少数情况下需要手动强制更新可以通过$forceUpdate
v-once创建静态组件:需要渲染大量静态内容,除非觉得渲染非常慢,否则不推荐
1
2
3
4
5
6<div v-once>
<h1>
大量静态数据
</h1>
...
</div>