1、路由的概念
-
路由的概念:
- 后端的路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源
- 前端的路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;
-
单页面的概念:
-
多页面:MPA multiple page application 利用a链接
-
单页面:SPA single page application 通过判断hash的变化(vue-router)
-
2、Vue-Router基础使用
-
第1步:引入vue.js 再引入vue-router.js、 vue-router需要引入在vue之后
-
第2步:设置路由
-
a、配置页面组件的配置信息
let 组件配置变量 ={ template:"#模板id", data(){ return{} } ... }
-
b、建立映射关系
let routes = [ { path:"/地址", component:组件配置变量 }, { path:"/地址/:id", // 动态路由 component:组件配置变量 }, { path:"/地址", components:{ default:组件配置变量 // <router-view name="default"/> 视图的名称:组件配置变量 // <router-view name="视图名称"/> } }, { path:"/地址", // 访问地址的时候回去访问地址2 component:组件配置变量, redirect:"/地址2" }, { path:"/地址", component:组件配置变量A, children:[ { path:"地址2", // 访问 /地址/地址2 //就渲染 组件配置变量 会渲染在组件配置变量A模板里面router-view里面 component:组件配置变量 } ] } ]
-
实例化一个路由对象
let router = new VueRouter({ // routes:routes // routes 简写 routes })
-
挂载到Vue实例里面去
new Vue({ el:"", data:{}, // router:router // 简写 router })
-
在vue的模板里面设置好视图
<div id="app"> <router-view/> </div>
-
页面的跳转 使用 router-link
<router-link to="/地址">
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <router-view></router-view> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <router-link to="/">首页</router-link> <router-link to="/menus">分类</router-link> <router-link to="/car">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> </body> <script> // 第2步: 定义页面所需要的组件 let index = { template:"<h1>首页</h1>", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let menus = { template:"<h1>分类</h1>", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let car = { template:"<h1>购物车</h1>", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let user = { template:"<h1>用户</h1>", data(){ return{ } }, computed:{}, watch:{}, methods:{} } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:index }, { path:"/menus", component:menus }, { path:"/car", component:car }, { path:"/user", component:user } ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> <script> // 什么是路由: // 后端的路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源 // 前端的路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现; // 单页面应用程序: // 多页面 MPA multiple page application 利用a链接 // 单页面 SPA single page application // vue-router Vue的路由 实现 hash变化。 页面变化(渲染不同的组件) // 第一步: 引入vue 引入vue-router // 第二步: 配置页面组件 // 第三步: 配置映射关系 访问什么地址,渲染什么组件 // 第四步: 实例化一个路由对象 将配置映射关系放入 // 第五步: 将路由对象注入到 Vue实例里面去 </script> </html>
-
3、激活class、路由模式、重定向、404
-
激活class
// 实例化路由对象的时候 let router = new VueRouter({ routes:routes, activeLinkClass:"激活class名" // 只要页面的地址和a链接里面地址一致,这个a将会被添加上这个class }) // 注意: 有个坑 // 首页如果设置为 / 那么,也会被匹配中。 是因为路由没有进行严格匹配。 // 解决: <router-link exact to="/">首页</router-link>
-
路由模式
// 实例化路由对象的时候 let router = new VueRouter({ routes:routes, mode:"hash/history" // 默认是hash history一定要跑服务器的模式运行 })
-
重定向 redirect
let routes = [ { path:"/地址", // 访问 地址 的时候回去访问 地址2 component:组件配置变量, redirect:"/地址2" }, ]
-
- 配置一些路由没有设置的时候显示的页面
let routes = [ { // 一般配置在最后 path:"*", // 路由没有设置,没有匹配到。 那么就渲染这里的组件 component:组件配置变量 }, ]
-
代码实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } .footer a{ width: 25%; float: left; text-align: center; line-height: 60px; } .footer a.active{ background-color: orange; color: #fff; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <router-view></router-view> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <router-link exact to="/">首页</router-link> <router-link to="/menus">分类</router-link> <router-link to="/car">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> </div> </template> <!---------------------分类模板---------------------------> <template id="menus"> <div class="page"> <h3>我是分类x</h3> </div> </template> <!---------------------购物车模板---------------------------> <template id="car"> <div class="page"> <h3>我是购物车</h3> </div> </template> <!---------------------用户模板---------------------------> <template id="user"> <div class="page"> <h3>我是用户</h3> </div> </template> <!---------------------404---------------------------> <template id="notfound"> <div class="page"> <h3>找不到这个该死的页面</h3> </div> </template> </body> <script> // 第2步: 定义页面所需要的组件 let index = { template:"#index", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let menus = { template:"#menus", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let car = { template:"#car", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let user = { template:"#user", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let notfound = { template:"#notfound", data(){ return{ } }, computed:{}, watch:{}, methods:{} } // 第3步:建立路由映射关系 / index /menus menus /car car /user user // let ysgx = [ let routes = [ { path:"/", // 访问地址 component:index, // 对应地址渲染的组件 redirect:"/car" // 重定向 }, { path:"/menus", component:menus }, { path:"/car", component:car }, { path:"/user", component:user }, { path:"*", // 这个选项是最后一个映射关系 component:notfound } ] // 第4步: 创建一个路由(实例化一个路由对象) // new VueRouter(配置对象) // let ly = new VueRouter({ let router = new VueRouter({ // routes: ysgx //routes 路由配置信息 // routes: routes // 前面的routes是固定的配置项, routes是变量名 routes, linkActiveClass:"active", // 激活class 注意:坑 就是 首页 / router-link 需要添加上 exact // mode:"history" // 路由模式, hash 默认 history }); // 第5步: 将路由实例注入到Vue实例中 // vue 实例里面 有一个router配置选项 new Vue({ el:"#app", data:{ }, // router:ly // router:router router // router:router }) </script> <script> </script> </html>
4、动态路由设置
-
如何设置:
let routes = [ { path:"/list/:id", // 访问 /list/10 component:组件配置变量 }, ]
<router-link to="/list/10">新闻10</router-link>
-
如何获取这个动态参数:
// 在跳转的组件内部: this.$route // 当前路由信息 this.$route.params // 当前路由的动态数据 this.$route.params.id // 获取值
-
什么时候用: 多级页面跳转,传递关键参数。 比如列表到详情,传入ID
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <router-view></router-view> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <router-link to="/">首页</router-link> <router-link to="/menus">分类</router-link> <router-link to="/car">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> </div> </template> <!---------------------分类模板---------------------------> <template id="menus"> <div class="page"> <h3>我是分类x</h3> <ul> <li> <router-link to="/list/1">AAA</router-link> </li> <li> <router-link to="/list/2">BBB</router-link> </li> </ul> </div> </template> <!---------------------购物车模板---------------------------> <template id="car"> <div class="page"> <h3>我是购物车</h3> </div> </template> <!---------------------用户模板---------------------------> <template id="user"> <div class="page"> <h3>我是用户</h3> </div> </template> <!---------------------列表模板---------------------------> <template id="list"> <div class="page"> <h3>我是列表</h3> </div> </template> </body> <script> // 第2步: 定义页面所需要的组件 let index = { template:"#index", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let menus = { template:"#menus", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let car = { template:"#car", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let user = { template:"#user", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let list = { template:"#list", data(){ return{ } }, created(){ console.log(this.$route); // 当前路由信息 console.log(this.$route.params); } } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:index }, { path:"/menus", component:menus }, { path:"/car", component:car }, { path:"/user", component:user }, { path:"/list/:id", // /list/2 component:list } ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> <script> </script> </html>
5、编程式导航
-
本质: 通过JS控制页面的跳转
-
实现:
this.$router // 当期那的路由对象 // push(地址) 打开新页面 // go(-1,0,1) 前进、后退、刷新 // back() 后退 // forward() 前进 this.$router.push(path地址) this.$router.go(1/-1/0) this.$router.back() this.$router.forward()
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <router-view></router-view> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <router-link to="/">首页</router-link> <router-link to="/menus">分类</router-link> <router-link to="/car">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> <!-- <button @click="go">我要去用户中心</button> --> <button @click="$router.push('/user')">我要去用户中心</button> </div> </template> <!---------------------分类模板---------------------------> <template id="menus"> <div class="page"> <h3>我是分类x</h3> </div> </template> <!---------------------购物车模板---------------------------> <template id="car"> <div class="page"> <h3>我是购物车</h3> </div> </template> <!---------------------用户模板---------------------------> <template id="user"> <div class="page"> <h3>我是用户</h3> <button @click="$router.back()">返回</button> </div> </template> </body> <script> // 第2步: 定义页面所需要的组件 let index = { template:"#index", data(){ return{ } }, computed:{}, watch:{}, methods:{ go(){ console.log("go"); console.log(this.$router); // push() back() forward() go() this.$router.push('/user'); } } } let menus = { template:"#menus", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let car = { template:"#car", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let user = { template:"#user", data(){ return{ } }, computed:{}, watch:{}, methods:{} } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:index }, { path:"/menus", component:menus }, { path:"/car", component:car }, { path:"/user", component:user } ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> <script> // <!-- 编程式导航: 用JS控制导航 用JS控制页面跳转 --> // 编程式导航就是: 组件this里面有一个 $router 代表 实例化的路由对象。 // 而这个路由对象, 有 push(); go(); back(); forward(); </script> </html>
6、命名视图
-
本质: 访问一个路由路径的时候 同时渲染多个组件在不同的视图内
-
实现:
let routes = [ { path:"/地址", components:{ default:组件配置变量 // <router-view name="default"/> 视图的名称A:组件配置变量A // <router-view name="视图名称A"/> } }, ]
<router-view name="default"/> <router-view name="视图的名称A"/>
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <div class="box1"> <router-view name="default"></router-view> </div> <div class="box2"> <router-view name="aa"></router-view> </div> <div class="box3"> <router-view name="bb"></router-view> </div> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <router-link to="/">首页</router-link> <router-link to="/menus">分类</router-link> <router-link to="/car">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> </div> </template> <!---------------------分类模板---------------------------> <template id="menus"> <div class="page"> <h3>我是分类x</h3> </div> </template> <!---------------------购物车模板---------------------------> <template id="car"> <div class="page"> <h3>我是购物车</h3> </div> </template> <!---------------------用户模板---------------------------> <template id="user"> <div class="page"> <h3>我是用户</h3> </div> </template> </body> <script> // 第2步: 定义页面所需要的组件 let index = { template:"#index", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let menus = { template:"#menus", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let car = { template:"#car", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let user = { template:"#user", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let shuai = { template:"<h1>我很帅</h1>" } let mei = { template:"<h1>我很美</h1>" } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:index }, { path:"/menus", component:menus }, { path:"/car", // 访问car的时候,同时渲染 car组件。 shuai组件,mei组件 // component:car components:{ default:car, aa:shuai, bb:mei } }, { path:"/user", component:user } ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> <script> // 命名视图: 一个地址渲染一个组件,有时候我们希望访问一个path地址,同时渲染多个组件 // 使用: /* { path:"地址", components:{ default:组件 组件将会渲染在 <router-view name="default"></router-view> 名称A:组件A 组件A将会渲染在 <router-view name="名称A"></router-view> 名称B:组件B 组件B将会渲染在 <router-view name="名称B"></router-view> } } // 命名视图一定要注意 视图 的对应性 */ </script> </html>
7、嵌套路由
-
本质: 一个页面需要内部还有一个不同的内容展示区域。 比如:个人中心,左侧是个人中心的菜单,右侧是不同菜单的内容。
-
实现:
let routes = [ { path:"/地址", component:组件配置变量A, children:[ { path:"地址2", // 切记不要加/ // 访问 /地址/地址2 //就渲染 组件配置变量 会渲染在组件配置变量A模板里面router-view里面 component:组件配置变量 } ] } ]
//组件A内部要有一个router-view.而不是渲染在根级的router-view里面
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .nav{ width: 1200px; line-height: 60px; background-color:red; margin: 0 auto; } .nav li{ display: inline-block; } .content{ width: 1200px; height: 400px; background-color: #eee; margin: 0 auto; } .left{ width: 200px; background-color: orange; float: left; } .right{ width: 700px; height: 400px; background-color: blue; float: left; } </style> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> </head> <body> <div id="app"> <div class="nav"> <ul> <li> <router-link to='/'>首页</router-link> </li> <li> <router-link to='/user'>用户中心</router-link> </li> </ul> </div> <div class="content"> <router-view></router-view> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> </div> </template> <!---------------------用户模板---------------------------> <template id="user"> <div class="page"> <div class="left"> <ul> <li> <router-link to="/user/userorder">我的订单</router-link> </li> <li> <router-link to="/user/useraddress">我的地址</router-link> </li> </ul> </div> <div class="right"> <router-view/> </div> </div> </template> </body> <script> // 路由 中 在套了一个路由 </script> <script> // 第2步: 定义页面所需要的组件 let index = { template:"#index", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let user = { template:"#user", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let userInfo = { template:"<h1>我是用户中心</h1>" } let userOrder = { template:"<h1>我是用户订单</h1>" } let userAddress = { template:"<h1>我是用户地址</h1>" } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:index }, { path:"/user", component:user, redirect:"/user/userinfo", children:[ // 当前路由的子路由 . 组件也会渲染在当前组件的 内部的router-view里面 { path:"userinfo", // 访问 /user/userinfo 就渲染userInfo组件 component:userInfo }, { path:"userorder", component:userOrder }, { path:"useraddress", component:userAddress } ] } ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> </html>
8、路由页面之间传参
-
作用: 多级页面之间的关键参数的传递
-
实现:
- search传参
- 动态路由
- 本地存储
-
search传参
<router-link to="/地址?属性名=属性值"></router-link>
// 组件JS内部 this.$route.query // {属性名:属性值} this.$route.query.属性名
-
动态路由
- 见上面
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <router-view></router-view> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <router-link to="/">首页</router-link> <router-link to="/menus">分类</router-link> <router-link to="/car">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> <router-link to='/user?abc=10#ttt=100&bb=200'>去用户中心</router-link> </div> </template> <!---------------------分类模板---------------------------> <template id="menus"> <div class="page"> <h3>我是分类x</h3> </div> </template> <!---------------------购物车模板---------------------------> <template id="car"> <div class="page"> <h3>我是购物车</h3> </div> </template> <!---------------------用户模板---------------------------> <template id="user"> <div class="page"> <h3>我是用户</h3> </div> </template> </body> <script> // 第2步: 定义页面所需要的组件 let index = { template:"#index", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let menus = { template:"#menus", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let car = { template:"#car", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let user = { template:"#user", data(){ return{ } }, created(){ console.log(this.$route); console.log(this.$route.query); // search参数内容 }, computed:{}, watch:{}, methods:{} } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:index }, { path:"/menus", component:menus }, { path:"/car", component:car }, { path:"/user", component:user } ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> <script> // 页面之间传参 // 设置成动态路由 this.$route.params.变量 // 通过search传参 this.$route.query.变量 </script> </html>
9、命名路由
-
定义: 给每个路由一个名称
let routes = [ { name:"路由名", path:"/", component:组件配置变量 } ]
-
访问的时候:
<router-link to="/地址?属性名=属性值"></router-link> <router-link :to="{name:'路由名',path:'/地址',params:{动态参数},query:{search传值}}"></router-link>
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <router-view></router-view> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <!-- <router-link to="/">首页</router-link> --> <router-link :to="{name:'Index'}">首页</router-link> <!-- <router-link to="/menus">分类</router-link> --> <router-link :to="{path:'/menus'}">分类</router-link> <!-- <router-link to="/car/1">购物车</router-link> --> <router-link :to="{name:'Car',params:{id:3}}">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> </div> </template> <!---------------------分类模板---------------------------> <template id="menus"> <div class="page"> <h3>我是分类x</h3> </div> </template> <!---------------------购物车模板---------------------------> <template id="car"> <div class="page"> <h3>我是购物车</h3> </div> </template> <!---------------------用户模板---------------------------> <template id="user"> <div class="page"> <h3>我是用户</h3> </div> </template> </body> <script> // 第2步: 定义页面所需要的组件 let Index = { template:"#index", data(){ return{ } }, created(){ console.log(this.$route); }, computed:{}, watch:{}, methods:{} } let Menus = { template:"#menus", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let Car = { template:"#car", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let User = { template:"#user", data(){ return{ } }, computed:{}, watch:{}, methods:{} } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:Index, name:"Index" }, { path:"/menus", component:Menus, name:"Menus" }, { path:"/car/:id", component:Car, name:"Car" }, { path:"/user", component:User, name:"User" } ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> <script> </script> </html>
10、路由元信息
-
定义: 每个路由我们都希望他们有一些属于自己的数据。比如每个页面都有自己的标题
-
实现:我们的每个映射关系对象有一个配置选项叫做meta。是一个对象,我们可以给这个对象设置相关信息。
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <router-view></router-view> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <router-link to="/">首页</router-link> <router-link to="/menus">分类</router-link> <router-link to="/car">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> </div> </template> <!---------------------分类模板---------------------------> <template id="menus"> <div class="page"> <h3>我是分类x</h3> </div> </template> <!---------------------购物车模板---------------------------> <template id="car"> <div class="page"> <h3>我是购物车</h3> </div> </template> <!---------------------用户模板---------------------------> <template id="user"> <div class="page"> <h3>我是用户</h3> </div> </template> </body> <script> // 第2步: 定义页面所需要的组件 let index = { template:"#index", data(){ return{ } }, computed:{}, watch:{}, methods:{}, created(){ console.log(this.$route); console.log(this.$route.meta); document.title = this.$route.meta.title } } let menus = { template:"#menus", data(){ return{ } }, computed:{}, watch:{}, methods:{}, created(){ console.log(this.$route); console.log(this.$route.meta); document.title = this.$route.meta.title } } let car = { template:"#car", data(){ return{ } }, computed:{}, watch:{}, methods:{}, created(){ console.log(this.$route); console.log(this.$route.meta); document.title = this.$route.meta.title } } let user = { template:"#user", data(){ return{ } }, computed:{}, watch:{}, methods:{}, created(){ console.log(this.$route); console.log(this.$route.meta); document.title = this.$route.meta.title } } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:index, meta:{ // 每个路由自己有的一些信息 title:"首页" } }, { path:"/menus", component:menus, meta:{ // 每个路由自己有的一些信息 title:"分类" } }, { path:"/car", component:car, meta:{ // 每个路由自己有的一些信息 title:"购物车" } }, { path:"/user", component:user, meta:{ // 每个路由自己有的一些信息 title:"用户" } } ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> <script> </script> </html>
11、导航守卫
-
当我们进入路由的时候,希望做一些事情。比如:设置标题、判断登录、判断权限。这个时候我们希望路由已进入就执行某个函数
-
全局守卫:所有路由跳转都会执行
-
进入前:beforeEach
实例化的路由对象.beforeEach((to,from,next)=>{ // 切记一定要next(),不然路由被挂起,不执行下去 next() }) // 往往做: 判断登录、权限验证、设置标题
-
离开后:afterEach
实例化的路由对象.afterEach((to,from)=>{ // 没有next })
-
-
局部守卫:某个路由跳转才会执行
-
进入前:
//组件配置项: { template:"#id值", data(){ return{} }, beforeRouteEnter(to,from,next){ // this 不是当前组件。 因为组件还未创建。 不要取设置当前组件的数据,因为this不是当前组件 next(); } }
-
路由更新前(重要):
//组件配置项: { template:"#id值", data(){ return{} }, beforeRouteUpdate(to,from,next){ // this 是当前组件。 // 重要: 当前组件跳转到当前组件,这个钩子函数将会被触发 next(); } }
-
离开前:
//组件配置项: { template:"#id值", data(){ return{} }, beforeRouteLeave(to,from,next){ // this 是当前组件。 // 作用:往往做一些离开之前的判断,比如是否保存 next(); } }
-
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <router-view></router-view> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <router-link to="/">首页</router-link> <router-link to="/menus">分类</router-link> <router-link to="/car">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> </div> </template> <!---------------------分类模板---------------------------> <template id="menus"> <div class="page"> <h3>我是分类x</h3> </div> </template> <!---------------------购物车模板---------------------------> <template id="car"> <div class="page"> <h3>我是购物车</h3> </div> </template> <!---------------------用户模板---------------------------> <template id="user"> <div class="page"> <h3>我是用户</h3> </div> </template> </body> <script> // 第2步: 定义页面所需要的组件 let index = { template:"#index", data(){ return{ } }, computed:{}, watch:{}, methods:{}, } let menus = { template:"#menus", data(){ return{ } }, // 局部导航钩子 beforeRouteEnter(to,from,next){ // 路由进入前 console.log("路由进入前"); console.log(this); // window next(); }, beforeRouteUpdate(to,from,next){ // 路由更新的时候 console.log("路由更新的时候"); console.log(this); // this 当前组件对象 next(); }, beforeRouteLeave(to,from,next){ // 路由离开的时候 console.log("路由离开的时候"); console.log(this); // this 是当前路由信息 next(); } } let car = { template:"#car", data(){ return{ } }, computed:{}, watch:{}, methods:{}, } let user = { template:"#user", data(){ return{ } }, computed:{}, watch:{}, methods:{}, } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:index, meta:{ // 每个路由自己有的一些信息 title:"首页" } }, { path:"/menus", component:menus, meta:{ // 每个路由自己有的一些信息 title:"分类" } }, { path:"/car", component:car, meta:{ // 每个路由自己有的一些信息 title:"购物车" } }, { path:"/user", component:user, meta:{ // 每个路由自己有的一些信息 title:"用户" } } ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 全局前置钩子 // 进入之前 作用: 设置标题、检测是否登录、权限判断 ly.beforeEach(function(to,from,next){ // to 去的路由信息 // from 来的路由信息 // next() 钩子里面一定要调用next() 不调用 路由将不继续前行 // console.log(from); // console.log(to); document.title = to.meta.title console.log("全局前置钩子"); next(); }) // 全局后置钩子 // 离开之后 作用:判断页面数据是否保存 ly.afterEach(function(to,from){ // to 去的路由信息 // from 来的路由信息 // 没有next console.log(from); console.log(to); console.log("全局后置钩子"); }); console.log(ly); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> <script> </script> </html>
12、坑(同组件跳转路由不更新)
-
描述:路由同组件跳转,组件将不会更新
- 出现bug 商品详情页底部推荐商品,我们就无法重新获取商品数据。
-
解决:
- 方法1: 利用watch监听$route的变化
- 方法2: 利用路由局部钩子 beforeRouteUpdate 只要路由更新就调用
-
代码实现:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>Document</title> <!-- 引入vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-router.js 一定要引入在vue之后 --> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <style> body{ background-color: #000; } *{ margin: 0; padding: 0; } #app{ background-color: #fafafa; min-width: 320px; max-width: 640px; height: 100vh; /*v是 viewport 视口 vh 视口的高度 */ margin: 0 auto; position: relative; box-sizing: border-box; padding: 40px 0 60px; } .header{ width: 100%; height: 40px; text-align: center; background-color: orange; color: #fff; position: absolute; left: 0; top: 0; } .content{ height: 100%; overflow-y: scroll; } .footer{ width: 100%; height: 60px; background-color: #fff; border-top: 1px solid #eee; color: #fff; position: absolute; left: 0; bottom: 0; } </style> </head> <body> <div id="app"> <div class="header"></div> <div class="content"> <!-- 视图组件。 组件渲染在这里 --> <router-view></router-view> </div> <div class="footer"> <!-- router-link 组件 最终会渲染成a --> <router-link to="/">首页</router-link> <router-link to="/menus">分类</router-link> <router-link to="/car">购物车</router-link> <router-link to="/user">用户</router-link> </div> </div> <!---------------------首页模板---------------------------> <template id="index"> <div class="page"> <h3>我是index</h3> <ul> <li><router-link to="/list/1"> 新闻1</router-link> </li> <li><router-link to="/list/2"> 新闻2</router-link> </li> <li><router-link to="/list/3"> 新闻3</router-link> </li> </ul> </div> </template> <!---------------------列表模板---------------------------> <template id="list"> <div class="page"> <h3>我是新闻详情</h3> <p>新闻的ID是:{{ $route.params.id }}</p> <hr> <h3>推荐文章</h3> <ul> <li><router-link to="/list/111"> 新闻1111</router-link> </li> <li><router-link to="/list/222"> 新闻2222</router-link> </li> <li><router-link to="/list/333"> 新闻33333</router-link> </li> </ul> </div> </template> </body> <script> // 第2步: 定义页面所需要的组件 let index = { template:"#index", data(){ return{ } }, computed:{}, watch:{}, methods:{} } let list = { template:"#list", data(){ return{ } }, created(){ console.log("list组件被创建了"); console.log(this.$route.params.id); this.getdata(); }, // watch:{ // $route:function(){ // console.log('路由更新了'); // this.getdata(); // } // }, // watch:{ // 简写 // '$route':'getdata' // }, beforeRouteUpdate(to,from,next){ // 路由更新的时候 console.log("路由更新的时候"); console.log(this); // this 是当前路由信息 this.getdata(); next(); }, methods:{ getdata(){ // ajax } } } // 第3步:建立路由映射关系 / index /menus menus /car car /user user let ysgx = [ { path:"/", component:index }, { path:"/list/:id", component:list }, ] // 第4步: 创建一个路由(实例化一个路由对象) let ly = new VueRouter({ routes: ysgx //routes 路由配置信息 }); // 第5步: 将路由实例注入到Vue实例中 new Vue({ el:"#app", data:{ }, router:ly }) </script> <script> // 路由同组件跳转,组件将不会更新 // bug 商品详情页底部推荐商品,我们就无法重新获取商品数据。 // 方法1: 利用watch监听$route的变化 // 方法2: 利用路由局部钩子 beforeRouteUpdate 只要路由更新就调用 </script> </html>