效果如下:
前言
更新视图但不重新请求页面,是前端路由原理的核心之一。接下来实现一个简单嵌套路由的功能,并贴上代码。准备工作请参考前面几篇博客。共有五个路由组件,分别为:About.vue、Home.vue、News.vue、Message.vue、MessageDetail.vue。
其中App是根组件,包括About.vue和Home.vue两个路由组件,而Home组件又包括News.vue和Message.vue两个路由组件。在Message.vue组件中,使用按钮进行编程式导航,即页面跳转由点击按钮来实现。
一、目录
这个嵌套路由共包括如下目录文件
二、步骤
main.js
main.js是主入口文件,引入了vue框架,根组件,路由插件,并定义了vue的实例
代码如下:
/*
入口JS
*/
import Vue from 'vue'
import App from './App.vue'
import router from './router'
/* eslint-disable no-new */
new Vue({
el: '#app',
components: {App}, // 映射组件标签
template: '<App/>', // 指定需要渲染到页面的模板
router // 注册路由器
})
index.html
index.html可以理解为一个web页面容器,挂载main.js定义的根节点,内容由组件填充。
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>vue_demo</title>
<script>
</script>
<script src="src/main.js"></script>
</head>
<style>
.router-link-active{
color: red !important;
}
</style>
<body>
<div id="app"></div>
</body>
</html>
App.vue
App.vue是根组件,组件标签需要导入此页面
<template>
<div>
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header"><h2>Router Test</h2></div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!--生成路由链接-->
<router-link to="/about" class="list-group-item">About</router-link>
<router-link to="/home" class="list-group-item">Home</router-link>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!--显示当前组件-->
<keep-alive>
<router-view msg="abc"></router-view>
</keep-alive>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {}
</script>
<style>
</style>
index.js
index.js位于router(路由器)文件夹下,用来注册应用中所有的路由
/*
路由器对象模块
*/
import Vue from 'vue'
import VueRouter from 'vue-router'
import About from '../pages/About.vue'
import Home from '../pages/Home.vue'
import News from '../pages/News.vue'
import Message from '../pages/Message.vue'
import MessageDetail from '../pages/MessageDetail.vue'
// 声明使用vue-router插件
/*
内部定义并注册了2个组件标签(router-link/router-view),
给组件对象添加了2个属性:
1. $router: 路由器
2. $route: 当前路由
*/
Vue.use(VueRouter)
export default new VueRouter ({
// 注册应用中所有的路由
routes: [
{
path: '/about',
component: About
},
{
path: '/home',
component: Home,
children: [
{
path: '/home/news',
component: News
},
{
path: 'message',
component: Message,
children: [
{
path:'detail/:id',// 占位写法
component: MessageDetail
}
]
},
{
path: '',
redirect: '/home/news'
}
]
},
{
path: '/',
redirect: '/about'
}
]
})
五个路由组件
五个路由组件都放在一个文件page里.
- About.vue
<template>
<div>
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header"><h2>Router Test</h2></div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!--生成路由链接-->
<router-link to="/about" class="list-group-item">About</router-link>
<router-link to="/home" class="list-group-item">Home</router-link>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!--显示当前组件-->
<keep-alive>
<router-view msg="abc"></router-view>
</keep-alive>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {}
</script>
<style>
</style>
- Home.vue
<template>
<div>
<h2>Home</h2>
<div>
<ul class="nav nav-tabs">
<li><router-link to="/home/news">News</router-link></li>
<li><router-link to="/home/message">Message</router-link></li>
</ul>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {}
</script>
<style>
</style>
- News.vue
<template>
<ul>
<li v-for="(news, index) in newsArr" :key="index">{{news}}</li>
</ul>
</template>
<script>
export default {
data () {
return {
newsArr: ['News001', 'News002', 'News003']
}
}
}
</script>
<style>
</style>
- Message.vue
<template>
<div>
<ul>
<li v-for="m in messages" :key="m.id">
<router-link :to="`/home/message/detail/${m.id}`">{{m.title}}</router-link>
<button @click="pushShow(m.id)">push查看</button>
<button @click="replaceShow(m.id)">replace查看</button>
</li>
</ul>
<button @click="$router.back()">回退</button>
<hr>
<router-view></router-view>
</div>
</template>
<!--//$route代表当前的路由组件,$router代表当前路由器-->
<script>
export default {
data () {
return {
messages: [
/* {id: 1, title: 'Message001'},
{id: 3, title: 'Message003'},
{id: 5, title: 'Message005'}*/
]
}
},
mounted () {
setTimeout(() => {
const messages = [
{id: 1, title: 'Message001'},
{id: 3, title: 'Message003'},
{id: 5, title: 'Message005'}
]
this.messages = messages
}, 1000)
},
methods: {
//用按钮实现路由链接跳转,push和replace都可实现,但按push,再按回退键会回上一步链接,
// 而replace,会回退到上一级链接
pushShow (id) {
this.$router.push(`/home/message/detail/${id}`)
},
replaceShow(id) {
this.$router.replace(`/home/message/detail/${id}`)
}
}
}
</script>
<style>
</style>
- MessageDetail.vue
<template>
<ul>
<!--//$route代表当前的路由组件,$router代表当前路由器-->
<li>id: {{$route.params.id}}</li>
<li>title: {{detail.title}}</li>
<li>content: {{detail.content}}</li>
</ul>
</template>
<script>
const messageDetails = [
{id: 1, title: 'Message001', content: 'message content00111....'},
{id: 3, title: 'Message003', content: 'message content00222....'},
{id: 5, title: 'Message005', content: 'message content00333....'}
]
export default {
data() {
return {
detail: {}
}
},
mounted () {// 改变当前路由组件参数数据时, 不会重新创建组件对象, mounted不会重新执行
const id = this.$route.params.id
this.detail = messageDetails.find(detail => detail.id===id*1)
},
watch: {
$route: function () { // 改变当前路由组件参数数据时自动调用
console.log('$route()')
const id = this.$route.params.id
this.detail = messageDetails.find(detail => detail.id===id*1)
}
}
}
</script>
<style>
</style>