const path = require('path');
const BASE_URL = process.env.NODE_ENV === 'production' ? './' : '/';
const resolve = dir => path.join(__dirname,dir);
module.exports = {
lintOnSave: false,
publicPath : BASE_URL,
chainWebpack : config => {
config.resolve.alias
.set('@',resolve('src')) // 配置:用 @ 符号来代替 src 的根目录
.set('_s',resolve('src/assets/style'))
},
//打包时不生成 .map 文件 减小打包体积 缩短打包时间
productionSourceMap : false,
devServer : {
proxy : 'http://localhost:4000'
}
}
上述为配置:后面所有例子都以该配置为主
一般项目中会把路由文件分为两个部分: 1.配置路由列表文件 2. 创建路由实例文件(需引入vue-router插件)
// 配置路由列表 import Home from '@/views/Home.vue' export default [ { path: '/', //path 指代路径 component: Home }, { path: '/about',// route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ '@/views/About.vue') }, { path : '/argu/:name', component : () => import('@/views/argu.vue') } ]
//上面例子概述了两种组件的引入方式 : 第一种 Home 的引入方式 将组件以变量的形式引入 第二种直接在 component 中引入
// 创建路由实例 import Vue from 'vue' import Router from 'vue-router' // 插件 import routes from './router' //引入路由列表文件 Vue.use(Router) export default new Router({ routes })
实例化一个vue:
import Vue from 'vue' import App from './App.vue' //引入App组件 赋值给App import router from './router' //引入创建路由实例文件 赋值给变量 router import store from './store' Vue.config.productionTip = false new Vue({ router, render: h => h(App) }).$mount('#app') //app为vue渲染的元素
//App.vue组件 <template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | //router-link封装了一个 a 标签 to指定的值是路径 也就是路由列表中的 path <router-link :to="{name : 'about'}">About</router-link> </div> <router-view/> //视图渲染组件通过 router-link 加载的组件都会在这边渲染 </div> </template>
动态路由匹配:
//在配置路由列表中 { path : '/argu/:name', component : () => import('@/views/argu.vue') //引入 argue 组件 },
//argue组件 <template> <!--$route表示当前加载页面的路由对象 params是参数 name是值--> <div>{{$route.params.name}}</div> </template> <script> export default { // } </script>
嵌套路由:
//在配置路由列表中 { path : '/parent', component : () => import('@/views/parent.vue'), children : [ //嵌套子组件 { path : 'child',//子组件路径不需要加 '/' component : () => import('@/views/child.vue') } ] }
<!-父组件--> <template> <div> I am parent <router-view/> </div> </template> <script> export default { // name: "parent" } </script>
<!--子组件--> <template> <div>I am child</div> </template> <script> export default { // name: "child" } </script>
命名路由 :
<!--命名路由 name值与路由列表中的name值对应--> <router-link :to="{name : 'about'}">About</router-link>
//在配置路由列表中配置(router.js) { path: '/about', name: 'about', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ '@/views/About.vue') }
命名视图:(同一个页面上显示多个视图)
<router-view/> <!--命名视图--> <router-view name="email"/> <router-view name="tel"/>
{ path: '/name_view', components:{ default: () => import('@/views/child.vue'), email: () => import('@/views/email.vue'), tel: () => import('@/views/tel.vue'), } }
注意:路由列表中组件的优先级是由上而下的,上面的优先级较高
前置守卫:
// 创建路由实例 import Vue from 'vue' import Router from 'vue-router' // 插件 import routes from './router' //引入路由列表文件 Vue.use(Router) const router = new Router({ mode : 'history',//默认hash模式 routes }) //实例化一个登录页面 const HAS_LOGINED = true // 做一个简单的判断 是否登录 //注册一个全局前置守卫 //to 即将跳转页面的路由对象 from当前操作的路由对象 next时一个函数 router.beforeEach((to,from,next) => { if(to.name !== 'login'){//如果即将跳转的页面不是登录页面 //判断是否登录 如果已经登录直接执行 next() 跳转 if(HAS_LOGINED) next() //如果没有登录直接执行 next() 跳转到 login 页面 else next({name : 'login'}) }else{ if(HAS_LOGINED) next({name : 'home'}) else next() } }) export default router
//在配置路由列表中配置(router.js) { path : '/login', name : 'login', component: () => import(/* webpackChunkName: "about" */ '@/views/login.vue') },
//login.vue文件 <template> <div>login-page</div> </template> <script> export default { name: "login" } </script>
组件独享守卫:
{ path: '/', name: 'home', component: Home, //to 即将跳转页面的路由对象 from当前操作的路由对象 next时一个函数 beforeEnter : (to,from,next) => { if(from.name === 'about') alert('这是由about页面跳转来的') else alert('这不是由about页面跳转来的') next() } }
在组件内使用守卫:
<template> <div class="home"> <img alt="Vue logo" src="@/assets/image/logo.png"> <HelloWorld msg="Welcome to Your Vue.js App"/> <button @click="hendleClick">返回上一页</button> </div> </template> <script> // @ is an alias to /src import HelloWorld from '@/components/HelloWorld.vue' export default { name: 'home', components: { HelloWorld }, beforeRouteEnter(to,from,next){ alert(to.name + from.name) next() }, //多用在文本编辑 beforeRouteLeave(to,from,next){ const leave = confirm('您确定要离开吗') if(leave) next() else next(false) }, methods: { hendleClick: function () { this.$router.back() } } } </script>
完整的导航解析流程:
1. 导航被触发
2. 在失活的组件(即将离开的组件)里调用离开守卫 beforeRouteLeave
3.调用全局的前置守卫 beforeEach
4.在重用的组件里调用 beforeRouteUpdate
5.调用路由独享的守卫 beforeEnter
6.解析异步路由组件
7.在被激活的组件(即将进入的组件)里调用 beforeRouteEnter
8.调用全局的解析守卫
9. 导航被确认
10. 调用全局的后置守卫
11.触发DOM更新