10.路由

如何使用路由

要使用路由功能,需要先安装路由模块

npm i vue-router

然后在src目录下,创建一个router文件夹,然后在该文件夹下创建index.js编写以下代码 :

import Vue from 'vue'
import Router from 'vue-router'
import Index from '@/views/index'
import Login from '@/views/login'

Vue.use(Router)

let router = new Router({
    routes : [{
        path : '/index',
        component : Index
    },{
        path : '/login',
        component : Login
    },]
})

export default router;

其中Index组件和Login组件的代码如下 :

<template>
    <div class='index'>
        index
    </div>
</template>
<template>
    <div class='index'>
        login
    </div>
</template>

然后把App.vue代码改成这样 :

<template>
  <div id="app">
    <router-view/>  <!--主要在这里加了一个router-view-->
  </div>
</template>

<script>
export default {
  name: 'App',
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
</style>

router-view是用来显示我们上面的index和login组件的容器

然后打开main.js,增加以下代码 :

import Vue from 'vue'
import App from './App'
import router from './router' //这里!!!

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,  //这里!!!
  components: { App },
  template: '<App/>'
})

完成以上工作后,路由就已经生效了。打开浏览器输入“http://localhost:8080/#/index” 或者 http://localhost:8080/#/login

 

路由跳转

现在我们想从login跳到index,打开login.vue,增加以下代码 :

<template>
    <div class='login'>
        <router-link to="/index">go to index</router-link>
    </div>
</template>

router-link类似于html的a标签,to类似a标签的href。to后面带的是路由的path。

除了使用router-link来跳转外,vue还提供了下面3种方式来跳转路由,分别是 :

this.$router.push 
跳转到指定url路径,并想history栈中添加一个记录,点击后退会返回到上一个页面

this.$router.replace 
跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面)

this.$router.go(n) 
向前或者向后跳转n个页面,n可为正整数或负整数

this.$router.push例子

<template>
    <div class='login'>
        <p @click="gotoIndex">go to index</p>
    </div>
</template>

<script>
export default {
    methods : {
        gotoIndex(){
            this.$router.push({
                path : '/index'
            });
        }
    }
}
</script>

运行效果 :

注意看左上角,我们是可以返回上一页的。

 

this.$router.replace例子

<template>
    <div class='login'>
        <p @click="gotoIndex">go to index</p>
    </div>
</template>

<script>
export default {
    methods : {
        gotoIndex(){
            this.$router.replace({
                path : '/index'
            });
        }
    }
}
</script>

运行效果 :

???

注意看左上角,我们不可以返回上一页

 

this.$router.go例子

<template>
    <div class='login'>
        <p @click="gotoIndex">go to index</p>
    </div>
</template>

<script>
export default {
    methods : {
        gotoIndex(){
            this.$router.push({
                path : '/index'
            });
            setTimeout(()=>{
                this.$router.go(-1);
            },2000);
        }
    }
}
</script>

运行效果 :

该函数的作用就是类似于我们手动的点击浏览器上的前进或者返回。(负数返回,正数前进)

 

跳转路由的时候传参

传参

<template>
    <div class='login'>
        <p @click="gotoIndex">go to index</p>
    </div>
</template>

<script>
export default {
    methods : {
        gotoIndex(){
            this.$router.push({
                path : '/index',
                query : {
                    name : 'tom',
                    age : 18
                }
            });
        }
    }
}
</script>

获取传过来的参数

<template>
    <div class='index'>
        index
    </div>
</template>
<script>
export default {
    mounted(){
        alert( `name=${this.$route.query.name},age=${this.$route.query.age}` );
    }
}
</script>

需要注意的是,这是是 this.$route,不是this.$router。没有r

 

路由懒加载

实际上我们这里这样写,即使我们一开始没有访问Index路由,但是Index组件还是被解析了。若一个项目中有很多组件,则一开始的加载速度则会大大减低。正常情况下是,我们访问到这个路由,才去加载这个路由对应的组件。

解决方案 :

import Vue from 'vue'
import Router from 'vue-router'
const Index = ()=>import("@/views/index"); //懒加载
const Login = ()=>import("@/views/login"); //懒加载

Vue.use(Router)

let router = new Router({
    routes : [{
        path : '/index',
        component : Index
    },{
        path : '/login',
        component : Login
    },]
})

export default router;

 

scrollBehavior

当从B页面跳到A页面,如果此时B页面已经被用户滑动到底部,然后点击某个按钮跳到A页面,此时的A页面也是在底部。

如下图 :

解决方案 :

 

mode

router有两种模式:hash模式(默认)、history模式(需配置mode: 'history')

在浏览器上输入http://localhost:8080/访问该项目,地址栏上的地址突然变成http://localhost:8080/#/login,很丑。如果要改成http://localhost:8080/login这种模式,则只需要在

即可。此时在访问项目,是没问题的。但是如果把项目打包出来然后放到服务器上运行,你会发现运行项目时,一片空白。这是因为服务器匹配不到路由是什么玩意(因为此时的静态文件只有一个index.html,并没有什么/login、/index)

解决的方法是修改服务器的代码,这里以node.js为例 :

const http = require('http');
const fs = require('fs');
const path = require('path');
const url = require('url');

const httpPort = 3000; //端口号
const staticPath = './www'; //项目的存储目录

//获取文件类型,用以写入文件头
function getFileMime(suffix) {
    return new Promise((resolve, reject)=>{
        fs.readFile('./data/mime.json', (err, data)=>{
            if(err){
                reject(err);
            }else{
                resolve( JSON.parse(data.toString())[suffix] );
            }
        }); 
    });
} 

