43、前端路由介绍
44、前端路由原理
45、vue-router的基本使用
46、命名路由的使用
47、小结
48、路由参数之params和query的使用
49、编程式导航
50-51、嵌套路由的使用及警告处理
52、动态路由匹配
53、keep-alive在路由中的使用
43、前端路由介绍
vue+vue-router主要来做单页面应用(SinglePageApplication)
为什么我们要做单页面应用?
1)传统的开发方式URL改变后,立马发送请求,响应整个页面,
有可能资源过多,传统开发会让前端页面出现“白屏”用户体验不好
2)SPA单页面应用:锚点值的改变后,不会立刻发送请求,而是在某个合适的时机
发送ajax请求,局部改变页面中的数据,页面不立刻跳转。用户体验好
44、前端路由原理
SPA:SinglePageApplication
1)锚点值 监视
2)ajax获取动态的数据
3)核心点是锚点值的改变
前端中vue/react/angular都很适合做单页面应用
<body> <a href="#/login">登录页面</a> <a href="#/register">注册页面</a> <div id="app"> </div> <script type="text/javascript"> window.onhashchange = function () { oDiv = document.getElementById('app'); //onhashchange事件监听URL上锚点数据(#/xxx的改变) console.log(location.hash); //根据不同的锚点值,对页面不同的切换 switch (location.hash) { case '#/login': oDiv.innerHTML='<h2>登录页面</h2>'; break; case '#/register': oDiv.innerHTML='<h2>注册页面</h2>'; break; default: break; } } </script> </body>
45、vue-router的基本使用
下载vue-router:
npm init --yes
npm install vue-router --save
router-link标签上不能用类似“@click”语句绑定事件,要这样绑定事件必须用a标签或者button按钮
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <router-link to="/login">登录</router-link> <router-link to="/register">注册</router-link> <router-view></router-view> </div> </body> <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> // 0.如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter) // 1. 定义模块 const Login = {template:`<h1>登录页面</h1>`}; const Register = {template:`<h1>注册页面</h1>`}; // 2. 定义路由 const routes = [{path:"/login", component:Login},{path:"/register", component:Register}]; // 3. 实例化VueRouter let router = new VueRouter({ routes:routes }); // 4.在Vue中使用 new Vue({ router:router }).$mount("#app"); </script> </html>
被选中的<router-link>标签有router-link-active样式,如果自己定义了一个a标签的样式,例如:a.is-active{ color: red} ,怎样让a标签的is-active应用到router-link标签上呢???
实例化VueRouter时,加上linkActiveClass:"is-active"即可
如果不想要路由时候的‘#’号, 把路由模式改为‘history’模式即可
改之前:
改之后:
<body> <div id="app"> </div> <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script> <!--1. 引入vue-router对象 全局的VueRouter对象--> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> // 2. 让Vue使用该VueRouter创建(如果使用模块化机制编程,导入Vue和VueRouter要写Vue.use(VueRouter),实际上此处可以不写) Vue.use(VueRouter); // 创建路由组件 var Login = { template:`<h2>登录页面</h2>` }; var Register = { template:`<h2>注册页面</h2>` }; // 3. 创建一个路由对象 var router = new VueRouter({ // 配置路由对象 routes:[ { path:'/login', component:Login, }, { path:'/register', component:Register, }, ] }); //4. 创建Vue对象 var App={ template:`<div> <router-link to="/login">登录页面</router-link> <router-link to="/register">注册页面</router-link> <div id="view"> <router-view></router-view> </div> </div>` }; new Vue({ el:'#app', template:`<App />`, components:{ App }, router, //要让vue使用router }) </script> </body>
效果:
46、命名路由的使用
<body> <div id="app"> </div> <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script> <!--1. 引入vue-router对象 全局的VueRouter对象--> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> // 2. 让Vue使用该VueRouter创建 Vue.use(VueRouter); // 创建路由组件 var Login = { template:`<h2>登录页面</h2>` }; var Register = { template:`<h2>注册页面</h2>` }; // 3. 创建一个路由对象 var router = new VueRouter({ // 配置路由对象 routes:[ { path:'/login', name:'login', //命名路由 component:Login, }, { path:'/register', name:'register', //命名路由 component:Register, }, ] }); //4. 创建Vue对象 var App={ template:`<div> <router-link :to="{name:'login'}">登录页面</router-link> <router-link :to="{name:'register'}">注册页面</router-link> <div id="view"> <router-view></router-view> </div> </div>` }; new Vue({ el:'#app', template:`<App />`, components:{ App }, router, //要让vue使用router }) </script> </body>
47、小结
1)引入vue-router的模块,产生VueRouter对象和两个全局组件router-link和router-view
我们可以在任何组件内通过 this.$router
访问路由器,
push方法: this.$router.push({ name: 'userp', params: { userId: '1' }}) ----当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 等同于调用 router.push(…)。
repalce方法:this.$router.replace('/'
)
// 一般使用replace来做404页面
也可以通过 this.$route
访问当前路由(http://xxx.com/code/1 或者 http://xxx.com/code?id=1 ) this.$route.params / this.$route.query / this.$route.path
2)Vue.use(VueRouter)
3)创建路由对象
4)路由对象挂载到vue实例化对象中
5)命名路由,给当前的配置路由信息对象设置name属性
:to="{name:'login'}"
48、路由参数之params和query的使用
两种路由范式如何实现?
1)xxx.html#/user/1
2)xxx.html#/user?userID=1
<body> <div id="app"> </div> <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script> <!--1. 引入vue-router对象 全局的VueRouter对象--> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> // 2. 让Vue使用该VueRouter创建 Vue.use(VueRouter); // 创建路由组件 var UserParams = { template:`<h2>我是用户1</h2>`, created(){ // console.log(this.$route); //路由配置信息 // console.log(this.$router); //VueRouter对象 //发送ajax请求 console.log(this.$route.params.userId); // 1 } }; var UserQuery = { template:`<h2>我是用户2</h2>`, created(){ // 发送ajax请求 console.log(this.$route.query.userId); // 2 } }; // 3. 创建一个路由对象 var router = new VueRouter({ // 配置路由对象 routes:[ { // 路由范式一:xxx.html#/user/1 path:'/user/:userId', name:'userp', component:UserParams, }, { // 路由范式二:xxx.html#/user?userId=1 path:'/user', name:'userq', component:UserQuery, }, ] }); //4. 创建Vue对象 var App={ template:`<div> <router-link :to="{name:'userp', params:{userId:1}}">用户1</router-link> <router-link :to="{name:'userq', query:{userId:2}}">用户2</router-link> <div id="view"> <router-view></router-view> </div> </div>` }; new Vue({ el:'#app', template:`<App />`, components:{ App }, router, //要让vue使用router }) </script> </body>
效果:
49、编程式导航
上面的例子可以用编程式导航来实现:
<body> <div id="app"> </div> <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script> <!--1. 引入vue-router对象 全局的VueRouter对象--> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> // 2. 让Vue使用该VueRouter创建 Vue.use(VueRouter); // 创建路由组件 var UserParams = { template:`<h2>我是用户1</h2>`, created(){ // console.log(this.$route); //路由配置信息 // console.log(this.$router); //VueRouter对象 //发送ajax请求 console.log(this.$route.params.userId); // 1 } }; var UserQuery = { template:`<h2>我是用户2</h2>`, created(){ // 发送ajax请求 console.log(this.$route.query.userId); // 2 } }; // 3. 创建一个路由对象 var router = new VueRouter({ // 配置路由对象 routes:[ { // 路由范式一:xxx.html#/user/1 path:'/user/:userId', name:'userp', component:UserParams, }, { // 路由范式二:xxx.html#/user?userId=1 path:'/user', name:'userq', component:UserQuery, }, ] }); //4. 创建Vue对象 var App={ template:`<div> <button type="button" @click="paramsHandler">用户1</button> <button type="button" @click="queryHandler">用户2</button> <div id="view"> <router-view></router-view> </div> </div>`, methods:{ paramsHandler(){ this.$router.push({ name: 'userp', params: { userId: '1' }}) }, queryHandler(){ this.$router.push({ name: 'userq', query: { userId: '2' }}) } } }; new Vue({ el:'#app', template:`<App />`, components:{ App }, router, //要让vue使用router }) </script> </body>
50-51、嵌套路由的使用及警告处理
嵌套路由:
一个router-view里面包含另一个router-view
例如:一个导航按钮点开,里面有子导航按钮
而且子导航按钮,各自打开的结构还不一样(不能用数据驱动视图)就要用到嵌套路由
<body> <div id="app"> </div> <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script> <!--1. 引入vue-router对象 全局的VueRouter对象--> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> // 2. 让Vue使用该VueRouter创建 Vue.use(VueRouter); /* 嵌套路由: 需求:进入首页之后 点击音乐/home/music 电影/home/movie 加载两个不同的组件 */ var Home = { template:`<div> <router-link to="/home/music">音乐</router-link> <router-link to="/home/movie">电影</router-link> <router-view></router-view> </div>`, }; var Music = { template:`<p>我是音乐</p>` }; var Movie = { template:`<p>我是电影</p>` }; // 3. 创建一个路由对象 var router = new VueRouter({ routes:[ { path:'/', // redirect:{name:'home'} redirect:'/home' }, //默认跳转到/home { path:'/home', // name:'home', //如果有这个会报警告,如果父路由有子路由时,父路由最好不要弄命名路由 component:Home, //动态路由匹配 表示你的子组件中的结构是不同的 children:[ //当访问/home时,Home组件的出口是不会渲染任何内容,这是因为没有匹配到合适的子路由,这样写表示渲染Music组件 { path:'', //表示访问的/home component:Music }, { path:'music', component:Music }, { path:'movie', component:Movie }, ] }, ] }); //4. 创建Vue对象 var App={ template:`<div> <router-link to="/home">首页</router-link> <div id="view"> <router-view></router-view> </div> </div>`, }; new Vue({ el:'#app', template:`<App />`, components:{ App }, router, }) </script> </body>
效果:访问根路径后显示的页面
52、动态路由匹配
动态路由
跟嵌套路由相反,例如:一个导航按钮点开,里面有子导航按钮
而且子导航按钮,各自打开的结构一样,只是数据不同,可以用数据驱动视图,
这时,就要用到动态路由。
--------核心思想-------
[“Android” 链接+ “前端” 链接+其<router-view>] 都放在首页的<router-view>里面,
点击“Android” 或 “前端” 在其<router-view>里共享同一个组件
<body> <div id="app"> </div> <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script> <!--1. 引入vue-router对象 全局的VueRouter对象--> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> // 2. 让Vue使用该VueRouter创建 Vue.use(VueRouter);var Timeline = { template:`<div> <router-link :to="{name:'commonDesc', params:{id:'android'}}">Android</router-link> <router-link :to="{name:'commonDesc', params:{id:'frontend'}}">前端</router-link> <router-view></router-view> </div>` }; var Pins = { template:`<p>我是沸点</p>` }; var CommonDesc = { data(){ return { msg:'', } }, template:`<p>我是一个{{msg}}</p>`, // 当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。 // 因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。 // 复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象 created(){ this.msg = 'android'; }, watch:{ $route(to, from){ // console.log(from); //更新前$route // console.log(to); //更新后$route this.msg = to.params.id; console.log(this.msg); } } }; // 3. 创建一个路由对象 var router = new VueRouter({ routes:[ { path:'/timeline', component:Timeline, children:[ { path:'', component:CommonDesc }, { path:':id', // path:'/timeline/:id', name:'commonDesc', component:CommonDesc }, ] }, { path:'/pins', component:Pins, }, ] }); //4. 创建Vue对象 var App={ template:`<div> <router-link to="/timeline">首页</router-link> <router-link to="/pins">沸点</router-link> <div id="view"> <router-view></router-view> </div> </div>`, }; new Vue({ el:'#app', template:`<App />`, components:{ App }, router, }) </script> </body>
53、keep-alive在路由中的使用
keep-alive的作用是将<router-view>里渲染的内容缓存起来,下次切换的时候直接使用。
keep-alive使用后,生命周期钩子函数中的created mounted 只调用一次, activated和deactivated生效
下面案例中:点击“沸点”, 将字体变红,再点击“首页”,再点回“沸点”,字体颜色依然是红色,就是keep-alive的产生的缓存效果
<body> <div id="app"> </div> <script type="text/javascript" src="./node_modules/vue/dist/vue.js"></script> <!--1. 引入vue-router对象 全局的VueRouter对象--> <script type="text/javascript" src="./node_modules/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> // 2. 让Vue使用该VueRouter创建 Vue.use(VueRouter); var Timeline = { template:`<p>我是首页</p>` }; var Pins = { template:`<p @click="clickHandler">我是沸点</p>`, methods:{ clickHandler(e){ e.target.style.color = 'red'; } } }; // 3. 创建一个路由对象 var router = new VueRouter({ routes:[ { path:'/timeline', component:Timeline, }, { path:'/pins', component:Pins, }, ] }); //4. 创建Vue对象 var App={ template:`<div> <router-link to="/timeline">首页</router-link> <router-link to="/pins">沸点</router-link> <div id="view"> <keep-alive> <router-view></router-view> </keep-alive> </div> </div>`, }; new Vue({ el:'#app', template:`<App />`, components:{ App }, router, }) </script> </body>