一 显示课程列表
需求:当你点击课程,course.vue在 <router-view>渲染,并不需要你进行其他点击,所欲的课程列表直接在前端显示,数据是从数据库拿到的。
补充1:生命周期钩子:mounted
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
1 完成这个功能的vue组件框架
<template>
<ul>
<a v-for="(item,index) in course_list">{{item.name}}
</ul>
</template>
<script>
export default{
name:'xx',
data(){
return{
course_list:[]
}
}
mounted(){
this.func1()
}
methods:{
func1(){
var that = this
this.$axios.request({
}
).then(function(response){
that.course_list = response.data
})
}
}
}
</script>
<style>
</style>
实际代码
Course.vue
<template> <div> <p>{{msg}}</p> <ul> <li v-for="(item,index) in course_list">{{item.id}} {{item.name}}</li> </ul> </div> </template> <script> export default{ name:'course', data(){ return { msg: '这是课程页面', course_list: [] } }, mounted(){ this.initcourse() }, methods:{ initcourse(){ var that = this this.$axios.request({ url:this.$store.state.apilist.course, // 更合理的方式使吧url统一放在vuex中,方便维护。 method:'GET', params:{ //以 127.0.0.1:8000/api/v1/course/?token=gaegaeg3523的样式访问 token:this.$store.state.token, // 因为是get请求,没有请求体,所以没有 data这个key值,与之对应的是有params这个key。 } }).then(function (response) { console.log(response.data,typeof response.data); // 类型是object 对象 that.course_list = response.data }) } } } </script> <style> </style>
页面显示
2 需求 :到了上一步,感觉差不多了。实际上,点击每个课程,都应该跳转到显示每个课程详细信息的页面。
对Course.vue 和 路由的 index.js 进行如下修改。
Course.vue
<template> <div> <p>{{msg}}</p> <ul> <router-link v-for="(item,index) in course_list" :to="{path:'/course/detail/'+item.id}"> {{item.name}}</router-link> <!--这里感觉带冒号是与路由中的数据吻合 --> </ul> </div> </template>
index.js
{ path: '/course/detail/:id', //:id 表示动态的 name: 'coursedetail', component: CourseDetail, },
需求:有个问题,在这个页面中如何获取具体的课程的id。因为要 需要根据具体的id,获取数据库的详细信息。
在CourseDetail.vue中 ,this.$route.params.id 便可以获取到跳转的id值。 这个 'id' 是与index.js中的 :id 是相对应的。 index.js中改为 :xx,在CourseDetail中便是用this.$route.params.xx获取。
剩下的代码就可以完成,后台的路由改动需要注意下。
前端代码
Course.vue
<template> <div> <p>{{msg}}</p> <ul v-for="(item,index) in course_list"> <li> <router-link :to="{path:'/course/detail/'+item.id}"> <div>{{item.name}}</div></router-link> </li> </ul> </div> </template> <script> export default{ name:'course', data(){ return { msg: '这是课程页面', course_list: [] } }, mounted(){ this.initcourse() }, methods:{ initcourse(){ var that = this this.$axios.request({ url:this.$store.state.apilist.course, method:'GET', params:{ token:this.$store.state.token, } }).then(function (response) { console.log(response.data,typeof response.data); that.course_list = response.data }) } } } </script> <style> </style>
Course.vue
<template> <div> <p>{{msg}}</p> 课程id:{{courseid}} 课程:{{detail.name}} 价格:{{detail.price}} 周期:{{detail.period}} </div> </template> <script> export default{ name:'coursedetail', data(){ return { msg: '这是详细的课程信息', courseid:this.$route.params.id, //获取 课程id detail:{} } }, mounted(){ this.coursedetail() }, methods:{ coursedetail(){ let that = this; var url = this.$store.state.apilist.course + this.courseid + '/'; // 拼接 要访问的后台api,一定注意,最后面要加 '/',排错拍了一个多小时。 this.$axios.request({ // url:'http://127.0.0.1:8000/api/v1/course/'+this.$route.params.id, url:url, method:'GET', params:{ token:this.$store.state.token, }, } ).then(function (response) { that.detail = response.data; }) } }, } </script> <style> </style>
后台代码
收获:两个不同的路由,可以走一个视图。因为,url 后面的(d+) 是可以视图的参数 (*args,**kwargs)。在视图中,对args,kwargs进行判断区分即可。
urls.py。
urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/auth/$',views.AuthView.as_view() ), url(r'^(?P<version>[v1|v2]+)/course/$',views.CourseView.as_view() ), url(r'^(?P<version>[v1|v2]+)/course/(?P<pk>d+)/$',views.CourseView.as_view() ), ]
views.py
class CourseView(APIView): def get(self,request,*args,**kwargs): pk = kwargs.get('pk') print(pk) if not pk: ret = [{'id':1,'name':'python基础'}, {'id':2,'name':'面向对象'} ] return Response(ret) else: ret = {'name': 'python基础', 'price': '50', 'period': '180', } return Response(ret)
3 实现每个课程页面有其关联课程。关联课程可以跳转。
思路 1 this.$router.push(),可以实现导航到不同的url。
2 利用 <router-link :to="">的方式实现页面跳转,会有这样一个问题。 api/v1/course/2 --> api/v1/course/3,在浏览器上,路径的url的确会发生改变,但是因为这两个url在vue路由中匹配的是同一个地址,只是 后面的 id不同。这种情况下,页面是不会刷新的,尽管手动刷新是可以的。这不是个好的方法。
3 手动写函数,在函数中,利用router.push()跳转页面。然后,执行 初始化页面的方法。
Course.vue
<template> <div> <p>{{msg}}</p> <p>课程id:{{courseid}}</p> <p> 课程:{{detail.name}}</p> <p>价格:{{detail.price}}</p> <p> 周期:{{detail.period}}</p> 推荐课程: <ul> <li v-for="(item,index) in this.detail.recommend"><a href="" @click="changeurl(item.id)">{{item.name}}</a></li> </ul> </div> </template> <script> export default{ name:'coursedetail', data(){ return { msg: '这是详细的课程信息', courseid:this.$route.params.id, detail:{} } }, mounted(){ this.initcoursedetail() }, methods:{ initcoursedetail(){ let that = this; var url = this.$store.state.apilist.course + this.courseid + '/'; this.$axios.request({ // url:'http://127.0.0.1:8000/api/v1/course/'+this.$route.params.id, url:url, method:'GET', params:{ token:this.$store.state.token, }, } ).then(function (response) { that.detail = response.data; }) }, changeurl(courseid){ this.courseid = courseid; this.$router.push({name:'courseDetail',params:{id:courseid}}); // 注意,name: '',一定要加。是去路由中去找这个名称,反向生成。 this.initcoursedetail() // 初始化页面,拿到当前页面的id,从数据库中取值,666 } }, } </script> <style> </style>
4 路由和视图的逼格更高点
之前的view.py
class CourseView(APIView): def get(self,request,*args,**kwargs): pk = kwargs.get('pk') print(pk) if not pk: ret = [{'id':1,'name':'python基础'}, {'id':2,'name':'面向对象'} ] return Response(ret) else: ret = {'name': 'python基础', 'price': '50', 'period': '180', 'recommend':[{'id':10,'name':'基本数据类型'}], } return Response(ret)
urls.py
urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/auth/$',views.AuthView.as_view() ), url(r'^(?P<version>[v1|v2]+)/course/$',views.CourseView.as_view() ), url(r'^(?P<version>[v1|v2]+)/course/(?P<pk>d+)/$',views.CourseView.as_view() ),
改之后
views.py
class CourseView(GenericViewSet): #继承GenericViewSet def list(self,request,*args,**kwargs): ret = [{'id':1,'name':'python基础'}, {'id':2,'name':'面向对象'} ] return Response(ret) def retrieve(self,request,*args,**kwargs): pk = kwargs.get('pk') ret = {'name': 'python基础', 'price': '50', 'period': '180', 'recommend': [{'id': 10, 'name': '基本数据类型'}], }
urls.py
urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/auth/$',views.AuthView.as_view() ), url(r'^(?P<version>[v1|v2]+)/course/$',views.CourseView.as_view({'get':'list'}) ), url(r'^(?P<version>[v1|v2]+)/course/(?P<pk>d+)/$',views.CourseView.as_view({'get':'retrieve'}) ), ]
这样就不在视图里对情况进行判断,而是通过 最开始的路由分发的时候就做好对应关系,更简洁。
根据url,找到对应的视图,对此url的访问方式不同,依照as_views()后面的对应关系,执行这个视图的不同方法。api/course/ 和 api/course/1/ 是两个不同的url,记住,尽管可以走同一个视图。