http.createServer((req, res) => {

    let urlPath = url.parse(req.url).pathname;
    //路径中包含/static/css、/static/js、/static/img的,则是资源文件
    if (urlPath.startsWith('/static/css') || urlPath.startsWith('/static/js') || urlPath.startsWith('/static/img')) {
        fs.readFile(staticPath + urlPath, async(err, data) => {
            if (err) {
                console.log(err);
            }
            let type = await getFileMime(path.extname(urlPath));
            res.writeHead(200, {'Content-Type': type + ';charset="utf-8"'}); 
            res.end(data);
        })
    }
    //否则是其它路径,则全部读取index.html
    else {
        fs.readFile(staticPath + '/index.html', 'utf-8', (err, content) => {
            if (err) {
                res.end(404);
                console.log(err);
            }
            res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
            res.end(content)
        })
    }

}).listen(httpPort, () => {
    console.log('Server listening on: http://localhost:%s', httpPort);
})

/static/css、/static/js、/static/img这里指的是vue打包后的文件夹名字。我的是这样的 :

运行效果 :

这个例子的下载地址 :https://download.csdn.net/download/QQ408896436/12659140

该方法有bug,如果路由是动态路由,则会报错。本以为是我代码上有问题,所以我用express + connect-history-api-fallback 的方法来测试,也是一样,会报错。知道的大大麻烦告知一下,3Q

 

动态路由

比如有一个路由,他的路径是这样的 :http://localhost:8080/news/4bcvb,后面的4bcvb可以是任意的数字。

import Vue from 'vue'
import Router from 'vue-router'

const Index = ()=>import("@/views/index"); //懒加载
const Login = ()=>import("@/views/login"); //懒加载
const New = ()=>import("@/views/news"); //懒加载

Vue.use(Router)

let router = new Router({
    mode : 'history',
    scrollBehavior: () => ({ y: 0 }),
    routes : [{
        path : '/index',
        component : Index
    },{
        path : '/login',
        component : Login
    },{
        path : '/news/:id',  //这里!!!
        component : New
    },]
})

export default router;

如果要获取这个参数,则 :

this.$route.params.id

这里的id必须和path : '/news/:id'这里的id是同一个名称, 跳转的时候这样写 :

this.$router.push({
   path : /news/' + id,
})

 

路由重定向

现在我们在浏览器上输入http://localhost:8080/,则页面是空白的。因为我们设置路由的path只有3个,分别是 :

解决方案 :设置一个默认的path,当上面的路由都匹配不到的时候,默认显示这页

import Vue from 'vue'
import Router from 'vue-router'

const Index = ()=>import("@/views/index"); //懒加载
const Login = ()=>import("@/views/login"); //懒加载
const New = ()=>import("@/views/news"); //懒加载

Vue.use(Router)

let router = new Router({
    mode : 'history',
    scrollBehavior: () => ({ y: 0 }),
    routes : [{
        path : '/index',
        component : Index
    },{
        path : '/login',
        component : Login
    },{
        path : '/news/:id', 
        component : New
    },{
        path: '*', //这里!!!
        redirect: '/login'  //这里!!!
      }]
})

export default router;

 

子路由

比如有一个"个人中心"的页面,个人中心的页面中有2个子页面 :"我的收藏"、"我的足迹"。这时候就可以使用子路由

import Vue from 'vue'
import Router from 'vue-router'

const Index = ()=>import("@/views/index"); 
const Login = ()=>import("@/views/login"); 
const New = ()=>import("@/views/news"); 
const My = ()=>import("@/views/my/"); //父组件
const Collection = ()=>import("@/views/my/component/collection"); //子组件
const History = ()=>import("@/views/my/component/history"); //子组件

Vue.use(Router)

let router = new Router({
    mode : 'history',
    scrollBehavior: () => ({ y: 0 }),
    routes : [{
        path : '/index',
        name : 'index',
        component : Index
    },{
        path : '/login',
        name : 'login',
        component : Login
    },{
        path : '/news/:id', 
        name : 'news',
        component : New
    },{
        path : '/my',  //这里!!!
        name : 'my',
        component : My,
        children : [{
            path : 'collection',
            name : 'collection',
            component : Collection
        },{
            path : 'history',
            name : 'history',
            component : History
        }]
    },{
        path: '*',
        redirect: '/login' 
      }]
})

export default router;

然后在my的路由下,使用children属性来定义子路由。然后在my组件下定义一个 <router-view/>;来显示子路由的内容。如下 :

<template>
    <div class='my'>
        <div class='nav'>
            <ul>
                <li @click="$router.push({name : 'collection'})">collection</li>
                <li @click="$router.push({name : 'history'})">history</li>
            </ul>
        </div>
       <router-view/> <!--这里-->
    </div>
</template>
<script>
export default {

}
</script>
<style scoped>
    .nav{
        overflow: hidden;
    }
    li{
        float: left;
        list-style-type: none;
        width: 50%;
    }
</style>

运行效果 :

 

通过name来跳转路由

如果一个path的路径太长,比如上面说的嵌套路由。跳转的时候需要写一大串的路径不太方便。这时候可以通过name来跳转路由。

给每个路由添加一个name属性,跳转路由的时候:

this.$router.push({
    name : 'index', //这里
    query : {
        name : 'tom',
        age : 18
    }
});

 

全局守卫和局部守卫

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值