Vue-router的使用姿式

虽然有不少router的相关文章了,可是那又怎么样,我就是要写。javascript

欢迎来个人Vue技术群交流:Vue887516034css

其实vuejs有一个叫作动态组件的东西,效果和路由有点类似,根据需求显示不一样的组件,可是在实际使用上,很小气,就给人玩不爽,没办法像路由同样编程式导航(push,replace),也没有浏览器路径的语义引导,动态组件更适合小规模的局部tab,给你们秀一波用法html

<template>
    <div>
        ul>li>tab1+tab2     @click=""  <!-- >>>此处改变下面data中的tab值就能够切换了 -->
        <!-- 此处至关于router-link效果,虽然没有浏览器的url引导,可是能够本身写面包屑 -->
        <component :is="tab"></component>  <!-- 这里就是router-view显示区了 -->
    </div>
</template>

<script> import tab1 from 'path/to/tab1.vue' //相比vue-router要引入不少文件 麻烦 import tab2 from 'path/to/tab2.vue' //其实vue-router也引入文件,可是在.vue文件里面引入那么多就很难看 export default { data(){ tab:'tab1' //默认显示tab1 }, components:{ tab1, tab2 //es6语法 对象中,键值相同能够这样写 } } </script>
复制代码

咱们不提动态组件了,开始router了。经常使用的api,官网介绍的很详细了。记得看官方教程,别忘了官方的apivue

路由的配置

不论是什么路由的配置 仍是vuex的配置等等,都有相应的规范,在普通js文件,不按规范也不会怎么样,在ts文件,就会报错了。前提是有兴趣玩ts。java

// router/index.js
// 此处省略一堆 import
const router = new Router({
    base:'/',
    mode:'history',//default-->hash
    routes:[],
    scrollBehavior:()=>{
        return {x:0,y:0}
    }
})
复制代码

其实配置很简单,就这么一点。webpack

base

浏览器url的前缀,默认为'/',若是设置为'/some/',则运行项目,浏览器url都是'/some/...',不会对静态文件的引用产生影响,通常写网站都会有域名,均可以把域名指向某个服务器目录,因此默认'/'便可,若是是写公司内部后台管理,那么不必定会用域名,可能就是某个ip下的某个目录,好比打包后的文件在111.22.33.44/admin,这个时候路由的配置匹配浏览器路径的时候,会从这个/admin开始算,若是base仍是默认的/,那么路由配置的routespath就要所有加上/admin/前缀,而且router-linkpush方法也要加上这个/admin,很麻烦,可是只要设置base'/admin/',路由内部配置以及全部相关的方法均可以忽视服务器ip下的目录名。这种状况,一样也要配置webpackpublicPath也为/admin/,这里不细说了。nginx

mode

这个太简单了,一共三种模式,es6

hash:浏览器会有‘#’符号,参考锚点效果,缺点很丑,可是兼容性棒棒web

history:去除‘#’符号,让url变好看,下面会讲服务端配置。ajax

abstract:非浏览器环境,会强制使用这个模式,例如weex

history模式服务端配置

我我的和公司都是用nginx,这里就讲nginx,配置这个的缘由是当你进入某个路由以后,再次刷新页面时(或者是浏览器直接输入某个路由路径时),当刷新页面,浏览器就会从新dns解析,tcp协议,这个时候会根据浏览器的url去服务器找对应资源,固然咱们vue-router是为单页面服务的,对应的url在服务端是确定没有静态资源的,就会出现404,当配置了如下url重写语句,注意是重写,不是重定向,不改变url的状况重写浏览器内容,重写到index.html,由于这个index.html使咱们项目的入口,index.html里面会读取当时打包好的app.js,就能够读取到路由配置,以实现咱们浏览器的url对应的路由页面。

hash模式不须要配置,由于浏览器会忽略#和?后面的参数

打包文件在根目录时,

location / { 
  try_files $uri $uri/ /index.html;
}
复制代码

打包文件在非根目录时,

location /admin {
  try_files $uri $uri/ /admin/index.html;
}
复制代码

routes

核心路由配置,官网讲的很详细,我就讲几个注意点,全部自定义的配置,例如是否须要鉴权或者对应的icon等,须要规范化的话都写在meta对象中, 不规范的话 ,就和path同级咯,随意玩,玩坏了我不背锅。

path是必须指定的,name须要惟一,不是必须。

routes的配置遵循顺序匹配,当url成功匹配,就不会再往下匹配,因此像403,404的页面应当写在最后。

