Vue 实例从建立到销毁的过程,就是生命周期。html
同时在这个过程当中也会运行一些叫作生命周期钩子的函数,这给了用户在不一样阶段添加本身的代码的机会,利用各个钩子来完成咱们的业务代码,钩子以下:vue
1.beforeCreate
实例初始化以后、建立实例以前被调用,此时数据观察和事件配置都还没好准备好
2.created
实例建立完成后被调用,此时data有了,dom尚未,挂载属性el还没生成webpack
3.beforeMount
将编译完成的html挂载到对应的虚拟dom时调用,此时相关的render函数首次被执行,页面尚未内容,表达式{{ }}的值还未被替换
4.mounted
编译好的html挂载到页面完成后调用,此时页面已经被渲染出数据web
5.beforeUpdate
数据更新时调用,发生在虚拟 DOM 从新渲染和打补丁以前。 你能够在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
6.update
因为数据更改致使的虚拟 DOM 从新渲染和打补丁,在这以后会调用该钩子。vue-router
7.beforeDestroy
销毁前调用
8.destroyed
销毁后调用,Vue 实例指示的全部东西都会解绑定,全部的事件监听器会被移除,全部的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。vuex
🍃 资料1:标注图+部分举例聊聊Vue生命周期
🍃 资料2:关于Vue实例的生命周期created和mounted的区别vue-cli
1.v-text
:更新元素的 textContent
2.v-html
:更新元素的 innerHTML
3.v-show
:根据表达式之真假值,切换元素的 display CSS 属性
4.v-if
、v-else-if
、v-else
:条件判断
5.v-for
:基于源数据屡次渲染元素或模板块
6.v-on
:(语法糖 @
)绑定事件npm
修饰符:segmentfault
7.v-bind
(语法糖 :
)当表达式的值改变时,将其产生的连带影响,响应式地做用于DOM
8.v-model
:表单元素实现双向数据绑定api
修饰符:
🍃 资料1:Vue.js入门教程-指令
经过directive
就能够在Vue
上注册一个自定义指令(全局注册、局部注册)
🌰 举例注册一个自定义指令,实现页面加载自动聚焦到元素
// 1. 注册一个全局自定义指令 `v-focus` Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } }) // 2. 注册一个局部自定义指令 `v-focus` directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } } // 使用 <input v-focus>
🍃 资料1:【译】vue 自定义指令的魅力
🍃 资料2:vue 自定义指令
过滤器(全局过滤器,局部过滤器)能够经过管道符号|
实现文本数据的格式化,能够用在表达式 {{}}
和bind
中
// 全局过滤器 Vue.filter('toTime', function(value) { //value 表示要过滤的内容 }) // 批量注册全局过滤器 import * as filters from "config/filters" Object.keys(filters).forEach(key => { Vue.filter(key, filters[key]); }); // 局部过滤器 var app = new Vue({ el: '#app', data: {}, filters: { toTime: function(value){ //value 表示要过滤的内容 } } }) // 使用 <div :data-time="date | toTime">{{ date | toTime }}</div>
过滤器能够串联、接收参数,好比:
{{ message | filterA | filterB }} {{ message | filterA('p1', 'p2') }}
使用方法:
<p>个人名字:{{ fullname }}</p> var vm = new Vue({ el: '#app', data: { firstname: 'jack', lastname: 'rose' }, computed: { fullname() { return this.firstname + '.' + this.lastname } } })
注意:computed
中的属性不能与data
中的属性同名,不然会报错。
Q: {{ }}
、computed
、methods
里面的方法分别在什么状况下使用 ?
`{{}}`经常使用于简单的运算,当过长或逻辑复杂时会变得难以维护。 `computed`经常使用语复杂逻辑运算,基于依赖缓存。 当计算属性所依赖的数据发生变化时,才会从新取值,当遍历大数组或作大量计算时使用计算属性比较好 `methods`里的方法只要从新渲染就会被调用,函数也会被执行。
监测属性watch
能够经过监测数据来响应数据的变化,可在数据变化时须要执行异步或开销较大的操做时使用。
它是一个对象,键是须要观察的表达式,值是对应回调函数,回调函数接收两个参数分别是新值和旧值。
⚠️ 注意:watcher
回调函数不可用箭头函数,箭头函数绑定了父级做用域的上下文,会改变this
指向。
new Vue({ data: { a: 1, b: { age: 10 } }, watch: { a: function(newVal, oldVal) { //若是a发生改变,这个函数就会运行 }, /** * 监听对象变化 * deep - 深度监测,对象内部属性或方法发生改变,使用它才能监测到该对象的改变 * immediate - 当即执行,初始化的时候 watch 是不会执行的,若是想在初始化的时候就执行,则需开启这个属性 */ b: { handler: function (val, oldVal) { //TODO ... }, deep: true, immediate: true }, /** * 监听对象具体某个属性的变化 */ 'b.age': function (val, oldVal) { //TODO ... }, } })
Q: watch
在任什么时候候均可以监测的到数据变更吗?
vm.items[0] = {}
vm.items.length = 0
以上三种状况下均数据发生改变时,watch
都不能检测出来,解决办法以下:
vue
提供的方法,如$set()、$delete()等
Object.assign()
、JSON.parse(JSON.stringify(obj))
、{...obj}
、[...arr]
等🍃 资料1:Vue watch选项
🍃 资料2:Vue的computed和watch的细节全面分析
🍃 资料3:Vue中$watch的监听变化 & vue中正确的使用watch进行监听
方法:
使用Vue.component(tagName, options)
能够注册一个全局的组件
全局组件在全部的vue实例中均可以使用
let myButton = Vue.extend({ template: `<button>点击我</button>`, // 组件中的 data 必须是函数 而且函数的返回值必须是对象 data() { return {} } }) Vue.component('my-button', myButton)
语法糖:
Vue.component('my-button', { template: `<button>点击我</button>` })
使用:
<div id="app"> <my-button /> </div>
方法:
使用Vue
实例 / 组件实例选项中components
注册
局部注册的组件只能够应用在当前实例中。
let myButton = Vue.extend({ template: `<button>点击我</button>` }) let app = new Vue({ el: '#app', components: { 'my-button':myButton } })
语法糖:
let app = new Vue({ el: '#app', components: { 'my-button': { template: `<button>点击我</button>` } } })
使用:
<div id="app"> <my-button /> </div>
🍃 资料:Vue.js入门教程-组件注册
1.
子组件能够经过props
声明从父组件接收过来的数据,props
值分两种,一种是字符串数组,一种是对象 (须要对值验证能够用对象)。
2.
因为html
特性不区分大小写,当使用dom
模板时,驼峰命名的props
名称要转为短横线分隔命名(字符串模板除外)
3.
若是传递的数据不是直接写死的,而是来自父级的动态数据,可使用指令v-bind
来动态绑定 props
的值,当父组件的数据变化时,也会传递给子组件 ,反之不行
4.
业务中常常会遇到两种须要改变props
的状况:
可是,以上两种状况,针对于引入类型的数据,在子组件中修改值是会影响到父组件的值的,须要注意!
例子:基于vue-cli
// 父组件 - 传递 msg1 的值到子组件 <template> <div class="parent-box"> 我是父组件 <child :msg1="msg1"></child> </div> </template> <script> import child from "./components/child"; export default { name: "app", components: { child }, data() { return { msg1: "我是msg1 - 父组件传给子组件的第1个值", }; } }; </script>
//子组件child - 接收来自父组件的 msg1 的值 <template> <div class="child-box"> 我是子组件 {{msg1}} </div> </template> <script> export default { name: "child", props: ["msg1"], //props 接收来自父组件传递过来的值 }; </script>
当子组件须要像父组件传递数据时,就要用到自定义事件。
相似观察者模式,子组件用$emit
来触发事件,父组件用v-on
(语法糖@
)来监听子组件触发的自定义事件。
用法: step1
:父组件 - 定义一个方法,并经过v-on
(语法糖@
)绑定给子组件,如:
<child :msg1="msg1" @changeMsg1="changeMsg1"></child>
step2
:子组件 - 经过 $emit
触发已绑定的方法,如:
//参数1 eventName - 方法名 //参数2 [...arg] - 要返给被触发方法的参数 this.$emit("changeMsg1", '传给父组件的参数');
例子:
//父组件 - 传递给子组件一个函数 changeMsg1 <template> <div class="parent-box">我是父组件 <child :msg1="msg1" @changeMsg1="changeMsg1"></child> </div> </template> <script> import child from "./components/child"; export default { name: "app", components: { child }, data() { return { msg1: "我是msg1 - 父组件传给子组件的第1个值", }; }, methods: { //参数 data 是子组件传递过来的参数 changeMsg1(data) { this.msg1 = data; } } }; </script>
//子组件child - 给 button 绑定 handleClick 方法,在 handleClick 中经过 $emit 去触发changeMsg1方法,并传参过去 <template> <div class="child-box"> {{msg1}} <button @click="handleClick">btn</button> </div> </template> <script> export default { name: "child", props: ["msg1"], methods: { handleClick() { this.$emit("changeMsg1", '传给父组件的参数'); } } }; </script>
this.$parent
能够直接访问该组件父实例或组件(子 -> 父),父组件也能够经过this.$children
访问全部子组件(数组)(父 -> 子),并且能够递归向上或向下无线访问,直到根实例或最内层组件。
业务中子组件应该应该尽量避免依赖父组件数据,更不应主动修改父组件数据,这样会使父子组件耦合严重,只看父组件很难理解父组件状态,由于父组件的值可能被随意修改了。
这种方式适用于一个页面单纯的拆分红多个组件组合在一块儿的状况,被拆分的组件只有一个公用且肯定了的父组件。
例子:
//父组件 - 经过 $children 改变子组件 tip 值 <template> <div class="parent-box"> 我是父组件 <child :msg="msg"></child> <button @click="handleClick">父btn</button> </div> </template> <script> import child from "./components/child"; export default { name: "app", components: { child }, data() { return { msg: "我是父组件 msg 的值" }; }, methods: { handleClick() { this.$children.map(i => { i.tip = "我是父组件,我用 $children 改变了子组件 child 中 tip的值"; }); } } }; </script>
//子组件 - 经过 $parent 改变父组件 msg 值 <template> <div class="child-box"> 我是子组件 {{tip}} {{msg}} <button @click="handleClick">子btn</button> </div> </template> <script> export default { name: "child", props: ["msg"], data() { return { tip: "我是子组件的数据,谁能改变我?" }; }, methods: { handleClick() { this.$parent.msg = "我是子组件,我用 $parent 改变了父组件中 msg 的值"; } } }; </script>
当子组件不少时,很难经过$children
遍历出来须要的组件实例,能够用ref
来为子组件指定一个索引名称,而后用this.$refs[name]
来查找
例子:
//父组件 - 用 ref 给子组件 child 设置索引名,经过 refs 去查找子组件 <template> <div class="parent-box"> 我是父组件 <child ref="component1" :msg="msg"></child> <button @click="handleClick">父btn</button> </div> </template> <script> import child from "./components/child"; export default { name: "app", components: { child }, data() { return { msg: "我是父组件 msg 的值" }; }, methods: { handleClick() { this.$refs.component1.tip = '我是父组件,我要经过 $refs 来查找子组件 child 并修改 它的 tip 值' } } }; </script>
若是涉及到爷孙之间、兄弟之间或更深层次组件之间须要通讯,能够声明一个vue
实例,把公共方法和属性放在这个实例上面,让这个实例充当一条通信桥梁。
范围:适用于简单场景,复杂场景请用 vuex
步骤:基于vue-cli
step1:
建立一个vue
实例,挂载到全局,好比:
//main.js 文件 Vue.prototype.$bus = new Vue(); //或 window.$bus = new Vue();
step2:
用$on
和$emit
完成通讯
// $on 监听事件,处理回调 bus.$on('eventName', val => { //TODO... }) // $emit 触发事件,返回参数 bus.$emit('eventName', val)
例子:让两个同级组件通信
//main.js - 声明一个全局变量来保存 vue 实例 import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false Vue.prototype.$bus = new Vue(); // $bus new Vue({ render: h => h(App), }).$mount('#app')
// 根组件 - 包含两个子组件 <template> <div class="parent-box"> 我是父组件 <child></child> <child2></child2> </div> </template> <script> import child from "./components/child"; import child2 from "./components/child2"; export default { name: "app", components: { child, child2 } }; </script>
//child 子组件 - $on 监听事件,若是有新参数进来当即替换 childMsg 值 <template> <div class="child-box"> 我是子组件 child {{childMsg}} </div> </template> <script> export default { name: "child", data() { return { childMsg: "我是child的数据" }; }, created() { //$on 监听 this.$bus.$on('changeMsg', data => { this.childMsg = data; }) }, }; </script>
//child2 - $emit 触发事件,并传递参数到 changeMsg 方法中 <template> <div class="child-box"> 我是子组件 child2 <button @click="handleClick">child2 btn</button> </div> </template> <script> export default { name: "child2", methods: { handleClick() { //$emit 触发 this.$bus.$emit('changeMsg', '我是 child2 ,我更改了 child 的 childMsg 值') } } }; </script>
v-model
能够在 表单控件 或者组件上建立双向绑定。
表单控价上的双向绑定,如:
<input v-model="msg"> //至关于: <input :value="msg" @input="msg = $event.target.value">
如上,能够看出语法糖v-model
的实现过程:将input
标签用v-bind
绑定value
属性,v-on
绑定input
事件。当输入框的文本发生改变时,自动将属性value
的值替换成目标输入值。
那么,换到组件中该怎么实现呢?
父组件:
经过v-model
绑定变量
<child v-model="msg"></child> //至关于 <child :value="msg" @input="msg = arguments[0]"></child>
子组件:
value
属性value
时触发input
事件举个栗子:
// 父组件 - 用 v-model 绑定 msg <template> <div class="parent-box"> 我是父组件 这是个人 msg 值:{{msg}} <child v-model="msg"></child> </div> </template> <script> import child from "./components/child"; export default { name: "app", components: { child }, data() { return { msg: "我是父组件的 msg" }; } }; </script>
//子组件 - 经过 props 接收 value,用 $emit 触发 input 事件 <template> <div class="child-box"> 我是子组件 child <button @click="handleClick">child's btn</button> </div> </template> <script> export default { name: "child", props: ["value"], methods: { handleClick() { this.$emit("input", "我是 child,这是我传给父组件的新值"); } } }; </script>
上例中,若是属性value
被占用了,或者input
事件冲突了,就会引发报错,因此最好用 model 属性来定制 v-model
定制方法:model { prop?: string, event?: string }
上例中,child
组件重写为:
//child - 经过 model 定制 v-model <template> <div class="child-box"> 我是子组件 child <button @click="handleClick">child's btn</button> </div> </template> <script> export default { name: "child", model: { prop: 'msg', //代替 value event: 'changeMsg' //代替input方法 }, props: ["msg"], methods: { handleClick() { this.$emit("changeMsg", "我是 child,这是我传给父组件的新值"); } } }; </script>
2.3版本中从新引入的.sync 修饰符做为语法糖存在,它会被扩展为自动更新父组件属性的v-on
监听器,以下:
<child :msg.sync="msg"></child> //至关于 <child :msg="msg" @update:msg="val => msg = val"></child>
当子组件须要更新msg
时,触发update方法,将旧值替换成新值,以下:
this.$emit('update:name', newVal)
一次性想传递多个属性时,能够结合v-bind
一块儿使用,以下:
//父组件 - 传递一个对象到子组件,会分别为对象的每一个属性分配一个 v-on 监听器 <template> <div class="parent-box"> 我是父组件 {{info.msg1}} {{info.msg2}} <child v-bind.sync="info"></child> </div> </template> <script> import child from "./components/child"; export default { name: "app", components: { child }, data() { return { info: { msg1: 1111, msg2: 2222 } }; } }; </script>
//子组件 - $emit 触发事件 <template> <div class="child-box"> 我是子组件 child <button @click="handleClick">child's btn</button> </div> </template> <script> export default { name: "child", methods: { handleClick() { this.$emit("update:msg1", "33333"); this.$emit("update:msg2", "44444"); } } }; </script>
1.在多级组件通讯中,$attrs & $listeners 分别负责收集父组件中传递过来的属性和事件,其中$attr
中收集的属性不包括组件中已经过props
接受的属性,$listeners
中收集的事件不包括有.native
修饰符的事件。属性经过v-bind="$attrs"
一级级向下传递, 事件经过v-on="$listeners"
一级级向下传递。
2.$attrs
中包含的属性,默认状况下将会做为普通的HTML
属性应用在子组件的根元素上,能够经过在当前组件中设置inheritAttrs: false
去掉(style
, class
除外),去掉默认行为不影响数据的使用。
例如:
未设置 inheritAttrs: false
时:
<div class="grandson-box" msg3="333" msg4="444"></div>
设置了 inheritAttrs: false
时:
<div class="grandson-box"></div>
3.适用范围:简单的多级组件通讯
例子:
// 一级组件 - 经过 v-bind, v-on 传递属性和事件到下级组件 <template> <div class="parent-box"> 我是爷爷 <son v-bind="msg" @event1="event1" @event2.native="event2" @event3="event3" @event4="event4"></son> </div> </template> <script> import son from "./components/son"; export default { name: "app", components: { son }, data() { return { msg: { msg1: 111, msg2: 222, msg3: 333, msg4: 444 } }; }, methods: { event1() { console.log(1); }, event2() { console.log(2); }, event3(data) { console.log(3, data); //3, 我是孙子组件grandson传递到爷爷那去的参数 }, event4() { console.log(4); } } }; </script>
// 二级组件 - 经过 v-bind="$attrs" v-on="$listeners" 传递属性和事件到下一级组件中 <template> <div class="son-box"> 我是儿子 {{$attrs}} <grandson v-bind="$attrs" v-on="$listeners"/> </div> </template> <script> import grandson from "./grandson"; export default { name: "son", inheritAttrs: false, //组件根部屏蔽掉 $attrs 的属性,可是值仍然存在只是不展现在 html 上了 components: { grandson }, props: ["msg1", "msg2"], //经过 props 接收的属性 会被过滤,不存在 $attrs 中 created() { console.log("----- son -------"); //若是上级组件传递过来的事件含有 .native 修饰符,则该事件被过滤, 不存在 $listeners 中 console.log(this.$listeners); //{event1: ƒ, event3: ƒ, event4: ƒ} } }; </script>
// 三级组件 <template> <div class="grandson-box"> 我是孙子 {{$attrs.msg3}} </div> </template> <script> export default { name: "grandson", created() { console.log("------ grandson ------"); console.log(this.$listeners); //{event1: ƒ, event3: ƒ, event4: ƒ} this.$listeners.event3("我是孙子组件grandson传递到爷爷那去的参数"); } }; </script>
🍃 资料一:vue组件的那点事
🍃 资料二:vue组件通讯全揭秘(共7章)
🍃 资料三:Vue.js 父子组件通讯的十种方式
===================== 分割线 ====================
vue-router
的使用流程(基于vue-cli
):
vue-router
router
实例,将配置好的路由传入vue-router
yarn add vue-router -S
1.引入vue
及 vue-router
import Vue from 'vue' import VueRouter from 'vue-router'
2.注册
Vue.use(VueRouter)
基于vue-cli
,咱们在写好页面组件以后,一般会经过import
或require
引入到管理路由的文件中,普通引入方式以下:
import login from '../page/login'; //或者 const login = require('../page/login').default;
注意:用 require 引入组件时须要加 default,不然报错!
扩展:exports、module.exports 和 export、export default 究竟是咋回事
这种普通的引入方式有一个缺点,就是在npm run build
的时候,全部引入的文件最终会被打包成一个文件,加载的时候会加载整个文件,文件过大会致使页面加载缓慢,为了解决这个问题,咱们一般在项目中将它分红多个小的代码块来加载,一般用如下三种方法:
第一种:异步组件
当须要这个组件的时候,会异步加载过来,并将结果储存以供下次使用。
const login = resolve => require(['../page/login'], resolve)
第二种:懒加载组件
结合Vue
的异步组件和Webpack
的代码分割功能,实现路由组件的懒加载。
const login = () => import('../page/login');
注意:若是使用 Babel,须要添加 syntax-dynamic-import 插件
若是想把某个路由下的全部组件都打包在同个异步块 (chunk
) 中。能够经过命名chunk
来实现,以下login
和 index
都被打包到了base
文件中:
const login = () => import(/* webpackChunkName: "base" */ '../page/login'); const index = () => import(/* webpackChunkName: "base" */ '../page/index'); const list = () => import( /* webpackChunkName: "list" */ '../page/list');
第三种:webpack 代码分割
webpack
打包时,会把其对应的文件拆分到一个单独的chunk
中,此chunk
会在须要的时候被异步加载。
//最后一个参数 'login' 能够指定打包出的 chunk 名称 const login = r => require.ensure([], () => r(require('../page/login')), 'login');
🍃 资料:vue项目实现按需加载的3种方式:vue异步组件、es提案的import()、webpack的require.ensure()
举个例子:
const routes = [ { path: '/', redirect: '/index' }, { path: '/login', component: login, name: 'login', meta: { windowTitle: '登陆' } }, { path: '/index', component: index, name: 'index', meta: { windowTitle: '首页' } }, { path: '/list/:id', component: list, name: 'list', meta: { windowTitle: '列表'}, props: true} ]
routes
经常使用配置:
格式:path: string
概述:当前页面的路径
项目中常常会遇到这种状况,好比有一个 产品列表 list 组件,对于全部id
各不相同的产品,都要使用这个组件来渲染,能够经过配置 动态路径参数 来匹配这种路径,例如:path:'/list/:id'
。
格式:component?: Component
概述:路由视图,经过懒加载等方式引入的组件(见 step2 内容)
格式:name?: string
概述:命名路由,可经过 name 名字跳转页面,两边 name 要保持一致,跳转方式如:
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link> //或 router.push({ name: 'user', params: { userId: 123 }})
格式: boolean | Object | Function
概述:组件中使用 $route 会使之与其对应路由造成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。路径上的参数可经过配置props: true
[将组件和路由解耦][27],没必要再经过 $route.params 去访问参数例如:
{ path: '/user/:id', component: User, props: true }, //User - 设置了props:true 以后,route.params 将会被设置为组件属性。 const User = { props: ['id'], template: '<div>User {{ id }}</div>', //template: '<div>User {{ $route.params.id }}</div>' //不须要这样获取值了 }
格式:Array<RouteConfig>
概述:嵌套路由
router
实例,将配置好的路由传入经常使用配置以下:
const router = new VueRouter({ //页面配置(见step3) routes, /** * mode - 模式,默认 hash * hash,地址会变成有 # 号的那种,很丑 * history,无 # 号的正常地址 */ mode: 'history', strict: process.env.NODE_ENV !== "production", //滚动位置 scrollBehavior(to, from, savedPosition) { if (savedPosition) { //savedPosition - 在按下 后退/前进 按钮时,就会像浏览器的原生表现那样 return savedPosition; } else { //返回到顶部 return { x: 0, y: 0 }; } } });
import router from './router' //引入路由 new Vue({ router, //注册 render: h => h(App), }).$mount('#app')
router.js
文件配置
//step1 - 安装并注册`vue-router` import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) //step2: 定义路由组件 const login = r => require.ensure([], () => r(require('../page/login')), 'login'); //登陆 const index = r => require.ensure([], () => r(require('../page/index')), 'index'); //首页 const list = r => require.ensure([], () => r(require('../page/list')), 'list'); //首页 //step3: 配置路由 const routes = [ { path: '/', redirect: '/index' }, { path: '/login', component: login, name: 'login', meta: { windowTitle: '登陆' } }, { path: '/index', component: index, name: 'index', meta: { windowTitle: '首页' } }, { path: '/list/:id', component: list, name: 'list', meta: { windowTitle: '列表'}, props: true }, ] //step4: 建立`router`实例,将配置好的路由传入 const router = new VueRouter({ routes, mode: 'hash', //模式 strict: process.env.NODE_ENV !== "production", //滚动位置 scrollBehavior(to, from, savedPosition) { if (savedPosition) { return savedPosition; } else { return { x: 0, y: 0 }; } } }); //路由守卫 router.beforeEach((to, from, next) => { const token = localStorage.token || ''; const userArr = localStorage.userArr ? JSON.parse(localStorage.userArr) : null; if (to.meta.windowTitle) document.title = to.meta.windowTitle; if (!token && to.name !== 'login') { next({name: 'login', replace: true}); //没有token进入登陆页面 } else if (token && userArr && to.name == 'login') { next({name: 'index', replace: true}); //有token进入登陆页面跳转首页 } else if (to.name != 'login' && !userArr) { next({name: 'login', replace: true}); } else { //TODO 若是没有登陆信息 - 保存登陆信息 // if (!store.state.userArr) { // store.commit('SAVE_USERARR', userArr); // } next(); } }) export default router;
main.js
文件配置
import Vue from 'vue' import App from './App' import router from './router' //引入路由 Vue.config.productionTip = false //step5: 建立并挂载根实例,注入路由 new Vue({ router, render: h => h(App), }).$mount('#app')
🍃 资料1:Vue2.0 探索之路——vue-router入门教程和总结
🍃 资料2:vue-router 一些容易被忽略的知识点
🍃 资料3:关于vue-router的beforeEach无限循环的问题
🍃 资料4:Vue的钩子函数[路由导航守卫、keep-alive、生命周期钩子