1.1.Vue路由基础
Vue属于单页应用(SPA),即整个应用程序中只有一个html页面。
在单页应用中(SPA),由于只是更改DOM来模拟多页面,所以页面浏览历史记录的功能就丧失了。此时,就需要前端路由来实现浏览历史记录的功能。
<div id="app">
<p>
<!-- 使用 router-link 组件来导航. to属性指定导航地址-->
<router-link to="/home">home</router-link>
<router-link to="/news">news</router-link>
</p>
<!-- 路由出口(路由匹配到的组件将渲染在这里) -->
<router-view></router-view>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
// 1. 定义(路由)组件。
const Home = {
template: '<div>首页</div>'
}
const News = {
template: '<div>新闻</div>'
}
// 2. 定义路由规则对象(每个路由应该映射一个组件)
const routes = [
{
path: '/home',
component: Home
},{
path: '/news',
component: News
}
]
// 3. 创建 router 实例,然后传 `routes` 配置
const router = new VueRouter({
//如果路由规则对象名也为routes,那么就可以简写为 routes
routes:routes
})
// 4. 将路由对象挂载到Vue实例上
// 通过 router 配置参数注入路由,从而让整个应用都有路由功能
var vm = new Vue({
el: '#app',
data: {},
// 将路由添加到Vue中
router
})
</script>
注意: 上面代码中,router-link标签默认会被渲染成一个a标签
路由重定向:上面代码中,我们应该设置打开浏览器就默认调整到 “首页”,所以需要把根路由/重定向到/home。 修改路由配置:
// 2. 定义路由规则对象(每个路由应该映射一个组件)
const routes = [
{
path: '/', //根路由
redirect: '/home' //把根路由重定向到home
},{
path: '/home',
component: Home
},{
path: '/news',
component: News
}
]
1.2.嵌套路由
实际应用界面,通常由多层嵌套的组件组合而成。 比如,我们 “首页”组件中,还嵌套着 “登录”和 “注册”组件,那么URL对应就是/home/login和/home/reg。
<div id="app">
<p>
<!-- 使用 router-link 组件来导航. to属性指定导航地址-->
<router-link to="/home">home</router-link>
<router-link to="/news">news</router-link>
</p>
<!-- 路由出口(路由匹配到的组件将渲染在这里) -->
<router-view></router-view>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
// 1. 定义(路由)组件。
const Home = {
template: `<div>
<h2>首页</h2>
<router-link to="/home/login">登录</router-link>
<router-link to="/home/reg">注册</router-link>
<router-view></router-view>
</div>`
}
const News = {
template: '<div>新闻</div>'
}
const Login = {
template: '<div>登陆</div>'
}
const Reg = {
template: '<div>注册</div>'
}
// 2. 定义路由规则对象(每个路由应该映射一个组件)
const routes = [
{
path: '/', //根路由
redirect: '/home' //把根路由重定向到home
},{
path: '/home',
component: Home,
children: [ //配置子路由
{
path: '/home',
redirect: '/home/login'
},{
path: '/home/login',
component: Login
},{
path: '/home/reg',
component: Reg
}
]
}, {
path: '/news',
component: News
},
]
// 3. 创建 router 实例,然后传 `routes` 配置
const router = new VueRouter({
//如果路由规则对象名也为routes,那么就可以简写为 routes
routes: routes
})
// 4. 将路由对象挂载到Vue实例上
// 通过 router 配置参数注入路由,从而让整个应用都有路由功能
var vm = new Vue({
el: '#app',
data: {},
// 将路由添加到Vue中
router
})
</script>
1.3.路由传参
路由传参有多种方式,这里我们学习两种:params与query。
1.3.1.params形式传参
<div id="app">
<p>
<router-link :to="{name:'Home',params:{msg:'hello world!'}}">home</router-link>
<router-link :to="{name:'News',params:{id:id,name:name}}">news</router-link>
</p>
<router-view></router-view>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
const Home = {
template: '<div>{{$route.params.msg}},首页</div>'
}
const News = {
template: `<div>新闻;
参数1:{{$route.params.id}}
参数2:{{$route.params.name}}
</div>`
}
const routes = [{
path: '/home',
name:'Home', //每个路由规则中必须要有一个name属性
component: Home
}, {
path: '/news',
name:'News',
component: News
}]
const router = new VueRouter({
routes
})
var vm = new Vue({
el: '#app',
data: {
id:1,
name:'zhangsan'
},
router
})
</script>
注意:
- 使用v-bind绑定to属性。
- to属性的值是一个json对象,此对象有两个属性:name属性和params属性。
- name属性就是要路由的对象。所以,在路由规则列表中,每一个路由规则都应用有一个name值。
- params属性就是要传递的参数。也是一个json对象。
- 组件接收参数时,使用 this.$route.params.参数名 的形式。
1.3.2.query形式传参
<div id="app">
<p>
<router-link :to="{path:'/home',query:{msg:'hello world!'}}">home</router-link>
<router-link :to="{path:'/news',query:{id:id,name:name}}">news</router-link>
</p>
<router-view></router-view>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
const Home = {
template: '<div>{{$route.query.msg}},首页</div>'
}
const News = {
template: `<div>新闻;
参数1:{{$route.query.id}}
参数2:{{$route.query.name}}
</div>`
}
const routes = [{
path: '/home',
component: Home
}, {
path: '/news',
component: News
}]
const router = new VueRouter({
routes
})
var vm = new Vue({
el: '#app',
data: {
id:1,
name:'zhangsan'
},
router
})
</script>
注意:
- to属性的值仍然是一个josn对象,但是两个属性变了,一个是path,一个是query。
- path属性就是路由地址,对应路由规则中的path值。
- query属性就是要传递的参数。也是一个json对象。
- 组件接收参数时,使用 this.$route.query.参数名 的形式。
1.3.3.params方式与query方式的区别
query方式传值:
params方式传值:
总结:params方式与query方式的区别:
- query方式:
类似于get方式,参数会在路由中显示,可以用做刷新后仍然存在的参数。
利用路由规则中的path跳转。- params方式:
类似于post方式,参数不会在路由中显示,页面刷新后参数将不存在。
利用路由规则中的name跳转。
2.编程式路由
2.1.利用JS实现路由跳转
router-link标签可以实现页面超链接形式的路由跳转。但是实际开发中,在很多情况下,需要通过某些逻辑判断来确定如何进行路由跳转。也就是说:需要在js代码中进行路由跳转。此时可以使用编程式路由。
- 使用this.$router.push方法可以实现路由跳转,方法的第一个参数可为string类型的路径,或者可以通过对象将相应参数传入。
- 通过this.$router.go(n)方法可以实现路由的前进后退,n表示跳转的个数,正数表示前进,负数表示后退。
如果只想实现前进后退可以使用this.$router.forward()(前进一页),以及this.$router.back()(后退一页)。
<div id="app"> <p> <button @click="toHome">首页</button> <button @click="toNews">新闻</button> <button @click="toLogin">登陆</button> <button @click="doForward1">前进</button> <button @click="doForward2">前进</button> <button @click="doBack1">后退</button> <button @click="doBack2">后退</button> </p> <router-view></router-view> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> const Home = { template: '<div>首页</div>' } const News = { template: '<div>新闻:{{$route.query.name}}</div>' } const Login = { template: '<div>登陆</div>' } const routes = [{ path: '/', component: Home }, { path: '/home', component: Home }, { path: '/news', component: News }, { path: '/login', component: Login }] const router = new VueRouter({ routes }) var vm = new Vue({ el: '#app', data: {}, router, methods:{ toHome(){ //无参数时,push方法中直接写路由地址 this.$router.push('/home'); }, toNews(){ //有参数时,push方法中写一个json对象 this.$router.push({path:'/news',query:{name:'zhangsan'}}); }, toLogin(){ this.$router.push('/login'); }, doForward1(){ this.$router.forward(); }, doForward2(){ this.$router.go(1); }, doBack1(){ this.$router.back(); }, doBack2(){ this.$router.go(-1); } } }) </script>
2.2.通过watch实现路由监听
通过watch属性设置监听$route变化,达到监听路由跳转的目的。
在上面代码中添加watch监听:watch: { // 监听路由跳转。 $route(newRoute, oldRoute) { console.log('watch', newRoute, oldRoute) } }
2.3.导航守卫
路由跳转前做一些验证,比如登录验证,是网站中的普遍需求。 对此,vue-route 提供了实现导航守卫(navigation-guards)的功能。
你可以使用 router.beforeEach 注册一个全局前置守卫:const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })
每个守卫方法接收三个参数:
to:即将要进入的目标路由对象(去哪里),可以使用 to.path 获取即将要进入路由地址。
- from:当前导航正要离开的路由对象(从哪来),可以使用 from.path 获取正要离开的路由地址。
- next:一个函数,表示继续执行下一个路由。(如果没有next,将不会进入到下一个路由)
下面例子中实现了如下功能:
- 列举需要判断登录状态的 “路由集合”,当跳转至集合中的路由时,如果“未登录状态”,则跳转到登录页面
- 当直接进入登录页面LoginPage时,如果“已登录状态”,则跳转到首页HomePage;
<div id="box"> <p> <router-link to="/home">home</router-link> <router-link to="/news">news</router-link> <router-link to="/music">music</router-link> <router-link to="/login">login</router-link> </p> <router-view></router-view> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue-router/dist/vue-router.js"></script> <script type="text/javascript"> const Home = { template: '<div>首页</div>' } const News = { template: '<div>新闻</div>' } const Music = { template: '<div>音乐</div>' } const Login = { template: '<div>登录</div>' } const routes = [{ path: '/', component: Home }, { path: '/home', component: Home }, { path: '/news', component: News }, { path: '/music', component: Music }, { path: '/login', component: Login }] const router = new VueRouter({ routes // (缩写)相当于 routes: routes }) var vm = new Vue({ el: '#box', data: {}, router }) // 添加全局路由守卫 router.beforeEach((to, from, next) => { //创建守卫规则集合(这里表示'/news'与'/music'路径是需要权限验证的) const nextRoute = ['/news', '/music']; // 使用isLogin来模拟是否登录 let isLogin = false; // 判断to.path(要跳转的路径)是否是需要权限验证的 if (nextRoute.indexOf(to.path) >= 0) { if (!isLogin) { router.push({ path: '/login' }) location.reload(); //必须要有 } } // 已登录状态;当路由到login时,跳转至home if (to.path === '/login') { if (isLogin) { router.push({ path: '/home' }); location.reload(); } } next(); //必须要有 }); </script>
1、模拟一个在线书店后台管理系统,实现如下需求:
课后作业
1)该系统有登录页面和书籍管理界面,两个页面需要分别封装为组件
2)利用路由实现登录后切换至书籍管理界面
3)在主界面上可以呈现全部书籍、增加书籍、删除书籍。
4)书籍信息包括书籍编号、书籍名称、书籍价格。提示:涉及组件、路由、数据绑定等知识综合使用。
2、参考万圣节抽灵符游戏原生JS代码,综合利用到路由、组件、路由传参、style样式绑定等知识进行代码重构实现游戏界面切换、点击怪物图片抽取灵符等游戏功能。