基础
数组更新
vue包含一组观察数组变异方法,使用它们改变数组也会触发视图更新,push/pop/shift/unshift/splice/sort/reverse,但是非变异方法不改变数组(filter/concat/slice),可以用新数组代替就数组实现视图更新。xx = xx.filter()
注意:arr[3]=newVal 不会被检测到
可以:
使用vue内置的set
1
this.$set(arr, 3, newVal)
使用数组的变异方法splice
1
arr.splice(3,1, newVal)
方法与事件
@click调用的方法名可以不带括号”()”,此时,如果方法有参数,默认会将原生事件对象event传入。在大部分场景下,如果方法不需要写参数,可以简便不写括号。Vue提供了一个特殊变量$event,用于访问原生DOM事件,例如下面阻止链接打开。如果使用内联语句,语句可以访问一个 $event 属性:v-on:click=”handle(‘ok’, $event)”1
2
3
4
5<a herf="www.baidu.com" @click="handle('禁止打开',$event)></a>
handle(message, event){
event.preventDefault()
window.aleart(message)
}
事件修饰符
prevent
1
2<form @submit.prevent="submit"></form> // 阻止表单提交刷新页面
<a href="www.baidu.com" @click.prevent="goTo"> // 阻止a链接点击跳转stop
1
<div @click.stop="show"> // 阻止点击事件冒泡
self
1
<div @click.self="show"> // 只在该元素触发时(非子元素)触发回调
capture
1
<div @click.capture="show"> // 使用事件捕获模式
once
1
<div @click.once="show"> // 只触发一次
键盘事件按键修饰符
- enter
- tab
- delete
- space
- up/ down
1
<div @keyup.shift.13="doSomething"> // 只触发一次
v-model
表单控件在实际业务较为常见,比如单选、多选、下拉和输入。v-model用于在表单类元素绑定数据。
1个单选按钮 (不需要v-model, 直接绑定一个boolean)1
2
3
4
5
6
7
8
9
10
11<div id="app">
<input type="radio" :checked="picked">
</div>
<script>
var app = new Vue({
el:'#app',
data:{
picked:true
}
})
</script>
多个单选按钮 (v-model+ value)1
2
3
4
5
6
7
8
9
10<input type="radio" v-model="picked" value="html">
<label for="html">HTML</label>
<input type="radio" v-model="picked" value="CSS">
<label for="css">css</label>
<input type="radio" v-model="picked" value="js">
<label for="js">js</label>
picked: 'js'
多个多选按钮 (v-model+ value)1
2
3
4
5
6
7
8
9
10<input type="checkbox" v-model="checked" value="html">
<label for="html">HTML</label>
<input type="checkbox" v-model="checked" value="CSS">
<label for="css">css</label>
<input type="checkbox" v-model="checked" value="js">
<label for="js">js</label>
checked:['js','css']
v-model修饰符
- .lazy (不在input,而在change时候同步数据,即失焦或回车)
- .number (将输入转换为number类型,否则虽然输入的是数字,类型其实是Strng, 这个在数字输入框比较有用)
- trim (自动过滤首尾空格)
组件
注册和使用
全局注册, 任何vue实例都可以使用。Vue.component(‘my-comp’,{//options})
组件内注册,只有该实例作用域才能使用。 使用components选项
Vue组件的模板在某些情况下会受html的限制,比如table标签规定只允许是tr/td这些表格元素,所以在table里面直接使用组件是无效的,可以用特殊的is属性来挂载组件。1
2
3<table>
<tbody is="my-component"></tbody>
<table>
props传递数据
props中声明的数据与组件data函数reutrn的数据主要区别是props来自父级,而data中的是组件自己的数据,作用域是组件本身。这两种数据都可以在模板template、计算属性computed和方法methods中使用。
有时候传递的数据不是直接写死的,而是来自父级的动态数据,可以用指令v-bind来动态绑定props的值,当父组件数据变化时,也会传递给子组件。
注意:当传递的不是字符串,而是数字、布尔值、数组或对象,而不用v-bind, 传递的仅仅是字符串1
2
3
4
5<my-comp msg='[1,2,3]'></my-comp>
<my-comp :msg='[1,2,3]'></my-comp>
props:[msg]
template:'<div>{{msg.length}}</div>' // 7 3
单向数据流
业务中经常遇到两种需要改变prop的情况,一种是子组件将prop作为初始值保存起来,在自己的作用域下可以随意使用和修改,这种情况可以在组件data内再声明一个数据,引用prop1
2
3
4
5
6props:[initCount]
data:function(){
return {
count: this.initCount
}
}
另外一种是prop作为需要被转变的值传入,这种情况用计算属性就可以1
2
3
4
5props:[width],
template:'<div :style="style"></div>',
computed: style(){
return {width: this.width+'px'}
}
组件通信
自定义事件
v-on除了监听DOM事件外,还可以用于组件间的自定义事件。
$emit 第一个参数是自定义事件的名称。
v-on除了在组件上监听自定义事件外,还可以监听DOM事件,用.native修饰符表示监听的是一个原生事件,是该组件的根元素1
<comp @click.native="handelClick"></comp>
使用v-model
语法糖
1 | <input v-model="price"> |
语法糖,实际上是1
<input :value="price" @input="price=$event.target.value">
v-model作用在自定义组件上1
<cust-input v-model="price"></cust-input>
语法糖,实际上是(两者效果相同)1
2
3<cust-input :value="price" @input="price=argument[0]">
<cust-input :value="price" @input="price= $event"">
//在父级组件监听这个事件的时候,我们可以通过 $event 访问到被抛出的这个值
实现
原理: 数据从父组件通过props传入,子组件内部修改了数据,通过$emit通知父组件修改props
实现一个具有双向绑定v-model的组件需要满足下面两个要求
- 接收一个value属性
- 在有新的value时触发input事件
1 | <custom-input |
slot
当需要让组件组合使用时,混合父组件内容与子组件的模板时,就会用到slot, 这个过程叫做内容分发。
props传递数据,event触发事件和slot内容分发,构成了vue组件的3个api来源,再复杂的组件也是由这3部分组成。
理解作用域
父组件的模板是在父组件作用域内编译的,子组件模板的内容是在子组件作用域内编译的。slot分发的内容,作用域是在父组件上的。
slot用法
在子组件内使用特殊的slot元素就可以为这个子组件开启一个插槽,在父组件模板里插入子组件标签内的所有内容都会替代子组件的slot标签及其内容。
具名slot
1 | <child-comp> |
渲染出1
2
3
4
5
6<div>
<div>i am header</div>
<div>test1</div>
<div>test2</div>
<div>i am content</div>
</div>
作用域插槽
可从子组件插槽获取数据。作用域插槽的使用场景是既能复用子组件的slot, 又可以使slot的内容不一致。
简单理解,父组件可以利用子组件数据为子组件定制模板,定制化信息输出。
一个todolist组件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// <todo-list>
<ul>
<li
v-for="todo in todos"
v-bind:key="todo.id"
>
{{ todo.text }}
</li>
</ul>
// 修改后
<ul>
<li
v-for="todo in todos"
v-bind:key="todo.id"
>
<!-- 我们为每个 todo 准备了一个插槽,-->
<!-- 将 `todo` 对象作为一个插槽的 prop 传入。-->
<slot v-bind:todo="todo">
<!-- 回退的内容 -->
{{ todo.text }}
</slot>
</li>
</ul>
//使用
<todo-list v-bind:todos="todos">
<!-- 将 `slotProps` 定义为插槽作用域的名字 -->
<template slot-scope="slotProps">
<!-- 为待办项自定义一个模板,-->
<!-- 通过 `slotProps` 定制每个待办项。-->
<span v-if="slotProps.todo.isComplete">✓</span>
{{ slotProps.todo.text }}
</template>
</todo-list>
访问
$slots, 主要用于独立组件开发。
高级组件
递归组件
只要给组件设置name选项就可以,在组件内部递归,必须给一个条件限制递归数量,否则会栈溢出。
动态组件
Vue提供了一个特殊的元素component来动态挂载不同的组件,使用is特性来选择要挂载的组件。
异步组件
vue允许将组件定义为1个工厂函数,只在组件需要渲染的时候触发工厂函数,并把结果缓存起来,用于后面再次渲染。工厂函数接收一个resovle回调,在收到服务器下载的组件定义时使用。
其他
$nextTick
重要概念异步更新队列
vue在挂测到数据变化的时候并不会直接更新DOM,而是开启一个队列,并缓冲在同一事件循环中发生的所有的数据改变。在缓冲时去除重复数据,从而避免不必要的计算和DOM操作。然后在下一个事件循环中,vue刷新队列更新DOM
$nextTick就是用来知道什么时候DOM更新完的
手动挂载实例
1 | // demo 1 手动挂载 |
插件
vue-router
前端路由实现方式
- hash
js 通过hashChange事件监听url改变 - history(HTML5)
这种模式需要服务端支持,服务端在收到所有请求后,都指向同一个html文件,不然会出现404.因此SPA只有一个html,整个网站的内容都在这个html里面,通过js来处理。
webpack-dev-server也要配置增加支持history路由,增加–history-api-fallback,所有的路由会指向index.html
前端路由优点
- 页面持久性,像大部分音乐网站,可以播放的时候调到其他页面,音乐不中断
- 前后端分离
基础用法
webpack会把每一个路由打包成一个js文件,在请求到该页面时,采取加载这个页面的js,这就是异步实现的懒加载,按需加载。
路由切换时,切换的是标签router-view挂载的组件。
跳转?
- 使用内置的router-link, 会被渲染成为1个a标签
- $router.replace()/go()/push()
高级用法
路由列表的meta字段可以自定义一些信息。如beforeEach钩子从路由对象to里获取meta信息,从而改变标题。
beforeEach和afterEach可以做很多事情来提升用户体验
页面跳转后滚动条位置
1
2
3router.afterEach((to, from, next)=>{
window.scrollTo(0, 0)
})页面过渡的全局loading动画, beforeEach开始,afterEach结束
- next()方法设置参数,如校验登录
1
2
3
4
5
6
7router.beforeEach((to, from, next)=>{
if(window.localStorage.getItem('token')){
next()
}else{
next('/login')
}
})
vuex
模块
modules/ state/ getter/ mutations/ actions,
每个moudle有自己的state/ getter/ mutations/ actions
重点
mutation尽量不要做异步操作,如果有,组件commit后,数据不能立即改变,而且不知道什么时候改变?
action提交的是mutaion, 而且可以异步操作业务逻辑,组件内通过$store.dispatch触发action.