一.Vue2
1.1 模板语法
1.1.1 模板的理解
html中包含了一些JS语法代码,语法分为两种,分别为:
- 插值语法(双大括号表达式)
- 指令(以v-开头)
1.1.2 插值语法
- 功能:用于解析标签体内容
- 语法:{{xxx}}, xxx会作为js表达式解析
1.1.3 指令语法
- 功能:解析标签属性、解析标签体内容、绑定事件
- 举例:v-bind:href = 'xxxx , xxxx会作为js表达式被解析
- 说明:Vue中有很多的指令,此处只是用v-bind举个例子
1.1.4 单向数据绑定
- 语法:v-bind:href= "xxx" 或简写为:href
- 特点:数据只能从data流向页面
1.1.5 双向数据绑定
- 语法:v-mode:value="xxx" 或简写为 v-mode='xxx'
- 特点:数据不仅能从data 流向页面,还能从页面流向 data
- v-mode.number 制定类型为数字类型
- v-mode.lazy 失去焦点之后收集改变数据
- v-mode.trim 清除前后空格
1.1.6 MVVM 模型
- M:模型(model):对应data中的数据
- V:视图(view):模板--可看到的页面
- VM:视图模型(ViewModel): Vue实例对象
1.1.7 Object.defineProperty (vue中data属性原理 【数据代理】)
const person = {
name: 'zangh',
sex: '男'
}
Object.defineProperty(person, 'age', { // 对象增加一个属性 (对追加的属性设置限制)
value: 18,
enumerable: true, // 控制属性是否可以枚举,默认值是false
writable: true, // 控制属性是否可以被修改,默认值是false
configurable: true, // 控制属性是否可以被删除,默认值是false
})
// 需求:对象中的添加一个属性age = number,当number改变时,person中的age也会改变
let number = 34
Object.defineProperty(person, 'age',
// 当读取person的age属性时候,get(getter)函数会被调用,且返回值就是age的值
get () {
return number
},
// 当修改person的age属性时, set函数(setter)就会被调用,且会收到修改的具体值
set (value) {
console.log('age属性值被修改了,值为' + value)
number = value // 修改 person 中的age同时修改 number 参数值
}
})
1.2 事件处理
1.2.1 绑定监听
- v-on:xxx="fun"
- @xxx="fun"
- @xxx="fun"
- 默认事件形参:event
- 隐含属性对象:$event
1.2.2 事件修饰符
示例: @click.pervent="testClick"
- .prevent:阻止事件的默认行为 event.preventDefault()
- .stop:停止事件冒泡 evevt.stopPropagation()
- .once:事件只触发一次
- .capture:使用时间的捕获模式
- .self: 只有event.target是当前操作的元素时才出发
- .passive: 事件的默认行为立即执行.无需等待事件回调执行完毕 (如weel鼠标滚轮事件,打开之后不等待函数执行完成直接产生默认行为 【页面滚动】)
- 键盘事件 (@keyup.enter="test")
- .enter 回车
- .delete 删除
- .esc 退出
- .space 空格
- .tab
- .up
- .down
- .left
- .right
1.2.3 按键修饰符
- keycode :操作的是某个keycode值的键
- .keyName:操作的某个按键名的键(少部分)
1.3 计算属性与监视
1.3.1 计算属性-computed
- 要显示的数据不存在,要通过计算得来
- 在computed对象中定义计算属性
- 在页面中使用{{方法名}}来显示计算的结果
1.3.2 监视属性-watch
- 通过vm对象的$watch()或watch配置来监视指定的属性
- 当属性变化时,回调函数自动调用,在函数内部进行计算
1.3.3 watch 深度监视
numbers: {
a: 1,
b: 1
}
watch: {
// 监视多集结构中某个属性的变化
'numbers.a': {
handler () {
console.log('a被改变了')
}
},
// 监视多集结构中所有属性的变化
numbers: {
deep: true, // 默认是false
handler () {
console.log('numbers被改变了')
}
}
}
1.4 class与style绑定
- :class='xxx'
// 适用于: 样式的类名不确定,需要动态绑定
<div class="basic" :class="mood"></div>
data () { // 当前div的class为 ‘basic normal’
mood: 'normal'
}
- 表达式是字符传:'classA'
- 表达式是对象:{classA:isA,classB:isB}
// 适用于:要绑定的样式个数确定、名字也确定,但要动态绑定决定用不用
<div class="basic" :class="mood"></div>
data () { // 当前div的class为 ‘basic normal1’
mood: {
normal: true,
normal2: false
}
}
- 表达式是数组:['classA','classB']
// 适用于:要绑定的样式个数不确定、名字也不确定
<div class="basic" :class="mood"></div>
data () { // 当前div的class为 ‘basic normal normal2 normal3’
mood: ['normal', 'normal2', 'normal3']
}
1.4.2 style绑定
- :style="{color:activeColor,fontSize:fontSize+'px'}"
// 适用于:要绑定的样式个数不确定、名字也不确定
<div :style="styleObj"></div>
data () { // 当前div的class为 ‘basic normal normal2 normal3’
styleObj: {
fontSize: '100px',
color: "#999"
}
}
1.5 条件渲染
1.5.1 条件渲染指令
- v-if与v-show
- 当条件不成立时,v-if的所有子节点不会解析(项目中使用)
1.6 列表渲染
1.6.1 列表显示指令
遍历数组:v-for/index
遍历对象:v-for/key
1.7 过滤器
1.7.1 理解过滤器
- 功能:对要显示的数据进行特定格式化后再显示
- 注意:并没有改变原本的数据,是产生新的对应的数据
1.7.2 过滤器使用
<div>{{ time | timeFormater }}</div>
// 全局过滤器
Vue.filter('myscene', function (value) {
return value.slice(1,4)
})
new Vue({
el: '#root',
data: {
time: 12312313
},
methods: {},
// 局部过滤器
filters: {
timeFormater (value) {
return new Date(value)
}
}
})
过滤器可以用来筛选出符合条件的,丢弃不符合条件的
- fillter的作用就是:对值进行筛选加工
- 使用的地方有两个位置和两个方式
位置: {{msg|filterA}}双括号插值内
{{msg}}
// v-bind绑定的值的地方 (msg为需要fillter处理的值,filterA为过滤器) 方式: {{msg|filterA}}单个使用 {{msg|filterA|filterB}} 多个连用过滤器的制作方法
new Vue({
filters:{
//过滤器一:(使用时没有参数,即{{msg|filterA}})
filterA(value){
return “¥”+value
}
}
})
//添加filters属性,该属性内的函数就是过滤器。其中value就是{{msg|filterA}}中的msg。
new Vue({
filters:{
//过滤器二:(使用时有参数,即{{ msg | filterA( arg1, arg2, arg3.... )}})
filterA (value , ...args){//其中msg为filterA中的第一个参数value。
for(arg in args{
console.log(arg)
value+=arg
}
return value
}
},
filterB (value , ...args){
for(arg in args{
console.log(arg)
value+=arg
}
return value
}
}
})
(使用时有参数,即{{ msg | filterA( arg1, arg2, arg3.... ) | filterB( arg1, arg2, arg3.... )}})
此时msg为filterA的第一个参数,filterA执行完后的返回值为filterB的第一个参数,以后也是依次类推。
例如 以开发商需求为案例,需求是将后端返回的字段付款方式用文字显示
- 由于filter中定义的过滤函数不能使用this,需要全局定义一个数组
2.在vue实例中写fillter:{}代码
1.8 内置指令与自定义指令
- v-text:更新元素的 textContent
- v-html:更新元素的innerHTML
- v-if:如果为true,当前标签才会输出到页面
- v-else:如果为false,当前标签才会输出到页面
- v-show:通说控制display样式来控制显示/隐藏
- v-for:遍历数组/对象
- v-on:绑定事件监听,一般简写为@
- v-bing:绑定解析表达式.可以省略v-bing直接用:代替比如 :a=""
- v-model:双向数据绑定
- v-cloak:防止闪现,与css配合:[v-cloak]{display:none}
- v-once:所在节点在初次动态渲染后,就视为静态内容了,以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
- v-pre:跳过所在节点的编译过程,可以领用他跳过:没有指令语法,没有插值语法的节点,会加快编译.
1.8.2 自定义指令
- 注册全局指令
Vue.directive('my-directive', function(el, binding){
el.innerHTML = binding.value.toupperCase()
})
2.注册局部指令
directives : {
// 简写
'my-directive':function (el, binding) {
el.innertext = binding.value * 10
},
// 对象写法
'my-directive': {
// 指令与元素成功绑定时 (这时结构还没渲染到页面上)
bind (el, binding) {
el.innerHTML = binding.value.toupperCase()
},
// 指令所在元素被插入页面时
inserted () {
console.log('inserted')
},
// 指令所在的模板被重新解析时
update () {
console.log('update')
}
}
}
使用指令:v-my-directive='xxx'
1.9 Vue 实例生命周期
1.9.1 生命周期分析
1.初始化显示
beforeCreate()
created()
beforeMount()
// vue 完成模板的解析并且把真实的DOM元素放入页面后(挂载完毕) 调用mounted
mounted()
2.更新状态
beforeUpdate()
updated()
- 销毁vue实例:VM.$destory()
beforeDestory()
destoryed()
1.9.2 常用的生命周期方法
- mounted():发送ajax请求,启动定时器等异步任务
- beforeDestory():做收尾工作,如: 清除定时器
1.10 使用Vue脚手架
1.10.1 ref与props
ref
- 作用:用于给节点打标识
- 读取方式:this.$refs.xxxx
props
- 作用:用于父组件给子组件传递数据
- 读取方式一:至指定名称
props:['name','age','setName']
- 读取方式二:指定名称和类型
props:{
name:String,
age:Number,
setName:Function
}
4.读取方式三:指定名称/类型/必要性/默认值
props:{
name:{
type:String,
required:true,
default:xxx
}
}
1.10.2 mixin 混入
可以把多个组件公用的配置提取成一个混入对象
// mixin.js
export const hunhe = {
methods: {
showName () {
alert(this.name)
}
},
mounted () {
console.log('hello')
}
}
export const hunhe2 = {
methods: {
test () {
alert(this.test)
}
}
}
// 局部引入 template.vue
<script>
import { hunhe, hunhe2 } from '../mixin'
export default {
data() {
return {
name: 'name',
test: 'test'
}
},
mixins: [hunhe, hunhe2]
}
</script>
// 全局引入 main.js
Vue.mixin(hunhe)
Vue.mixin(hunhe2)
1.10.3 插件 Vue.use()
// pluhins.js
export default {
install (Vue) {
// 全局过滤器
Vue.filter('mySlice', function (value) {
return value + 'test'
})
// 混入
Vue.mixin({
data () {
test: 'test'
}
})
// 给vue原型增加方法
Vue.prototype.hello = () => { alert('hello') }
}
}
// main.js
import pluhins from 'pluhins.js'
Vue.use(pluhins)
1.11 Vue 中的自定义事件 绑定事件监听
<Header @addTodo="addTodo"/>
或者
<Header ref="header"/>
触发事件
this.$emit('addTodo', todo)
或者
this.$refs.header.$on('addTodo', this.addTodo)
解绑事件
this.$off('addTodo')
this.$off(['addTodo', 'demo']) // 解绑多个
this.$off() // 所有的自定义事件都解绑
- 子组件传至给父组件:通过父组件给子组件传值为一个函数,通过自定义事件,通过ref去监听子组件的事件
注:当在自定义组件上定义原生事件时候事件名后加native关键字,如:<Student @click.native="show">
1.12 全局事件总线
1.12.1 理解
- Vue 原型对象上包含事件处理方法
- $on(enentName,listner):绑定自定义事件监听
- $emit(eventName,data):分发自定义事件
- $off(eventName):解绑自定义事件监听
- $once(eventName,listener):绑定事件监听,但只能处理一次
- 所有组件实例对象的原型对象
- 所有组件对象都能看到Vue原型对象上的属性和方法
- Vue.prototype.bus=newVue(),所有的组件对象都能看到bus这个属性对象
- 全局事件总线
- 包含事件处理相关方法的对象(只有一个)
- 所有的组件都可以得到
1.12.2 指定事件总线对象
new Vue({
beforeCreate () { // 尽量早的执行挂载全局事件总线对象的操作
Vue.prototype.$globalEventBus = this
},
}).$mount('#root')
1.12.3 绑定事件
this.$globalEventBus.$on('deleteTodo',this.deletetodo)
1.12.4 分发事件
this.$globalEventBus.$emit('deleteTodo', this.index)
1.12.5 解绑事件
this.$globalEventBus.$off('deleteTodo')
1.13 消息订阅与发布
1.13.1 理解
- 这种方式的思想与全局事件总线很相似
- 它包含一下操作:
- 订阅消息--对应绑定事件监听
- 发布消息--分发事件
- 取消消息订阅--解绑事件监听
- 需要引入一个消息订阅与发布的第三方事件库:PubSubJS
1.13.2 使用PubSubJS
- 安装pubsub:
npm i pubsub-js - import PubSub from 'pubsub-js' // 引入
- PubSub.subscrube('msgName',functon(msgName,data){})
- PubSub.publish('msgName',data) // 发布消息,触发订阅的回调函数调用
- 最后在beforeDestroy钩子中取消订阅, PubSub.unsubscribe(this.pubsubId)
mounted() {
// 订阅消息,编写回调函数
this.pubsubId = pubsub.subscribe('hello',(msgName,data)=>{
console.log(`有人发布了${msgName}消息,消息内容是:${data}`)
})
},
1.12 $nextTick
在下一次DOM更新结束后执行指定的回调
this.$nextTick(function () {
this.$refs.inputTitle.focus() // 让 ref=inputTitle的输入框获取焦点
})
1.15 过度与动画
1.15.1 vue动画的理解
- 操作css的trasition或animation
- vue会给目标元素添加/移除特定的class
- 过度的相关类名
- xxx-enter-active:指定显示的 transition
- xxx-leave-active:指定隐藏的 transition
- xxx-enter/xxx-leave-to:指定显示隐藏时的样式
1.15.2 基本过渡动画的编码
- 在目标元素外包裹
- 定义class样式
- 指定过度样式:transition
- 指定隐藏时的样式:opacity/其他 当多个元素需要动画效果时候使用
第三方动画库:animate.css
1.16 slot 插槽
父组件向子组件传递带数据的标签,当一个组件有不确定的结构时, 就需要使用 slot 技术,注意:插槽内容是在父组件中编译后, 再传递给子组件的。
分类
- 默认插槽
- 命名插槽
- 作用域插槽(将子组件中的数据传给组件的使用者)
// 组件
<tempalte>
<div>
<h3>分类</h3>
<slot :games="games">我是某人的内容</slot>
</div>
</tempalte>
<script>
export default {
name: 'Category'
data () {
return {
games: ['123123', '213123213', '123123213']
}
}
}
</script>
// 使用组件
<Category>
<template scope="obj">
<div v-for="(item, index) in obj.games" :key="index">{{ item }}</div>
</template>
</Category>
1.17 vuex
vuex 是什么
- 概念:专门在vue 中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式管理(读/写),也是一种组件间的通信方式,且适用于审议组件间的通信
什么时候使用Vuex
- 多个组件依赖于同一状态
- 来自不同组件的行为需要变更同一状态
1.18 vuex 核心概念和API
1.18.1 state
1. vuex管理的状态对象
2.它应该是唯一的
const state={
xxx:initValue
}
1.18.2 action
1. 值为一个对象,包含多个响应用户动作的回调函数
2.通过commit()来触发mutation中函数的调用,间接更新state
3.如何触发action中的回调
在组件中使用: $store.dispatch('对应的action回调名')触发
4. 可以包含异步代码(定时器,ajax等等)
const actions = {
zzz ({ commit, state }, data1) {
commit('yyy', { data1 })
}
}
### 1.18.3 mutations
1. 值是一个对象,包含多个直接更新state的方法
2.谁能调用mutations中的方法? 如何调用
在action中使用:commit('对应的mutations方法名') 触发
3. mutations中方法的特点:不能写异步代码,只能单纯的操作state
const mutations= {
yyy (state,{data}){
// 更新state的某个属性
}
}
1.18.4 getters
1. 值为一个对象,包含多个用于返回数据的函数
2. 如何使用?---$store.getters.xxx
const getters = {
mmm (state){
return state.msg + '!
}
}
## 1.19. vue-router
路由组件通常存放在pages文件夹,一般组件通常放在components文件夹
实现切换(active-class可配置高亮样式)
<router-link active-class="actine" to="/about"></router-link>
指定路由页面展示位置
<router-view></router-view>
1.19.1 嵌套多级路由
### 1.19.2 路由传参
# query携带参数
<router-link active-class=“actine” :to=`{path: '/home', query: { id: 213, name; 'test' } }`></router-link>
params 携带参数
<router-link active-class=“actine” :to=`/user/${item.id}/${item.name`></router-link>
<router-link active-class=“actine” :to=“{name: '/user', params: { id: 234, name: 'test' }}”></router-link>
// router/index.js
const router = new VueRouter({
routes: [
{
name: 'user'
path: '/user/:id/:name', // 占位
component: User,
children: []
}
]
}]
1.19.3 路由的rops
const router = new VueRouter({
routes: [
{
name: home
path: '/home',
component: Home,
children: [
name: 'test'
path: 'test/:id/:title', // 子路由前面不用写 ‘/’
component: Test,
// props的第一种写法,值为对象;改对象中的所有key--value都会以props传给 Test 组件
props: { a: 1, b: 'hello' }
// props的第二种写法,值为布尔值, 若布尔值为真,就会把该组件收到的所有params参数,以props的形式传给 Test 组件
props: true
// props的第三种写法,值为函数,
props ($route) {
return { id: $route.query.id, title: $route.query.title }
}
]
}
]
})
1.19.5 路由的router-link 的replace
开启 replace
<router-link reeplace active-class="actine" to="/about></router-link>
浏览器的历史记录有两种写入方式:分别为push和replace,push是追加历史记录,replace是替换当前记录.路由在跳转时默认为push
1.19.5 编程式路由导航
- this.$router.push(path):相当于点击路由链接替换当前的路由(可以返回到当前路由界面)
- this.$router.replace(path):用新路由替换当前的路由(不可以返回到当前的路由界面)
- this.$router.back():请求返回上一个记录路由
- this.$router.go(-1):请求返回上一个记录路由
- this.$router.go(1):请求下一个记录路由
- 在新浏览器标签页打开某个路由页面
const {href}=this.$router.resolve({path:'/home',query:{id:23}})
window.open(href,'_blank')
1.19.6 缓存路由组件
让不展示的路由组件保持拦截,不被销毁 include:需要把缓存的组件名,不写则是缓存此路由显示去下的所有组件
<keep-alive include="test">
<router-view></router-view>
</keep-alive>
<keep-alive :include="['test', 'news']">
<router-view></router-view>
</keep-alive>
1.19.7 activated与deactivated生命周期钩子
在组件被设置了路由缓存才存在的钩子
activated () {} // 组件激活时
deactivated () {} // 组件失活时
1.19.8 路由守卫
1.19.8.1 全局路由守卫
const router = new VueRouter({
routes: [
{
name: 'test'
path: '/test', // 占位
component: Test,
meta: { isAuth: false, title: '测试' },
},
{
name: 'home'
path: '/home', // 占位
component: Home,
// 路由附带属性
meta: { isAuth: true, title: '主页' },
children: [
{
name: 'user'
path: 'user', // 占位
component: User,
meta: { isAuth: true, title: '用户' },
},
{
name: 'news'
path: 'news', // 占位
component: News,
meta: { isAuth: true, title: '新闻' },
// 独享路由守卫 (只有前置没有后置)
beforeEach((to, from, next) => {
if (!to.meta.isAuth) next() // 判断是否需要鉴权
if (localStorage.getitem('test') === 'test') {
next()
} else {
alert('无权限查看')
}
})
}
]
}
]
}]
// 全局前置路由守卫,初始化的时候与每次切换路由的时候被调用
router.beforeEach((to, from, next) => {
if (!to.meta.isAuth) next() // 判断是否需要鉴权
if (to.path === '/home/user' && localStorage.getitem('test') === 'test') {
next()
} else {
alert('无权限查看')
}
})
// 后置路由守卫,初始化和每次路由切换之后被调用
router.afterEach((to, from) => {
// 例:根据页面更改网页标签的标题
document.title = to.meta.title || 'vue'
})
export default router
1.19.8.2 组件内路由守卫
<scrip>
export default {
data () {},
// 通过路由规则进入该组件时被调用
beforeRouteEnter (to, from, next) {
next()
}
// 通过路由规则离开该组件时被调用
beforeRouteLeave (to, from, next) {
next()
}
}
</script>
1.19.9 history 模式与hash模式
const router = new VueRouter({
mode: 'history', // 默认是hash
routes: [
{
name: 'test'
path: '/test', // 占位
component: Test,
meta: { isAuth: false, title: '测试' },
}
]
}]
export default router
1.20 Vue UI 组件库
1.20.1 移动端常用UI组件库
- Vant youzan.github.io/vant
- Mint UI mint-ui.github.io
1.20.2 PC端常用UI组件库
- Element UI element.eleme.cn
- IView UI www.iviewui.com
1.21 总结
data: {
// 定义参数
},
methods: {
// 定义函数
},
filters: {
// 定义过滤器
},
computed: {
// 定义计算属性
},
watch: {
// 定义监听
},
directives: {
// 定义自定义指令
},
***********生命周期函数************
beforeCreate () {
// 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用此时组件的选项还未挂载,因此无法访问methods,data,computed上的方法或数据
},
created () {
// 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
// 这是一个常用的生命周期,因为你可以调用methods中的方法、改变data中的数据,并且修改可以通过vue的响应式绑定体现在页面上、获取computed中的计算属性等等。
},
beforeMount () {
// 在挂载开始之前被调用:相关的 render 函数首次被调用。
},
mounted () {
// el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
// 1.在这个周期内,对data的改变可以生效。但是要进下一轮的dom更新,dom上的数据才会更新。
// 2.这个周期可以获取 dom。 之前的论断有误,
// 3.beforeRouteEnter的next的勾子比mounted触发还要靠后4.指令的生效在mounted周期之前
},
beforeUpdate () {
// 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
},
updated () {
// 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新
// 所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。
},
beforeDestroy () {
// 实例销毁之前调用。在这一步,实例仍然完全可用。
// 这一步还可以用this来获取实例。2.一般在这一步做一些重置的操作。比如清除掉组件中的 定时器 和 监听的dom事件
},
destroyed () {
// Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
},
**************指令的周期*****************
bind () {
// 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
}
inserted () {
// 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。 实际上是插入vnode的时候调用。
}
update () {
// 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。慎用,如果在指令里绑定事件,并且用这个周期的,记得把事件注销
}
componentUpdated () {
// 被绑定元素所在模板完成一次更新周期时调用。
}
unbind () {
// 只调用一次, 指令与元素解绑时调用。
}
***********keep-alive周期函数***********
activated () {
// 在组件第一次渲染时会被调用,之后在每次缓存组件被激活时调用。
},
deactivated () {
// 组件被停用(离开路由)时调用。使用 keep-alive 就不会调用 beforeDestroy(组件销毁前钩子)和 destroyed(组件销毁),因为组件没被销毁,被缓存起来了,这个钩子可以看作 beforeDestroy 的替代
}
***************全局路由钩子**************
beforeEach () {
// router.beforeEach
// 示例router.beforeEach((to,from,next)=>{ console.log('路由全局勾子:beforeEach -- 有next方法')next()})
// 一般在这个勾子的回调中,对路由进行拦截。
// 比如,未登录的用户,直接进入了需要登录才可见的页面,那么可以用next(false)来拦截,使其跳回原页面。
// 值得注意的是,如果没有调用next方法,那么页面将卡在那。
// next的四种用法
// 1.next() 跳入下一个页面
// 2.next('/path') 改变路由的跳转方向,使其跳到另一个路由
// 3.next(false) 返回原来的页面
// 4.next((vm)=>{}) 仅在beforeRouteEnter中可用,vm是组件实例。
},
afterEach () {
// 示例router.afterEach((to,from)=>{console.log('路由全局勾子:afterEach---没有next方法')})
// 在所有路由跳转结束的时候调用,和beforeEach是类似的,但是它没有next方法
}
***************组件路由勾子**************
beforeRouteEnter () {}
beforeRouteUpdate () {}
beforeRouteLeave () {}