alias别名的使用,当须要在指定router-view显示某个组件,而且但愿浏览器url是本身想要的语义时使用

redirect重定向,参数能够是路径,也能够是对象(重定向到某个name),注意重定向是改变内容+改变url

scrollBehavior

这个滚动行为,老实说,感受很蹩脚,本人基本没有使用过,他控制的是body的滚动, 不少需求都是局部滚动。若是的确是须要控制body滚动,参考官方文档便可。

路由的使用

路由的配置一开始只有根目录/,每写一层children就要写一层router-view,不然组件不显示。每个嵌套children的层级和router-view的层级都是一一对应的。

// router/index.js
const router = new Router({
    routes:[
        {
            path:'/',   //此时配置数组的第一层级,即对应app.vue中的router-view
            component:Home,// <<<----------------------------
            children:[// |
                {   // |
                    //此时第一层级出现children第二层级,------------
                    //那么在这个第二层级所属的第一层级 Home组件中,就要写一层router-view,以此类推
                    path:'user', 
                    component:User,
                }
            ]
        }
    ]
})
复制代码

路由配置生成menu菜单

menu其实就是路由的导航,就是router-link,有不少小伙伴会另外建一个叫作menu.js的文件,而后模拟路由配置的结构去写一个数组,而后根据这个文件遍历生成dom,是否是有画蛇添足的感受,而且当使用第三方的menu的ui组件时,这种静态文件是没有状态 (当前访问路由的对应menu高亮,刷新页面或者输入路由的url进入页面会丢失高亮) 的。

menu有不少种状况,

  1. 固定层级,好比固定2层,或者3层,通常后台管理系统,固定层级较多,由于美观,整洁。这种就比较方便了。template的dom结构也比较方便。
  2. “个性”的产品经理,“定制化”的menu菜单,未知的层级,这里就要用到render函数去写dom。

固定层级

<template>
    <div class="menu">
        <div class="first-menu" v-for="item,index in menus" :key="item.name">
            <router-link :to="item.name">{{ item.meta.zhName }}</router-link>
            <template v-if="item.children.length">
                <div class="sub-menu" v-for="subItem.subIndex in item.children" :key="subItem.name">
                    <img :src="subItem.meta.icon" />
                    <router-link :to="subItem.name">
                    {{subItem.meta.zhName}}
                    </router-link>
                </div>
            </template>
        </div>
    </div>
