欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue - 路由(vue-router)

程序员文章站 2022-03-25 11:13:41
...

Vue.js

本章内容:

路由

​ 根据不同的路径 (锚点) ,显示不同的页面 (组件) ,不会刷新整个页面,,局部更新。

​ 官方地址: https://router.vuejs.org/zh/

引入vue-router
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
vue-router提供的组件
router-view

​ 路由的出口,用于渲染当前路由模板,在含有导航链接的页面都与要进行路由出口,否则路由不起作用。

<router-link to="/Home">首页</router-link> <!-- 导航链接 -->
<router-view></router-view> <!-- 路由出口 -->
router-link

​ 导航链接

<router-link to="/Home">首页</router-link>
  • 标签属性

    1. to (必选参数)

      <router-link to="/Login">登录</router-link>
      <!-- 表示路由的链接, 该值可以是字符串, 可也动态绑定数据 -->
      
    2. tag

      <router-link to="/Login" tag="strong">登录</router-link>
      <!-- tag表示渲染成指定的标签, 同样还会监听点击, 触发路由链接。默认是<a></a>标签。 -->
      
定义路由
// 创建`router`实例,传入`routes`配置。
let router = new VueRouter({
    routes: [
        {
            path: "/index",
            component: { // 每个路由中`component`的应该映射一个组件。
                template: `<h3>首页</h3>`
            }
        },
        {
            path: "/login",
            component: {
                template: `<h3>登录</h3>`
            }
        }
    ]
})
new Vue({
    el: "#app",
    router // 将`router`挂载Vue实例中。
})
动态路由

例如,我们有一个 login 组件,对于所有 ID 各不相同的用户,可以使用动态路由将用户ID传入。

<div id="app">
    <router-link to="/index">首页</router-link>
    <!-- 传入用户信息 -->
    <router-link to="/login/1/狗蛋/12345678">登录</router-link>
    <router-view/> <!-- 路由出口 -->
</div>

// 创建`router`实例,传入`routes`信息,并定义动态路由。
let router = new VueRouter({
    routes: [
        {
            path: "/index",
            component: {
                template: `<h3>首页</h3>`
            }
        },
        {
            path: "/login/:userID/:userName/:passWord", // 绑定动态路径参数,以:进行绑定某些字段。
            component: {
                template: `<h3>{{$route.params}}</h3>`
            }
        }
    ]
})
new Vue({
    el: "#app",
    router // 挂载路由
})
命名路由

​ 命名路由指的是在每一个路由配置上,都必须提供一个name

const Index = {
    template: "..."
}
let router = new VueRouter({
	routes: [
        {
            name: "index", // 提供当前路由配置上的`name`。
            path: "/index",
            component: Index
        }
    ]
})
$router和$route的区别
  • $router为VueRouter的实例, 是一个全局的路由对象。

  • $route是一个跳转的路由对象, 每一个路由都有route对象, 是一个局部对象, 包含路由路径携带的参数,以及查询字符携带的参数。

    <div id="app">
        <!-- 查询参数 -->
        <router-link to="/index?userID=1&userName=大锤&passWord=1314521">首页</router-link>
        <!-- 动态参数 -->
        <router-link to="/login/33/狗蛋/5211314">登录</router-link>
        <router-view></router-view> <!-- 路由出口 -->
    </div>
    
    
    let router = new VueRouter({
        routes: [
            {
                path: "/index", // 查询参数不需要绑定。
                component: {
                    template: `
                        <div>
                            <h3>登录</h3>
                            <h4>查询参数为:{{$route.query}}</h4>
                        </div>
                    `
                }
            },
            {
                path: "/login/:userID/:userName/:passWord", // 绑定动态路径参数,以:进行绑定某些字段。
                component: {
                    template: `
                        <div>
                            <h3>登录</h3>
                            <h4>动态参数为:{{$route.params}}</h4>
                        </div>
                    `
                }
            }
        ]
    })
    new Vue({
        el: "#app",
        router // 挂载`router`实例
    })
    
嵌套路由

路由套路由,<router-view/>内嵌套另一个<router-view/>组件。

<div id="app">
		<router-link to="/index">首页</router-link>
		<router-link to="/login">登录</router-link>
		<router-view></router-view>		<!-- 路由出口 -->
	</div>

let router = new VueRouter({
    routes: [
        {
            path: "/index",
            component: {
                template: `
                    <div>
                        <h3>首页</h3>
                        <router-link to="/index/child1">一入口</router-link>
                        <router-link to="/index/child2">二入口</router-link>
                        <router-link to="/index/child3">三入口</router-link>
                        <router-view></router-view>
                    </div>
				`
            },
            children: [ // 配置index的子路由。
                {
                    path: "child1",
                    component: {
                        template: `<h3>一入口</h3>`
                    }
                },
                {
                    path: "child2",
                    component: {
                        template: `<h3>二入口</h3>`
                    }
                },
                {
                    path: "child3",
                    component: {
                        template: `<h3>三入口</h3>`
                    }
                }
            ]
        },
        {
            path: "/login",
            component: {
                template: `<h3>登录</h3>`
            }
        }
    ]
})
new Vue({
    el: "#app",
    router: router // 将配置的路由实例挂载Vue实例中。
})
路由重定向

