vue-router
vue中会使用官方提供的vue-router插件来使用单页面,原理就是通过检测地址栏变化后将对应的路由组件进行切换(卸载和安装)
简单路由实现
1.若在vue-cli脚手架中没有安装vue-router,则可以通过以下命令的一种进行安装
cnpm install vue-router -S
yarn add vue-router -S
npm install vue-router -S
2.安装好之后,就可以进行使用
先引入vue-router,如果是在脚手架中,引入vue-router之后,需要用过Vue.use来注册使用插件router/index.js文件
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
3.创建router路由
new Router({
routes:[
{path:'/home',component:Home}//Home是你引入的组件的名称,home是请求的路由地址
]
})
4.创建路由表并配置在路由器中
var routes = [
{path:'/home',component:Home}//同样的,path为路径,component为路径对应的路由组件
]
var router = new Router({
routes;//若属性名和值相等,则可以进行简写
})
5.在根实例里注入router,目的是为了让所有的组件里都能通过this. r o u t e r 、 t h i s . router、this. router、this.route来使用路由相关功能的api
import router from './router'
new Vue({
el:'#app',
router,//注册一下,让组件可以通过this.$router、this.$route使用路由相关的api属性或方法
template:'<App/>',
components:{App}
})
6.利用router-view来指定路由切换的位置
<router-view></router-view>
<h1>我是组件下面的h1标签</h1>
7.使用router-link来创建切换的工具,会渲染成a标签,添加to属性来设置更改的path信息,且会根据当前路由的变化为a标签台南佳对应的router-link-active/router-link-exact-active(完全匹配成功)类名
<router-link to="/main">main</router-link>
<router-link to="/news">news</router-link>
.rouer-link-active{
color:red;//给选中的选项添加样式
}
8.路由的懒加载
懒加载也叫延迟加载,即在需要的时候进行加载,随用随载。在单页面应用中,如果没有懒加载的应用,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,延时过长,不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以又凶啊的分担首页所承担的加载压力,减少首页加载用时。
非按需加载则会把所有的路由组件块的js包打在一起。当业务包很大的时候建议用路由的按需加载(懒加载)。
按需加载会在页面第一次请求的时候,把相关路由组件块的js添加上;
{
path:'/about',
name:'/about',
component:() => import('@/views/About')//返回一个promise对象,es6的语法,异步组件,路由的懒加载
//component: resolve => require(['@/views/Ciname'],resolve)//es5的写法
// component: () => import(/* webpackChunkName:'ciname' */"@/views/Ciname")//webpack的代码分割,通过注释的方式设置打包的文件名
}
9.多级路由
在创建路由表的时候,可以为每一个路由对象创建children属性,值为数组,在这个里面又可以配置一些路由对象来使用多级路由,注意:一级路由path前加’/‘
const routes = [
{path:'/main,component:AppMain'},
{path:'/news',component:AppNews,children:[
{path:'/news/inside',component:AppNewsInside},
{path:'outside',component:AppNewsOutside}//二级路由简写的时候不加'/'
]}
]
二级路由组件的切换位置依然由router-view来指定(指定在父级路由组件的模板中)
<router-link to="inside">inside</router-link>
<router-link to="inside">inside</router-link>
<router-view></router-view>
10.默认路由和重定向
当我们进入应用,默认像显示某一个路由组件,或者当我们进入某一级路由组件的时候想默认显示其某一个子路由组件,我们可以配置默认路由:
{path:"",component:Main}//当路径为根目录时,指向Main路由组件
当我们需要进入之后进行重定向到其他路由的时候,或者当url与路由表不匹配的时候:
{path:'/',redirect:'/main'}
//...
{path:'*',redirect:'/main'}
11.命名路由
我们可以给路由对象配置name属性,这样的话,我们在跳转的时候直接写name:main就会快速的找到此name属性对应的路由,不需要写大量的urlpath路径了
<router-link
v-for="nav in navs"
:key="nav.id"
:to="{name:nav.name}"
>
{{nav.title}}</router-link>
//router/index.js的配置
var router = new VueRouter({
routes:[
{
path:"XXXX",
component:XXXX,
children:[
{path:"guonei",component:()=>import("@/views/Guonei"),name:"guonei"},
{path:"guoji",component:()=>import("@/views/Guoji"),name:"guoji"}
]
}
]
})
<script>
export default {
data(){
return {
navs:[
{id:1,title:"国内新闻",name:'guonei'},
{id:2,title:"国际新闻",name:'guoji'}
]
}
}
}
</script>
12.动态路由匹配
有的时候我们需要在路由跳转的时候跟上参数,路由传参的参数主要有两种:路由参数、queryString参数
路由参数需要在路由表里设置
{path:'/user/:id',component:User}
上面的代码就是给User路由配置接收id的参数,多个参数继续在后面设置
在组件中可以通过this.$route.params来使用
queryString参数不需要在路由表设置接收,直接设置"?"后面的内容,
在路由组件中通过this.$route.query接收
<div class="nowplaying">
<ul>
<router-link
v-for="data in datalist"
:key="data"
:to="{
name:'detail',
params:{id:data},
query:{title:'文章二'}
}"
tag="li"
>{{data}}</router-link>
</ul>
</div>
<script>
data(){
return {
datalist:["1111","2222","3333"]
}
}
</script>
detail.vue
<script>
export default{
props:['id'],
created(){
//需要获取nowplaying这边传递来的每一个id参数
/detail/:id
// console.log(this.$route.params.id)
console.log(this.id)
console.log(this.$route.query.title)//获取到?后面传递来的动态参数
</script>
router.js
{
name:"detail",
path:"/detail/:id",
component:Detail
}
13.声明式导航router-link
组件支持用户在具有路由功能的应用中(点击)导航。 通过 to 属性指定目标地址,默认渲染成带有超链接的 标签,可以通过配置 tag 属性生成别的标签.。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的 CSS 类名。
router-link的to属性,默认写的是path(路由的路径),可以通过设置一个对象,来匹配更多
:to='{name:"detail",params:{id:_new.id},query:{content:_new.content}}'
name是要跳转的路由的名字,也可以写path来指定路径,但是用path的时候就不能使用params传参,params是传路由参数,query传queryString参数
replace属性可以控制router-link的跳转不被记录
active-class属性可以控制路径切换的时候对应的router-link渲染的dom添加的类名
14.编程式导航
有的时候需要在跳转前进行一些动作,router-link直接跳转,需要在方法里使用$router的方法this.$router.push()
15.路由模式
因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。
所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
路由原理:
hash路由 ====> window.onhashchange监听路径的切换
history路由 ===> window.onpopstate监听路径的切换 (ie9以上版本才能使用)
16.路由守卫(路由拦截,路由钩子)
在某些情况下,当路由跳转前或跳转后、进入、离开某一个路由前、后,需要做某些操作,就可以使用路由钩子来监听路由的变化
全局路由钩子:
//进入到某个路由组件之前
router.beforeEach((to, from, next) => {
//会在任意路由跳转前执行,next一定要记着执行,不然路由不能跳转了
console.log('beforeEach')
console.log(to,from)
next()
})
//进入到某个路由组件之后
router.afterEach((to, from) => {
//会在任意路由跳转后执行
console.log('afterEach')
})
单个路由钩子:
只有beforeEnter,在进入前执行,to参数就是当前路由
routes: [
{
path: '/foo',
component: Foo,
//当进入到foo路由之前,就会触发
beforeEnter: (to, from, next) => {
// ...
next() //必须要执行next之后,对应的Foo组件才可以正常显示出来
}
}
]
路由组件钩子:
//进入到某个组件之前的拦截,获取不到组件内部的this
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
//离开某个组件之前的拦截,获取到组件内部的this
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}