</template>
<script> export default { computed:{ menus(){ return this.$router.options.routes //获取路由配置 } } } </script>
<style> .router-link-active{ /* 激活样式 */ } </style>
复制代码

这里我只写了2层,而且没有写样式,若是使用了像element-ui这样的menu组件,他底层没有渲染成router-link,那就要编程式导航了,click的时候,pushitem.name,而且当前路由的导航样式须要根据$route.name(当前路由配置)来判断

未知层级

由于不知道是几层菜单,因此在template的html标签没办法自由的遍历,因此须要js去操做路由配置的递归,由于render函数式js操做,因此须要用render函数渲染。

<script> export default { computed:{ menus(){ return this.$router.options.routes //获取路由配置 } }, // 使用render函数就不须要写template标签的dom了 render(h){ //这个 h 参数,原来的语义是createElement ,这里使用 h 是方便操做,也是官方建议 // ...... 这里是操做 menus 的递归代码,再经过render函数循环出来 return h('div','这是一个div') //这里必须return 对应的语法 } } </script>
复制代码

render函数的语法参见官方文档便可 render函数

这里有个注意点,若是router作了权限控制,那么路由配置不能经过$router.options.routes获取,由于addRoutes方法不改变原先的配置,须要在addRoutes的同时,把完整的路由配置保存在vuex,再获取。权限控制不细讲了,有不少相关文章,可是不建议copy,建议加入本身的理解,没有绝对的方案。

路由的缓存和过渡动画

过渡动画应该都用了,通常使用opacity过渡一下。

<template>
    <transition mode="out-in" name="fade">
        <!-- 这里若是在行内直接用$route.meta去v-if判断缓存 dom结构会变复杂 -->
        <keep-alive :include="aliveRoutes">
            <router-view :key="$route.fullPath" />
            <!-- 此处经过路由的完整路径加上key,当为动态路由时,触发路由组件从新渲染 -->
        </keep-alive>
    </transition>
    <!-- 都是些官方用法 不细说了-->
</template>
<script> export default { computed:{ aliveRoutes(){ // this.$router.options.routes 获取路由配置 //能够配置meta 是否缓存 根据 meta 字段 push到数组里 return [/* ... */] } } } </script>
复制代码

路由的钩子

官网讲的超详细的。触发顺序也讲清楚了,官方的说法叫导航守卫

注意点:要搞清楚哪些是全局钩子,哪些是组件内的钩子。而且全部的前置钩子,须要调用next() 才会正常进入路由,在写钩子函数内部逻辑时,须要注意,不能造成死循环

例如

router.beforeEach((to,from,next)=>{
    if (from.name === 'login'){
        next({
            name:'login'  //死循环
        })
        //更多next回调方法能够查看官方文档
    }
})
复制代码

组件内钩子使用状况,要看业务需求,好比动态路由↓↓↓。

动态路由

动态路由,使用场景是一个固定的路由视图组件,配合一个动态的浏览器url,在视图中显示不一样的数据,同时但愿url中有当前详情的语义,例如详情页,用户信息页。

先看下路由如何配置动态,这里用详情页举例

// router/index.js
const router = new Router({
    routes:[
        {
            path:'/list',
            name:'list',
            component:List
        },
        {
            path:'/detail/:id',//此处id对应params.id
            name:'detail',
            component:Detail
        }
    ]
})
复制代码
<!-- List.vue -->
<template>
    <div>
        <ul>
            <li @click="goDetail(item.id)" v-for="item in someData" :key="item.id">
            </li>
        </ul>
    </div>
</template>

<script> export default{ methods:{ goDetail(_id){ this.$router.push({ name:'detail', //此处注意只有经过name跳转路由,params才会生效 //query不受影响 params:{ id:_id //此处对应routes配置的/:id } }) } } } </script>
复制代码
<!-- Detail.vue -->

<script> export default { beforeRouteEnter (to, from, next) { //此处为路由组件内的钩子,能够经过判断 to.params.id 是否 undefined, //进行一些操做,由于即便 to.params.id 是 undefined,路由也能匹配成功 //由于这些id多是用来获取数据的,不会在页面显示,不必定能察觉是 undefined } } </script>
复制代码

关于路由传参

  1. params就如上面动态路由所讲,只有经过路由配置的name跳转,才会生效,即便没有使用动态路由,也能够经过params传参

这里有注意点:

  • 若是使用动态路由,那么在动态路由页面刷新路由,params参数依然存在,

  • 若是没有使用动态路由,params参数只在跳转路由时有效,刷新页面则会丢失params

  1. query参数,能够经过pathname跳转均可以传参,而且参数会和ajaxget请求同样,附加到浏览器的url上,刷新页面依然保留

路由的懒加载

路由组件打包单独的js,当访问路由时,加载对应js文件,加快首页加载时间,会增长项目的整体积。

  1. npmyarn安装babel-plugin-syntax-dynamic-import
  2. .babelrcbabel.config.js配置
module.exports = {
    plugins:["syntax-dynamic-import"]
}
复制代码
  1. 路由文件使用
// router/index.js
const router = new Router({
    routes:[
        {
            path:'/list',
            name:'list',
            component:()=>import(/* webpackChunkName:"SOME_NAME" */'path/to/List.vue')
            //此处 import 是方法 和 es6 的 import 不同
            //特殊注释语法 相同chunkName 打包到一个js中 可省略
        }
    ]
})
复制代码

路由的命名视图

我历来没用到过命名视图,不给你们误导了,我能解释的就是命名视图的做用是一个浏览器url,匹配多个router-view。有需求的移步官方文档。

部分api

  1. .vue文件中this.$router是指挂载的路由实例,可使用push等方法。
  2. .vue文件中this.$route当前路由信息对象,包括pathquery等,只读属性。
  3. router.approuter所挂载的vue实例,能够经过router.app.$options.store访问vuex,前提是main.js中,要先引入vuex,后引入router,不然报错。
  4. router.push()经常使用路由跳转方法,参数为{path?:string,name?:string,params?:object,query?:object},须要注意的是,push为方法名,与数组没有联系。
  5. router.replace()替换当前路由,参数和push一致,区别是替换当前路由,即点击浏览器的返回,不会回到以前被替换的路由。
  6. router.go()router.back(),参数为整数,前进或后退几步。
  7. router.addRoutes()参数是须要符合routes配置的数据,动态添加路由配置到原有配置。

结束

有疑问或者讲错的能够提出

tips:懂得分享才能走的更远。

欢迎来个人Vue技术群交流:Vue887516034

若是以为对你有用,就打赏一下吧。

相关文章
相关标签/搜索