路由
前端路由的实现原理
使用Vue-Router实现前端路由
实现嵌套路由,动态路由
实现命名路由以及编程式导航
并实现后台管理案例javascript
路由的本质就是一种对应关系,好比说咱们在url地址中输入咱们要访问的url地址以后,浏览器要去请求这个url地址对应的资源。
那么url地址和真实的资源之间就有一种对应的关系,就是路由。html
路由分为前端路由和后端路由前端
后端路由性能相对前端路由来讲较低,因此,咱们接下来主要学习的是前端路由
前端路由的基本概念:根据不一样的事件来显示不一样的页面内容,即事件与事件处理函数之间的对应关系
前端路由主要作的事情就是监听事件并分发执行事件处理函数vue
SPA(Single Page Application)java
前端路由web
后端路由vue-router
前端路由是基于hash值的变化进行实现的(好比点击页面中的菜单或者按钮改变URL的hash值,根据hash值的变化来控制组件的切换)
核心实现依靠一个事件,即监听hash值变化的事件编程
window.onhashchange = function(){ //location.hash能够获取到最新的hash值 location.hash }
前端路由实现tab栏切换:segmentfault
<!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> <!-- 导入 vue 文件 --> <script src="./lib/vue_2.5.22.js"></script> </head> <body> <!-- 被 vue 实例控制的 div 区域 --> <div id="app"> <!-- 切换组件的超连接 --> <a href="#/zhuye">主页</a> <a href="#/keji">科技</a> <a href="#/caijing">财经</a> <a href="#/yule">娱乐</a> <!-- 根据 :is 属性指定的组件名称,把对应的组件渲染到 component 标签所在的位置 --> <!-- 能够把 component 标签当作是【组件的占位符】 --> <component :is="comName"></component> </div> <script> // #region 定义须要被切换的 4 个组件 // 主页组件 const zhuye = { template: '<h1>主页信息</h1>' } // 科技组件 const keji = { template: '<h1>科技信息</h1>' } // 财经组件 const caijing = { template: '<h1>财经信息</h1>' } // 娱乐组件 const yule = { template: '<h1>娱乐信息</h1>' } // #endregion // #region vue 实例对象 const vm = new Vue({ el: '#app', data: { comName: 'zhuye' }, // 注册私有组件 components: { zhuye, keji, caijing, yule } }) // #endregion // 监听 window 的 onhashchange 事件,根据获取到的最新的 hash 值,切换要显示的组件的名称 window.onhashchange = function() { // 经过 location.hash 获取到最新的 hash 值 console.log(location.hash); switch(location.hash.slice(1)){ case '/zhuye': vm.comName = 'zhuye' break case '/keji': vm.comName = 'keji' break case '/caijing': vm.comName = 'caijing' break case '/yule': vm.comName = 'yule' break } } </script> </body> </html>
案例效果图:后端
点击每一个超连接以后,会进行相应的内容切换,以下:
核心思路:
在页面中有一个vue实例对象,vue实例对象中有四个组件,分别是tab栏切换须要显示的组件内容
在页面中有四个超连接,以下:
<a href="#/zhuye">主页</a> <a href="#/keji">科技</a> <a href="#/caijing">财经</a> <a href="#/yule">娱乐</a>
当咱们点击这些超连接的时候,就会改变url地址中的hash值,当hash值被改变时,就会触发onhashchange事件
在触发onhashchange事件的时候,咱们根据hash值来让不一样的组件进行显示:
window.onhashchange = function() { // 经过 location.hash 获取到最新的 hash 值 console.log(location.hash); switch(location.hash.slice(1)){ case '/zhuye': //经过更改数据comName来指定显示的组件 //由于 <component :is="comName"></component> ,组件已经绑定了comName vm.comName = 'zhuye' break case '/keji': vm.comName = 'keji' break case '/caijing': vm.comName = 'caijing' break case '/yule': vm.comName = 'yule' break } }
Vue Router
Vue Router官网:地址
Vue.js 官方的路由管理器。
它是一个Vue.js官方提供的路由管理器。是一个功能更增强大的前端路由器,推荐使用。
Vue Router官网:地址
Vue Router和Vue.js很是契合,能够一块儿方便的实现SPA(single page web application,单页应用程序)应用程序的开发。
Vue Router依赖于Vue,因此须要先引入Vue,再引入Vue Router
Vue Router的特性:
A.导入js文件
<script src="lib/vue_2.5.22.js"></script> <script src="lib/vue-router_3.0.2.js"></script>
B.添加路由连接:<router-link>
是路由中提供的标签,默认会被渲染为a标签,to属性默认被渲染为href属性,
to属性的值会被渲染为#开头的hash地址
<router-link to="/user">User</router-link> <router-link to="/login">Login</router-link>
C.添加路由填充位(路由占位符)
<router-view></router-view>
D.定义路由组件
var User = { template:"<div>This is User</div>" } var Login = { template:"<div>This is Login</div>" }
E.配置路由规则并建立路由实例
var myRouter = new VueRouter({ //routes是路由规则数组 routes:[ //每个路由规则都是一个对象,对象中至少包含path和component两个属性 //path表示 路由匹配的hash地址,component表示路由规则对应要展现的组件对象 {path:"/user",component:User}, {path:"/login",component:Login} ] })
F.将路由挂载到Vue实例中
new Vue({ el:"#app", //经过router属性挂载路由对象 router:myRouter })
小结:
Vue Router的使用步骤仍是比较清晰的,按照步骤一步一步就能完成路由操做
补充:
路由重定向:能够经过路由重定向为页面设置默认展现的组件
在路由规则中添加一条路由规则便可,以下:
var myRouter = new VueRouter({ //routes是路由规则数组 routes: [ //path设置为/表示页面最初始的地址 / ,redirect表示要被重定向的新地址,设置为一个路由便可 { path:"/",redirect:"/user"}, { path: "/user", component: User }, { path: "/login", component: Login } ] })
当咱们进行路由的时候显示的组件中还有新的子级路由连接以及内容。
嵌套路由最关键的代码在于理解子级路由的概念:
好比咱们有一个/login
的路由
那么/login
下面还能够添加子级路由,如:/login/account
/login/phone
<p> <router-link to="/user">User</router-link> <router-link to="/register">Register</router-link> </p> <div> <!-- 控制组件的显示位置 --> <router-view></router-view> </div>
const Register = { template: `<div> <h1>Register 组件</h1> <hr/> <router-link to="/register/tab1">Tab1</router-link> <router-link to="/register/tab2">Tab2</router-link> <!-- 子路由填充位置 --> <router-view/> </div>` }
const router = new VueRouter({ routes: [ { path: '/user', component: User }, { path: '/register', component: Register, // 经过 children 属性,为 /register 添加子路由规则 children: [ { path: '/register/tab1', component: Tab1 }, { path: '/register/tab2', component: Tab2 } ] } ] })
参考代码以下:
var User = { template: "<div>This is User</div>" } //Login组件中的模板代码里面包含了子级路由连接以及子级路由的占位符 var Login = { template: `<div> <h1>This is Login</h1> <hr> <router-link to="/login/account">帐号密码登陆</router-link> <router-link to="/login/phone">扫码登陆</router-link> <!-- 子路由组件将会在router-view中显示 --> <router-view></router-view> </div>` } //定义两个子级路由组件 var account = { template:"<div>帐号:<input><br>密码:<input></div>"}; var phone = { template:"<h1>扫我二维码</h1>"}; var myRouter = new VueRouter({ //routes是路由规则数组 routes: [ { path:"/",redirect:"/user"}, { path: "/user", component: User }, { path: "/login", component: Login, //经过children属性为/login添加子路由规则 children:[ { path: "/login/account", component: account }, { path: "/login/phone", component: phone }, ] } ] }) var vm = new Vue({ el: '#app', data: {}, methods: {}, router:myRouter });
页面效果大体以下:
var User = { template:"<div>用户:{{$route.params.id}}</div>"} // 路由组件中经过$route.params获取路由参数 var myRouter = new VueRouter({ //routes是路由规则数组 routes: [ //经过/:参数名 的形式传递参数 { path: "/user/:id", component: User }, ] })
补充:
若是使用$route.params.id
来获取路径传参的数据不够灵活。
1.咱们能够经过props来接收参数
var User = { props:["id"], template:"<div>用户:{{id}}</div>" } var myRouter = new VueRouter({ //routes是路由规则数组 routes: [ //经过/:参数名 的形式传递参数 //若是props设置为true,route.params将会被设置为组件属性 { path: "/user/:id", component: User,props:true }, ] })
2.还有一种状况,咱们能够将props设置为对象,那么就直接将对象的数据传递给
组件进行使用
var User = { props:["username","pwd"], template:"<div>用户:{{username}}---{{pwd}}</div>" } var myRouter = new VueRouter({ //routes是路由规则数组 routes: [ //经过/:参数名 的形式传递参数 //若是props设置为对象,则传递的是对象中的数据给组件 { path: "/user/:id", component: User,props:{username:"jack",pwd:123} }, ] })
3.若是想要获取传递的参数值还想要获取传递的对象数据,那么props应该设置为
函数形式。
var User = { props:["username","pwd","id"], template:"<div>用户:{{id}} -> {{username}}---{{pwd}}</div>" } var myRouter = new VueRouter({ //routes是路由规则数组 routes: [ //经过/:参数名 的形式传递参数 //若是props设置为函数,则这个函数接收 route 对象为本身的形参 //经过函数的第一个参数获取路由对象 //并能够经过路由对象的params属性获取传递的参数 { path: "/user/:id", component: User, props:(route)=>{ return {username:"jack",pwd:123,id:route.params.id} } }, ] })
案例:
var myRouter = new VueRouter({ //routes是路由规则数组 routes: [ //经过name属性为路由添加一个别名 { path: "/user/:id", component: User, name:"user"}, ] })
添加了别名以后,可使用别名进行跳转
<router-link to="/user">User</router-link> <router-link :to="{ name:'user' , params: {id:123} }">User</router-link>
还能够编程式导航
myRouter.push( { name:'user' , params: {id:123} } )
页面导航的两种方式:
A.声明式导航:经过点击连接的方式实现的导航
B.编程式导航:调用js的api方法实现导航
Vue-Router中常见的导航方式:
this.$router.push("hash地址"); this.$router.push("/login"); this.$router.push({ name:'user' , params: {id:123} }); this.$router.push({ path:"/login" }); this.$router.push({ path:"/login",query:{username:"jack"} }); this.$router.go( n );//n为数字,参考history.go this.$router.go( -1 );
案例效果:
点击左侧的"用户管理","权限管理","商品管理","订单管理","系统设置"都会出现对应的组件并展现内容
其中"用户管理"组件展现的效果如上图所示,在用户管理区域中的详情连接也是能够点击的,点击以后将会显示用户详情信息。
案例思路:
1).先将素材文件夹中的11.基于vue-router的案例.html复制到咱们本身的文件夹中。
看一下这个文件中的代码编写了一些什么内容,
这个页面已经把后台管理页面的基本布局实现了
2).在页面中引入vue,vue-router
3).建立Vue实例对象,准备开始编写代码实现功能
4).但愿是经过组件的形式展现页面的主体内容,而不是写死页面结构,因此咱们能够定义一个根组件:
//只须要把本来页面中的html代码设置为组件中的模板内容便可 const app = { template:`<div> <!-- 头部区域 --> <header class="header">传智后台管理系统</header> <!-- 中间主体区域 --> <div class="main"> <!-- 左侧菜单栏 --> <div class="content left"> <ul> <li>用户管理</li> <li>权限管理</li> <li>商品管理</li> <li>订单管理</li> <li>系统设置</li> </ul> </div> <!-- 右侧内容区域 --> <div class="content right"> <div class="main-content">添加用户表单</div> </div> </div> <!-- 尾部区域 --> <footer class="footer">版权信息</footer> </div>` }
5).当咱们访问页面的时候,默认须要展现刚刚建立的app根组件,咱们能够
建立一个路由对象来完成这个事情,而后将路由挂载到Vue实例对象中便可
const myRouter = new VueRouter({ routes:[ {path:"/",component:app} ] }) const vm = new Vue({ el:"#app", data:{}, methods:{}, router:myRouter })
补充:到此为止,基本的js代码都处理完毕了,咱们还须要设置一个路由占位符
<body> <div id="app"> <router-view></router-view> </div> </body>
6).此时咱们打开页面应该就能够获得一个VueRouter路由出来的根组件了
咱们须要在这个根组件中继续路由实现其余的功能子组件
先让咱们更改根组件中的模板:更改左侧li为子级路由连接,并在右侧内容区域添加子级组件占位符
const app = { template:`<div> ........ <div class="main"> <!-- 左侧菜单栏 --> <div class="content left"> <ul> <!-- 注意:咱们把全部li都修改成了路由连接 --> <li><router-link to="/users">用户管理</router-link></li> <li><router-link to="/accesses">权限管理</router-link></li> <li><router-link to="/goods">商品管理</router-link></li> <li><router-link to="/orders">订单管理</router-link></li> <li><router-link to="/systems">系统设置</router-link></li> </ul> </div> <!-- 右侧内容区域 --> <div class="content right"> <div class="main-content"> <!-- 在 --> <router-view></router-view> </div> </div> </div> ....... </div>` }
而后,咱们要为子级路由建立并设置须要显示的子级组件
//建议建立的组件首字母大写,和其余内容区分 const Users = {template:`<div> <h3>用户管理</h3> </div>`} const Access = {template:`<div> <h3>权限管理</h3> </div>`} const Goods = {template:`<div> <h3>商品管理</h3> </div>`} const Orders = {template:`<div> <h3>订单管理</h3> </div>`} const Systems = {template:`<div> <h3>系统管理</h3> </div>`} //添加子组件的路由规则 const myRouter = new VueRouter({ routes:[ {path:"/",component:app , children:[ { path:"/users",component:Users }, { path:"/accesses",component:Access }, { path:"/goods",component:Goods }, { path:"/orders",component:Orders }, { path:"/systems",component:Systems }, ]} ] }) const vm = new Vue({ el:"#app", data:{}, methods:{}, router:myRouter })
7).展现用户信息列表:
A.为Users组件添加私有数据,并在模板中循环展现私有数据
const Users = { data(){ return { userList:[ {id:1,name:"zs",age:18}, {id:2,name:"ls",age:19}, {id:3,name:"wang",age:20}, {id:4,name:"jack",age:21}, ] } }, template:`<div> <h3>用户管理</h3> <table> <thead> <tr> <th>编号</th> <th>姓名</th> <th>年龄</th> <th>操做</th> </tr> </thead> <tbody> <tr :key="item.id" v-for="item in userList"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.age}}</td> <td><a href="javascript:;">详情</a></td> </tr> </tbody> </table> </div>`}
8.当用户列表展现完毕以后,咱们能够点击列表中的详情来显示用户详情信息,首先咱们须要建立一个组件,用来展现详情信息
const UserInfo = { props:["id"], template:`<div> <h5>用户详情</h5> <p>查看 {{id}} 号用户信息</p> <button @click="goBack">返回用户详情页</button> </div> `, methods:{ goBack(){ //当用户点击按钮,后退一页 this.$router.go(-1); } } }
而后咱们须要设置这个组件的路由规则
const myRouter = new VueRouter({ routes:[ {path:"/",component:app , children:[ { path:"/users",component:Users }, //添加一个/userinfo的路由规则 { path:"/userinfo/:id",component:UserInfo,props:true}, { path:"/accesses",component:Access }, { path:"/goods",component:Goods }, { path:"/orders",component:Orders }, { path:"/systems",component:Systems }, ]} ] }) const vm = new Vue({ el:"#app", data:{}, methods:{}, router:myRouter })
再接着给用户列表中的详情a链接添加事件
const Users = { data(){ return { userList:[ {id:1,name:"zs",age:18}, {id:2,name:"ls",age:19}, {id:3,name:"wang",age:20}, {id:4,name:"jack",age:21}, ] } }, template:`<div> <h3>用户管理</h3> <table> <thead> <tr> <th>编号</th> <th>姓名</th> <th>年龄</th> <th>操做</th> </tr> </thead> <tbody> <tr :key="item.id" v-for="item in userList"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.age}}</td> <td><a href="javascript:;" @click="goDetail(item.id)">详情</a></td> </tr> </tbody> </table> </div>`, methods:{ goDetail(id){ this.$router.push("/userinfo/"+id); } } }
this.$router 至关于一个全局的路由器对象,包含了不少属性和对象(好比 history 对象),任何页面均可以调用其 push(), replace(), go() 等方法。
this.$route 表示当前路由对象,每个路由都会有一个 route 对象,是一个局部的对象,能够获取对应的 name, path, params, query 等属性。