目录
一、 路由和传值
当某个组件可以根据某些参数值的不同,展示不同效果时,需要用到动态路由。
例如:访问网站看到课程列表,点击某个课程,就可以跳转到课程详细页面(根据课程ID不同展示不同数据)。
如何来设置动态路由呢?
-
定义路由(可以使用别名定义路由、可以实现动态值)
const router = new VueRouter({
routes: [
{ path: '/', component: Home},
{ path: '/course', component: Course, name: "Course"}
{ path: '/detail/:id', component: Detail, name: "Detail"}
],
})
HTML展示:(前三个就写死了)
<div>
<router-link to="/">首页</router-link>
<router-link to="/course">课程</router-link>
<router-link to="/detail/123">课程</router-link>
<router-link :to="{path:'/course'}">课程</router-link>
<router-link :to="{path:'/course?size=19&page=2'}">课程</router-link>
<router-link :to="{path:'/course', query:{size:19,page:2}">课程</router-link>
<router-link :to="{name:'Course'}">课程</router-link>
<router-link :to="{name:'Course', query:{size:19,page:2} }">课程</router-link>
<router-link :to="{path:'/detail/22',query:{size:123}}">Linux</router-link>
<router-link :to="{name:'Detail',params:{id:3}, query:{size:29}}">网络安全</router-link>
</div>
<h1>内容区域</h1>
<router-view></router-view>
组件获取URL传值和GET参数
const Detail = {
data: function () {
return {
title: "详细页面",
paramDict: null,
queryDict: null,
}
},
created: function () {
this.paramDict = this.$route.params;
this.queryDict = this.$route.query;
// 发送axios请求
},
template: `<div><h2>{{title}}</h2><div>当前请求的数据 {{paramDict}} {{queryDict}}</div></div>`
}
二、案例
结合上面的路由实现案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body {
margin: 0;
}
.container {
width: 1100px;
margin: 0 auto;
}
.menu {
height: 48px;
background-color: #499ef3;
line-height: 48px;
}
.menu a {
color: white;
text-decoration: none;
padding: 0 10px;
}
.course-list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.course-list .item {
width: 248px;
padding: 10px;
border: 1px solid #dddddd;
margin-right: 5px;
margin-top: 10px;
}
.course-list .item img {
width: 100%;
height: 120px;
}
</style>
<script src="./js/vue.min.js"></script>
<script src="./js/vue-router.js"></script>
<script src="./js/axios.min.js"></script>
</head>
<body>
<div id="app">
<div class="menu">
<div class="container">
<router-link to="/">申请入会</router-link>
<router-link to="/home">首页</router-link>
<router-link to="/course">写真</router-link>
<router-link to="/news">资讯</router-link>
</div>
</div>
<div class="container">
<router-view></router-view>
</div>
</div>
<script>
const Home = {
data: function () {
return {
title: "欢迎进入交友平台"
}
},
template: `<h2>{{title}}</h2>`
}
const Course = {
data: function () {
return {
courseList: []
}
},
created: function () {
/* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
- 可以去操作组件对象,例如:this.courseList = [11,22,33]
- 不可以去操作DOM,例如:document.getElementById (未创建)
*/
axios({
method: "get",
url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=0',
headers: {
"Content-Type": "application/json"
}
}).then((res) => {
this.courseList = res.data.data.result;
})
},
mounted: function () {
/* DOM对象已在页面上生成,此时就可以 */
},
template: `
<div class="course-list">
<div class="item" v-for="item in courseList">
<router-link :to="{name:'Detail',params:{id:item.id}}">
<img :src="item.cover" alt="">
<a>{{item.name}}</a>
</router-link>
</div>
</div>`
}
const News = {
data: function () {
return {
dataList: []
}
},
created: function () {
/* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
- 可以去操作组件对象,例如:this.courseList = [11,22,33]
- 不可以去操作DOM,例如:document.getElementById (未创建)
*/
axios({
method: "get",
url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=10',
headers: {
"Content-Type": "application/json"
}
}).then((res) => {
this.dataList = res.data.data.result;
})
},
template: `<ul><li v-for="item in dataList">{{item.name}}</li></ul>`
}
const Detail = {
data: function () {
return {
title: "详细页面",
courseId: null
}
},
created: function () {
this.courseId = this.$route.params.id;
// 此处可以根据课程ID,发送ajax请求获取课程详细信息
},
template: `<div><h2>课程详细页面</h2><div>当前课程ID为:{{courseId}}</div></div>`
}
const router = new VueRouter({
routes: [
{path: '/', component: Home},
{path: '/home', component: Home},
{path: '/course', component: Course},
{path: '/news', component: News},
{path: '/detail/:id', component: Detail, name: 'Detail'}
],
//mode: 'history'
})
var app = new Vue({
el: '#app',
data: {},
methods: {},
router: router
})
</script>
</body>
</html>
三、案例存在无法刷新问题
上述编写案例是没有问题,但如果在开发中会涉及到 同一个路由的跳转(默认不会重新加载页面,数据无法获取)。
例如:在详细页面再出现一个课程推荐,即:在课程详细,点击推荐的课程后跳转到课程详细页面(课程ID不同),此时课程的ID还是原来加载的ID,无法获取推荐课程的ID。
如何解决呢?
在课程详细的组件中设置watch属性即可,watch会监测$route
值,一旦发生变化,就执行相应的函数。
const Detail = {
data: function () {
return {
title: "详细页面",
courseId: null,
}
},
created: function () {
this.courseId = this.$route.params.id;
this.getCourseDetail();
},
watch: {
$route:function(to, from) {
this.courseId = to.params.id;
// this.getCourseDetail();
}
},
methods: {
getCourseDetail: function () {
// 根据this.courseId获取课程详细信息
}
},
template: `<div><h2>{{title}}</h2><div>当前请求的数据 {{paramDict}} {{queryDict}}</div></div>`
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body {
margin: 0;
}
.container {
width: 1100px;
margin: 0 auto;
}
.menu {
height: 48px;
background-color: #499ef3;
line-height: 48px;
}
.menu a {
color: white;
text-decoration: none;
padding: 0 10px;
}
.course-list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.course-list .item {
width: 248px;
padding: 10px;
border: 1px solid #dddddd;
margin-right: 5px;
margin-top: 10px;
}
.course-list .item img {
width: 100%;
height: 120px;
}
</style>
<script src="./js/vue.min.js"></script>
<script src="./js/vue-router.js"></script>
<script src="./js/axios.min.js"></script>
</head>
<body>
<div id="app">
<div class="menu">
<div class="container">
<router-link to="/">路飞学城</router-link>
<router-link to="/home">首页</router-link>
<router-link to="/course">课程</router-link>
<router-link to="/news">资讯</router-link>
</div>
</div>
<div class="container">
<router-view></router-view>
</div>
</div>
<script>
const Home = {
data: function () {
return {
title: "欢迎使用路飞学城"
}
},
template: `<h2>{{title}}</h2>`
}
const Course = {
data: function () {
return {
courseList: []
}
},
created: function () {
/* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
- 可以去操作组件对象,例如:this.courseList = [11,22,33]
- 不可以去操作DOM,例如:document.getElementById (未创建)
*/
axios({
method: "get",
url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=0',
headers: {
"Content-Type": "application/json"
}
}).then((res) => {
this.courseList = res.data.data.result;
})
},
mounted: function () {
/* DOM对象已在页面上生成,此时就可以 */
},
template: `
<div class="course-list">
<div class="item" v-for="item in courseList">
<router-link :to="{name:'Detail',params:{id:item.id}}">
<img :src="item.cover" alt="">
<a>{{item.name}}</a>
</router-link>
</div>
</div>`
}
const News = {
data: function () {
return {
dataList: []
}
},
created: function () {
/* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
- 可以去操作组件对象,例如:this.courseList = [11,22,33]
- 不可以去操作DOM,例如:document.getElementById (未创建)
*/
axios({
method: "get",
url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=10',
headers: {
"Content-Type": "application/json"
}
}).then((res) => {
this.dataList = res.data.data.result;
})
},
template: `<ul><li v-for="item in dataList">{{item.name}}</li></ul>`
}
const Detail = {
data: function () {
return {
title: "详细页面",
courseId: null,
hotCourseList: [
{id: 1000, title: "python全栈开发"},
{id: 2000, title: "异步编程"},
],
}
},
created: function () {
this.courseId = this.$route.params.id;
// 此处可以根据课程ID,发送ajax请求获取课程详细信息
this.getCourseDetail();
},
watch: {
$route: function (to, from) {
this.courseId = to.params.id;
this.getCourseDetail();
}
},
methods: {
getCourseDetail: function () {
// 根据this.courseId获取课程详细信息
}
},
template: `
<div>
<h2>课程详细页面</h2>
<div>当前课程ID为:{{courseId}}</div>
<h3>课程推荐</h3>
<ul>
<li v-for="item in hotCourseList">
<router-link :to="{name:'Detail', params:{id:item.id}}">{{item.title}}</router-link>
</li>
</ul>
</div>`
}
const router = new VueRouter({
routes: [
{path: '/', component: Home},
{path: '/home', component: Home},
{path: '/course', component: Course},
{path: '/news', component: News},
{path: '/detail:id', component: Detail, name: 'Detail'}
],
//mode: 'history'
})
var app = new Vue({
el: '#app',
data: {},
methods: {},
router: router
})
</script>
</body>
</html>