例如我们访问/a路由,重定向规定为/b,则当访问/a就会切换到/b路由。

let router = new VueRouter({
    routes: [
        {
            path: "/", // `/`表示根目录,`*`会匹配任意路由路径。
            redirect: "/index" // 定义重定向,如果是根目录则自动重定向到`redirect`指定的路由。
        },
        {
            path: "/index",
            component: {
                template: "<h3>首页</h3>"
            }
        },
        {
            path: "/login",
            component: {
                template: "<h3>登录</h3>"
            }
        }
    ]
})
编程式的导航

​ 在Vue实例内部,你可以通过$router访问路由实例,因此你可以调用this.$router.push(...)来导航到不同的路由。

​ 或者使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前 的 URL。

routerrouter使router和router功能等效,都可以使用,只不过router是router实例挂载Vue实例之后自动生成的对象。而router是构造函数。

// 实例化router
let router = new VueRouter({
    routes: []
})
new Vue({
    el: "#app",
    methods: {
        routerFn() {
            // $router是`router`实例挂载到Vue中才有的实例对象。
            this.$route.push(...);
            // router实例。 
            router.push(...);
            console.log(router === this.$router); // true,两种效果等效,都可使用。
        }
    },
    router // 挂载`router`实例
})
  • push
    该方法参数可以是一个字符串路径,或者是一个叙述地址的对象。例如:

    // 字符串
    this.$router.push("/index");
    // 对象
    this.$router.push({path: "index"});
    // 命名路由,通过路由内配置的`name`值相互绑定,也可实现路由跳转。
    this.$router.push({name: "index"});
    // params动态路由
    this.$router.push({name: "index", params: {id: 1} }); // -> {id: 1},可以通过$route.params获取。
    // 查询参数,URL变成 /index?id=100
    this.$router.push({name: "index", query: {id: 100} }); // -> {id: 100},可以通过$route.query获取。
    

    如果提供了pathparams就会被忽略,而query不会被忽略。你可以提供路由的name或手写完整的带有参数的path

    const Id = '123';
    // 提供了name,有效。
    this.$router.push({name: "index", params: {Id} }); // -> /user/123
    // 提供完整的`path`。
    this.$router.push({ path: `/user/${Id}` }) // -> /user/123
    // 这里的params不生效。
    this.$router.push({path: "index", params: {Id} });
    
  • go
    这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)

    // 在浏览器记录中前进一步,等同于 history.forward()。
    this.$router.go(1);
    // 后退一步记录,等同于 history.back()。
    this.$router.go(-1);
    // 前进 3 步记录
    this.$router.go(3);
    // 如果 history 记录不够用,那就默默地失败呗
    this.$router.go(-100);
    this.$router.go(100);
    
过渡动效

<router-view/>是动态组件,所以我们可以使用<transition/>组件给它添加一些过渡效果。

<transition name="fade">
	<router-view></router-view>
</transition>
单个路由的过渡

上面语法是给所有出口都进行了相同的过渡,如果想给每个路由模板添加各自的效果,可以在<transition/>上定义不同的name

const Bar = {
    template: `
			<transition name="fade">
				<div>...</div>
			</transition>
	`
}
const Foo = {
    template: `
			<transition name="slide">
				<div>...</div>
			</transition>
	`
}
导航守卫

vue-router 提供的导航守卫主要用来通过跳转或阻止跳转的方式守卫导航。记住参数或查询的改变并不会触发进入/离开的导航守卫

全局前置守卫

​ 使用router.beforeEach来注册一个全局前置守卫。

let router = new VueRouter({
    routes: [
        // ...
    ]
})
router.beforeEach((to, from, next) => {
    // ...
})

​ 同样也可以在vue中挂载的路由实例进行注册导航守卫。

let router = new VueRouter({
    routes: [
        // ...
    ]
})
new Vue({
    el: "#app",
    router,    // ES6语法,与router: router等效
    mounted() {
        // 通过路由实例注册
        this.$router.beforeEach((to, from, next) => {
            // ...
        })
    }
})
  • 每个守卫方法接受三个参数:

    • to
      即将要进入的目标路由。

    • from
      即将要离开的当前路由。

    • next
      用于允许路由的切换,在路由切换中必须调用next(), 否则钩子就不会被调用。

      router.beforeEach((to, from, next) => {
          next(); // 进行管道中的下一个钩子
          next(false); // 中断当前的导航
          next({path: "/login"}) // 链接到指定的路由,与`next("/login")`等效
      })
      
全局后置守卫

​ 使用router.afterEach来注册一个全局后置守卫,但是它不接收next参数。

router.afterEach((to, from) => {
    // ...
})
前置守卫与后置守卫的区别
  1. 前置守卫在进入前触发,后置守卫进入后触发。
  2. 前置守卫接受next回调,后置守卫不接受next回调
路由独享守卫

​ 在路由配置上直接定义beforeEnter守卫

let router = new VueRouter({
    routes: [
        {
            path: "/index",
            component: Index,
            beforeEnter(to, from, next) {
                // ...
            }
        }
    ]
})
组件内部守卫

​ 在路由组件内直接定义以下路由导航守卫 :

const Foo = {
    template: `...`,
    beforeRouteEnter (to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
    },
    beforeRouteUpdate (to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
    },
    beforeRouteLeave (to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
    }
}