vue - 路由(vue-router)

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`
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章