🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一、前端路由与后端路由 路由模块的本质 就是建立起url和页面之间的映射关系; ### **定义** 后端路由: 所有的URL地址都对应服务器上对应的资源; 前端路由: 对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,称作前端路由(区别于后端路由); ### **hash的特点** 1、HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现; 2、#代表网页中的一个位置(锚点); 3、HTTP请求不包含#及之后的字符,他们不会被发送到服务器端; 4、改变#不触发网页重载,不会向服务器发起重新请求; 5、改变#会改变浏览器的访问历史; ## 二、使用步骤 * 第一步: 创建路由组件; * 第二步: 配置路由映射: 组件和路径映射关系; * 第三步: 使用路由: 通过router-link和router-view; ## 三、路由定义 路由定义对象,接受一个路由配置对象作为构造参数,其核心是路由匹配规则数组,数组中每条规则,包含的核心属性: 1、path:就是上面提到的,hash后面的内容; 2、component:如果路由是前面匹配到的`path`,则展示`component`属性对应的那个组件,必须是一个组件的模板对象, 不能是组件的引用名称; ## 四、页面用法 ### **路由展示** ``` <router-view></router-view> ``` router-view这是vue-router提供的元素,专门用来当作占位符的,按路由规则,匹配到的组件,就会展示到这个router-view中去; ### **路由跳转** ``` <router-link to="/register">注册</router-link> <router-link to="/login">登录</router-link> ``` 路由页面跳转需要加`#`,不然就当于跳转链接地址了,加了`#` 就定位到当前页面,因为每次都写`#`很麻烦,因此可以使用router-link,它默认渲染为一个`a`标签(可通过tag属性来指定其他渲染方式),且会自动带上#,如上面的router-link代码等同于下面的代码: ``` <a href="#/login">登录</a> <a href="#/register">注册</a> ``` ## 五、树形路由(嵌套路由) 真实系统中,路由树往往是树形结构的路由(官方称嵌套路由)跳转,我们可以通过点击或编程的方式跳转到任意一级的路由; ``` var router = new VueRouter({ routes: [ { path: '/p1', component: account, children: [ { path: 'p11', component: login }, { path: 'p12', component: register } ] } ] }) ``` >[danger] 注意: > 1、最底层的路由path,要带根路径/,其各级子孙,都不能带根路径/; > 2、匹配路由的时候,从根开始逐级匹配,比如,/p1/p12这个路由,则就能匹配到login组件; > 3、path自身,随便你怎么写,只要能被用户请求匹配得上; > 4、一般的,子路由里面的path,不要用/打头,因为这样会导致匹配不上; > 5、官方定义,通过children实现嵌套多级定义,定义的时候,也遵循嵌套定义path,那么,匹配的时候,也将通过嵌套逐级来匹配了; ## 六、编程导航 有时候,路由导航并不一定必须通过用户点击按钮,或者是在做跳转的时候,还需要做一些附加操作,这两种情况,都需要使用编程的方式来导航(有点像传统页面的post提交,通过代码来提交,而非点击一个链接); 编程导航用到的对象就是$router; 主要方法: * `this.$router.go`根据浏览器记录 前进`1`后退`-1`; * `this.$router.push`(直接跳转到某个页面显示) * `push`参数: 字符串`/xxx` * `push`参数:对象 :`{name:'xxx',query:{id:1},params:{name:2} }` * `this.$router.replace` * 跟`router.push`很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录; ## 七、参数传递 通过路由传递参数主要有两种类型: params和query; ### **params的类型:** ``` this.$router.push({ name:'XXX' //配置文件中的name params:{ name:'yaoxx' } }) /XXX中接收参数代码: this.$route.params.name; //ps:传参用$router,但是接收用$route ``` 或 ``` <router-link :to="{name:'master', params:{count:100,type:obj}}"> ``` * 配置路由格式: /router/:id * 传递的方式: 在path后面跟上对应的值 * 传递后形成的路径: /router/123, /router/abc ### **query的类型:** ``` this.$router.push({ path:'/XXX' query:{ name:'yaoxx' } }) /XXX中接收参数代码: this.$route.query.name; //ps:传参用$router,但是接收用$route ``` 或 ``` <router-link :to="{name:'master', query:{count:100,type:obj}}"> ``` * 配置路由格式: /router, 也就是普通配置 * 传递的方式: 对象中使用query的key作为传递方式 * 传递后形成的路径: /router?id=123, /router?id=abc ## 七、动态路由 所谓的动态路由,是指路由规则定义,是动态路径,含参数的,而不是静态字符串; 例如: ~~~ const User = { template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({ routes: [ // 动态路径参数 以冒号开头 { path: '/user/:id', component: User } ] }) ~~~ 如上,像`/user/foo`和`/user/bar`都将映射到相同的路由,且参数值会被设置到`this.$route.params`,可以在每个组件内使用; ## 八、路由匹配 1、有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高; 2、常规参数只会匹配被`/`分隔的 URL 片段中的字符。如果想匹配**任意路径**,我们可以使用通配符 (`*`);基于规则1,含有*通配符*的路由应该放在最后; ## 九、命名路由 定义路由规则的时候,除了path和component必选元素外,还有一个name属性,如果定义了,则它就是命名路由; 命名路由定义意味着使用的时候,可以通过名称来获取,而非path匹配了; ## 十、命名视图 定义路由规则的时候,除了path和component必选元素外,还有一个components属性,如果定义了,则它就是命名视图; 如果想要在一个路由中,展示多个视图构成的页面(例如,包含了侧边导航视图和内容视图两部分的页面),那么就要用命名视图了; 例子: ~~~jsx <router-view class="view one"></router-view> <router-view class="view two" name="a"></router-view> <router-view class="view three" name="b"></router-view> ~~~ ~~~cpp const router = new VueRouter({ routes: [ { path: '/', components: { default: Foo, a: Bar, b: Baz } } ] }) ~~~ 注意: 1、如果 router-view 没有设置名字(一般默认显示的那个不设置名称),那么默认为 default; 2、一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件,也因此,定义的时候,用的是components; 3、设置了多个命名路由的时候,如果路由配置的时候,某个路由选项,只会渲染它已经根据命名配置了的视图,如果没有配置的,则不会渲染,例如上面的,如果只配置了一个default,那么a和b都不会被渲染; ## 十一、重定向 定义路由规则的时候,除了path和component必选元素外,还有一个redirect属性,如果定义了,则它就是重定向; ~~~ const router = new VueRouter({ routes: [ { path: '/a', redirect: '/b' }, { path: '/c', redirect: { name: 'foo' }}//重定向的目标也可以是一个命名的路由 ] }) ~~~ “重定向”的意思是,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b; 上面的例子,表明,通过/a匹配到当前路由的时候,它并不直接访问组件,而是继续重定向到/b,去匹配/b的路由; ### **别名** ~~~ const router = new VueRouter({ routes: [ { path: '/a', component: A, alias: '/b' } ] }) ~~~ 1、/a的别名是/b,意味着,当用户访问/b时,URL 会保持为/b,但是路由匹配则为/a,就像用户访问/a一样; 2、“别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构;