合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
# 路由 ## 介绍 Vue路由是vue.js的专业路由工具。它与Vue核心深度集成可以轻而易举的使用vue.js创建单页面应用(SPA)。功能包括: * 路由嵌套映射 * 动态路由 * 模块化,基于组件的路由配置 * 路由参数,查询,通配符支持 * 基于vue.js过渡系统的视图过渡效果 * 精细导航控制 * 自动激活链接CSS样式 * html5历史模式或哈稀模式 * 自定义滚动行为 * URL编码 ## 安装 ### **直接下载或CDN** [https://unpkg.com/vue-router@4](https://unpkg.com/vue-router@4) [Unpkg.com](https://unpkg.com/)提供基于CDM的链接。上面的链接指向一个最新版本的NPM。你也可以通过`https://unpkg.com/vue-router@4.0.5/dist/vue-router.global.js`查询特定的版本/标签。 ### **NPM** ~~~ npm install vue-router@4 ~~~ ### **yarn** ~~~ yarn add vue-router@4 ~~~ ## 必备基础(Essentials) ### **开始** 使用Vue + Vue路由创建一个单页面应用(SPA)是一个很自然的事情:使用vue.js我们已经准备好了使用组件构成应用。当把Vue路由融合进来以后,所有需要我们做的就是将组件映射到路由和让Vue路由知道在何处渲染他们。下面是一个基础示例: * **HTML** ~~~html <!DOCTYPE html> <html lang="en-US"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>router-basic</title> <script src="https://unpkg.com/vue@next"></script> <script src="https://unpkg.com/vue-router@4"></script> </head> <body> <div id="app"> <h1>你好,路由!</h1> <p> <!--使用router-link组件进行导航--> <!--通过to属性来指定链接地址--> <!--最终`router-link`会被渲染为有正确`href`的`a`标签--> <router-link to="/">首页</router-link> <router-link to="/about">关于我们</router-link> </p> <!--路由出路--> <!--根据链接导航的地址会渲染到这里--> <router-view></router-view> </div> <script type="text/javascript"> //1. 先定义组件,这些可以从独立文件中import进来 const Home = {template: '<div>这是首页</div>'} const About = {template: '<div>这是关于我们</div>'} //2. 定义路由变量 // 每一条路由需要映射到一个组件 // 后面会说到路由嵌套 const routes = [ {path: '/',component: Home}, {path: '/about', component: About} ] //3. 传入 routes创建路由实例 // 先尽量简洁,后面还可以传入其他的选项 const router = VueRouter.createRouter({ //4. use需要提供历史实现。这里使用简单路由模式。 history:VueRouter.createWebHashHistory(), routes // routes:routes的简写 }) // app实例 const app = Vue.createApp({}) // 确保_use_路由实例,引入全局路由中间件 app.use(router) app.mount("#app") </script> </body> </html> ~~~ <iframe height="265" style="width: 100%;" scrolling="no" title="vue-router-basic" src="https://codepen.io/zhouyu629/embed/vYgOXNV?height=265&theme-id=dark&default-tab=js,result" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href='https://codepen.io/zhouyu629/pen/vYgOXNV'>vue-router-basic</a> by zhou (<a href='https://codepen.io/zhouyu629'>@zhouyu629</a>) on <a href='https://codepen.io'>CodePen</a>. </iframe> 调用 `app.use(router)`,我们可以像任何组件中通过`this.$route`访问当前路由一样通过`this.$router`访问它。 * **JavaScript** ~~~ // Home.vue export default { computed: { username() { // We will see what `params` is shortly return this.$route.params.username }, }, methods: { goToDashboard() { if (isAuthenticated) { this.$router.push('/dashboard') } else { this.$router.push('/login') } }, }, } ~~~ 在`setup`函数中访问路由,调用`useRouter`或`useRoute`函数。学习[组合API](https://next.router.vuejs.org/guide/advanced/composition-api.html#accessing-the-router-and-current-route-inside-setup)了解更多 <br /> 整个文档中,我们将会经常` use router`实例。记住`this.$router`实际上同通过`createRouter`直接创建的`router`实例一样。我们使用`this.$router`是因为我们不需要在每个独立组件中都管理路由。 ### **动态路由匹配** 我们会经常将路由映射到给定样式的同一组件。例如我们有一个`user`的组件,所有用户都会使用这个组件做展示,但根据userId不同展示的内容可能不同。Vue的路由可以动态的传递参数来实现: ~~~ const User = { template: '<div>User</div>', } // 下面变量要传递给 `createRouter` const routes = [ // 动态参数以冒号开始 { path: '/users/:id', component: User }, ] ~~~ 现在URL像`/users/johnny`和`/users/jolyne`都映射到同一组件。 <br /> 一个有冒号`:`标志的参数,一旦路由匹配到,在每个组件中都期望参数值传给`this.$route.params`。因此,我们可以更新用户的id来渲染模板: ~~~ const User = { template: '<div>User {{ $route.params.id }}</div>', } ~~~ 同一路由上可以有多个参数,它们会映射到`this.$route.params.`相应的字段上。例如: | pattern | matched path | $route.params | | --- | --- | --- | | /users/:username | /users/eduardo | `{ username: 'eduardo' }` | | /users/:username/posts/:postId | /users/eduardo/posts/123 | `{ username: 'eduardo', postId: '123' }` | `$route.params`另外,`$route`对象也期望其它有用信息如`$route.query`(如果url中有query的话),`$route.query`等。你可以查看全部细节`[API参考](https://next.router.vuejs.org/api/#routelocationnormalized)`。 这有一个可运行的示例:[demo](https://codesandbox.io/s/route-params-vue-router-examples-mlb14?from-embed&initialpath=%2Fusers%2Feduardo%2Fposts%2F1) >[译者按] 我觉得多个参数第一个参数不带key有点不规范。试了下使用kv方式也是可行的。 /users/username/:username/posts/:postId ### **响应参数变化** 使用带参数的路由有一件事需要注意,当用户从`/users/johnny`导航到`/users/jolyne`时,**相同的组件实例将会被复用**。复用同一组件,总比销毁旧组件再实例化新组件效率要高。**但是,这意味着组件的生命周期勾子将不会被调用 !** 响应同一组件的参数变化,你只需简单的监听`$route`对象,就是`$route.params`: ~~~ const User = { template: '...', created() { this.$watch( () => this.$route.params, (toParams, previousParams) => { // react to route changes... } ) }, } ~~~ 或者,使用`beforeRouteUpdate`[导航向导](https://next.router.vuejs.org/guide/advanced/navigation-guards.html),它也可以让你取消导航: ~~~ const User = { template: '...', async beforeRouteUpdate(to, from) { // react to route changes... this.userData = await fetchUser(to.params.id) }, } ~~~ ### **拦截所有404路由** 常规参数只会匹配URL间`/`分隔的不同片断。如果我们想匹配任何内容,我们可以通过在参数后括号内加入正则表达式来定制一个参数规则: ~~~ const routes = [ // 会匹配 `$route.params.pathMatch`中的所有内容 { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound }, // 匹配所有以 `/user-`开始和`$route.params.afterUser`下面的所有内容 { path: '/user-:afterUser(.*)', component: UserGeneric }, ] ~~~ 特定方案我们在括号内使用[定制正则表达式](https://next.router.vuejs.org/guide/essentials/route-matching-syntax.html#custom-regexp-in-params)和将`pathMatch`参数作为可[重复选择项](https://next.router.vuejs.org/guide/essentials/route-matching-syntax.html#optional-parameters)。如果我们需要将`path`分割成一个数组,这可以让我们直接导航到路由。 ~~~ this.$router.push({ name: 'NotFound', //保存当前路径和移除第一个字符避免目标URL以`//`开始 params: { pathMatch: this.$route.path.substring(1).split('/') }, // 如果有query和has,保存之 query: this.$route.query, hash: this.$route.hash, }) ~~~ 更多请查阅[重复参数](https://next.router.vuejs.org/guide/essentials/route-matching-syntax.html#repeatable-params) 如果你使用[hsitory模式](https://next.router.vuejs.org/guide/essentials/history-mode.html),也要确认跟随介绍正确配置你的服务。 ### **高级匹配模式** Vue路径使用自带的路径匹配语法,使用`express`,所以它支持一些高级参数模式如选项参数,0或更多/一个或更多([译者按]应该是对应正则里的*和+)需求,甚至是自定义正则表达式模式。参考[高级匹配(https://next.router.vuejs.org/guide/essentials/route-matching-syntax.html)学习更多知识。 ## 高级