前端路由的实现原理
为什么要做单页面应用?
- (1) 传统的开发方式url改变后,立马发送请求响应整个页面, 有可能资源过多,传统开发会让前端的页面出现"白屏", 用户体验较差
- (2) SPA单页面应用:锚点值的改变后不会立刻发送请求, 而是在某个合适的时机, 发送ajax请求, 局部改变页面中的数据, 页面不立刻跳转
前端路由
- 1 锚点值监视
- 2 ajax获取动态的数据
- 3 核心点是锚点值的改变
如何使用vue-router
下载 vue-router
npm init --yes
npm install vue-router --save
1 引入vue-router模块 默认会抛出一个VueRouter对象 另外还有两个全局的组件 router-link, router-view
<script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/vue-router.js"></script>
2 使用VueRouter
Vue.use(VueRouter);
3 创建路由对象
// 创建一个路由对象 var router = new VueRouter({ // 配置路由对象 routes:[ { path:'/login', component:Login }, { path:'/register', component:Register } ] });
4 路由对象挂载到vue实例化对象中
var App = { template:` <div> <!--router-link默认会被渲染成a标签 to属性默认会被渲染成href属性--> <router-link :to="{name:'login'}">登录页面</router-link> <router-link :to="{name:'register'}">注册页面</router-link> <!--路由组件的出口--> <router-view></router-view> </div> ` }; new Vue({ el:'#app', components:{ App }, //挂载 router, template:`<App />` });
使用实例:
<div id="app"></div> <script type="text/javascript" src="node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript" src="node_modules/vue/dist/vue.js"></script> <script> // 让vue使用VueRouter创建 Vue.use(VueRouter); var Login = { template: ` <div>登录页面</div> ` }; var Register = { template: ` <div>注册页面</div> `, } // 创建一个路由对象 var router = new VueRouter({ // 配置路由对象 routes:[ { path:'/login', component:Login }, { path:'/register', component:Register } ] }); var App = { // router-link默认会被渲染成a标签 to属性默认会被渲染成href属性 template: ` <div> <router-link to="/login">登录页面</router-link> <router-link to="/register">注册页面</router-link> <!--路由组件的出口--> <router-view></router-view> </div> ` }; new Vue({ el: '#app', components: { App }, router, template: `<App/>` })
5 命名路由
给当前的配置路由信息对象设置name:'login'属性 :to = "{name:'login'}" <router-link :to="{name:'login'}">登陆</router-link> <router-link :to="{name:'register'}">注册</router-link> var router = new VueRouter({ routes:[ { path:'/login', name:'login', component: Login }, { path:"/register", name:"register", component:Register } ] });
6 路由规范
(1) xxxx.html#/user/1
//配置路由对象 var userParam = { template:"<div>用户1</div>", created(){ console.log(this.$router); console.log(this.$route); console.log(this.$route.params.user_id) } }; { path:'/user/:id', component:User } <router-link :to = "{name:'user',params:{id:1}}"></router-link>
(2) xxxx.html#/user?userId = 1
var userQuery = { template:"<div>用户2</div>", created(){ console.log(this.$router); console.log(this.$route); console.log(this.$route.query.user_id) } }; { path:'/user' } <router-link :to = "{name:'user',query:{id:1}}"></router-link> //在组件内部通过this.$route 获取路由信息对象
7 嵌套路由
<body> <div id="app"></div> <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script> <!-- 1.引入 vue-router的对象 --> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <!-- 全局的VueRouter对象 vue-router 还给咱们提供了两个全局的组件 router-link router-view--> <script type="text/javascript"> // 嵌套路由: // 需求:进入首页之后 点击音乐/hone/music 电影 /home/movie Vue.use(VueRouter); var Home = { template:` <div> <br/> <router-link to="/home/music">音乐</router-link> <router-link to="/home/moive">电影</router-link> <! --子路由组件--> <router-view></router-view> </div> `, }; var Music = { template:` <div> 我是音乐</div> ` }; var Moive = { template:` <div> 我是电影</div> ` }; // 3.创建一个路由对象 var router = new VueRouter({ // 配置路由对象 routes:[ { // 根目录默认跳转到home path:'/', redirect:'/home' // redirect:{name:'home'} }, { path: '/home', name:'home', component:Home, children:[ // 动态路由匹配表示自组件中的结构是不同的 // 当访问/home时, Home组件的出口是不会渲染任何内容, 这是因为没有匹配到合适的子路由 { path:'', component:Music }, { path:'music', component:Music }, { path:'moive', component:Moive } ] } ] }); var App = { template:` <div> <router-link :to="{name:'home'}">首页</router-link> <router-view></router-view> </div> `, }; new Vue({ el:'#app', components:{ App }, router, template:`<App />` }); </script> </body> </html>
8 动态路由匹配
<body> <div id="app"></div> <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script> <!-- 1.引入 vue-router的对象 --> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <!-- 全局的VueRouter对象 vue-router 还给咱们提供了两个全局的组件 router-link router-view--> <script type="text/javascript"> Vue.use(VueRouter); var Timeline = { template:` <div> <router-link :to="{name:'comDesc', params:{id:'安卓'}}">安卓</router-link> <router-link :to="{name:'comDesc', params:{id:'前端'}}">前端</router-link> <router-link :to="{name:'comDesc', params:{id:'python'}}">python</router-link> <router-link :to="{name:'comDesc', params:{id:'JAVA'}}">JAVA</router-link> <router-view></router-view> </div> `, }; var Pins = { template:` <div> 我是沸点</div> ` }; // 共同的子组件 var ComDesc = { data(){ return { msg:'' } }, template:` <div> 我是一个{{msg}} </div> `, created(){ this.msg = '安卓' }, watch:{ '$route'(to, from){ console.log(to); console.log(from); this.msg = to.params.id } } }; // 3.创建一个路由对象 var router = new VueRouter({ // 配置路由对象 routes:[ // 动态的路由参数以冒号开头 { path: '/timeline', name: 'timeline', component: Timeline, children:[ { path: "", component:ComDesc }, { path:"/timeline/:id", name:'comDesc', component:ComDesc } ] }, { path: '/pins', name: 'pins', component: Pins } ] }); var App = { template:` <div> <router-link to = "/timeline">首页</router-link> <router-link to = "/pins">沸点</router-link> <!--路由组件的出口--> <router-view></router-view> </div> `, }; new Vue({ el:'#app', components:{ App }, router, template:`<App />` }); </script>
9 keep-alive在路由中的使用
保持组件之前的状态
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"></div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/vue-router.js"></script> <script> Vue.use(VueRouter); var home = { template: `<div> 我是首页 </div>` }; var Pins = { template: ` <div> <h3 @click='clickHandler'>我是沸点</h3> </div> `, created(){ console.log("沸点组件创建了") }, mounted(){ console.log("沸点组件DOM加载了") }, destroyed(){ console.log("沸点销毁了") }, methods:{ clickHandler(e){ e.target.style.color = 'red'; } } }; var router = new VueRouter({ routes: [ { path: '/home', component: home, }, { path: "/pins", name: "pins", component: Pins } ] }); var App = { template: `<div> <router-link to="/home">首页</router-link> <router-link to="/pins">沸点</router-link> <keep-alive> <router-view></router-view> </keep-alive> </div>` }; new Vue({ el: '#app', router, template: `<App/>`, components:{App} }) </script> </body> </html>
10 权限控制
<body> <div id="app"></div> <script type="text/javascript" src="./node_modules/vue/dist/vue.min.js"></script> <!-- 1.引入 vue-router的对象 --> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <!-- 全局的VueRouter对象 vue-router 还给咱们提供了两个全局的组件 router-link router-view--> <script type="text/javascript"> Vue.use(VueRouter); // 导航栏上 有首页 智能题库 登录退出 四个按钮 // 用户访问首页时 看到的是首页的内容 // 1.当用户访问智能题库时,此时我们检测用户是否有权限访问该智能题库的内容, // 如果没有 检测用户是否登录过,如果没有,则跳转登录页面,登录完成之后。 // 在localStroage中通存储该用户的用户名和密码,并且立刻跳转到智能题库页面 // 2.当用户点击黜退,该用户直接删除 var Home = { template:` <div> 我是首页 <router-view></router-view> </div> ` }; var Questionbank = { template:` <div> 我是题库 <router-view></router-view> </div> ` }; var Login ={ data(){ return{ name:'', pwd:'' } }, template:` <div> <input type="text" v-model = 'name'/> <input type="text" v-model = 'pwd'/> <input type="submit" value="登录" @click = 'loginHandler'/> </div> `, methods:{ loginHandler(){ // 要登录了 // 存储用户名和密码保存到locaStorage 然后跳转相应的路由 localStorage.setItem('user', {name: this.name, pwd: this.pwd}); // 编程式导航 this.$router.push({name:'questionbank'}) } } } var router = new VueRouter({ // 配置路由对象 routes:[ // 动态的路由参数以冒号开头 { path: '/home', name: 'home', component: Home }, { path: '/questionbank', name: 'questionbank', component: Questionbank, // 给未来的路由做权限控制 meta:{ // 如果是true表明该组件需要登录 auth:true } }, { path:'/login', component:Login } ] }); // 全局的导航守卫 router.beforeEach(function (to, from, next) { console.log(to); console.log(from); if(to.meta.auth){ // 用户点击了智能题库导航 该用户未登录, 需要登录判断 if(localStorage.getItem('user')){ // 不为空 放行 next() }else { // 为空 进行登录页面 next({path:'/login'}) } }else { // 如果不调用next那么页面会卡住 // 直接放行 next(); } }); var App = { template:` <div> <router-link to = "/home">首页</router-link> <router-link to = "/questionbank">智能题库</router-link> <router-link to = "/login">登录</router-link> <a href="javascripy:void(0)" @click ='clear'>退出</a> <!--路由组件的出口--> <keep-alive> <router-view></router-view> </keep-alive> </div> `, methods:{ clear(){ // 退出 localStorage.removeItem('user'); this.$router.push('/log') } } }; new Vue({ el:'#app', components:{ App }, router, template:`<App />` }); </script> </body>