Vue+restfulframework示例

一、vue

vue前端框架:

修改源:
    npm config set registry https://registry.npm.taobao.org 

创建脚手架:
    vue init webpack Vue项目名称
    #记得把route的这个设置为yes,其他的设置为no 比如: Install vue-router? Yes
    

插件:
    axios,发送Ajax请求
    vuex,保存所有组件共用的变量
    vue-cookies,操作cookie
    

二、流程详细

1、创建脚手架

#可以用淘宝源来下载,这样下载的快
npm config set registry https://registry.npm.taobao.org
vue init webpack
#把route的那一个设置为yes,其他的设置为no

2、运行

cd Vue项目名称 
npm run dev

3、显示组件

# 用于点击查看组件
<router-link to="/index">首页</router-link>
                
# 组件显示的位置
<router-view/>

4、写路由

 1 import Vue from 'vue'
 2 import Router from 'vue-router'
 3 import Index from '@/components/Index'
 4 import Login from '@/components/Login'
 5 import Course from '@/components/Course'
 6 import Micro from '@/components/Micro'
 7 import News from '@/components/News'
 8 import CourseDetail from '@/components/CourseDetail'
 9 import NotFound from '@/components/NotFound'
10 
11 Vue.use(Router)
12 
13 export default new Router({
14   routes: [
15     {
16       path: '/',
17       name: 'index',
18       component: Index
19     },
20     {
21       path: '/index',
22       name: 'index',
23       component: Index
24     },
25     {
26       path: '/course',
27       name: 'course',
28       component: Course
29     },
30     {
31       path: '/course-detail/:id/',
32       name: 'courseDetail',
33       component: CourseDetail
34     },
35     {
36       path: '/micro',
37       name: 'micro',
38       component: Micro
39     },
40     {
41       path: '/news',
42       name: 'news',
43       component: News
44     },
45     {
46       path: '/login',
47       name: 'login',
48       component: Login
49     },
50     {
51       path: '*',
52       component: NotFound
53     }
54   ],
55   mode: 'history'
56 })
View Code
 1 # 定义路由
 2                     {
 3                       path: '/course-detail/:id/',
 4                       name: 'courseDetail',
 5                       component: CourseDetail
 6                     },
 7                     {
 8                       path: '/login',
 9                       name: 'login',
10                       component: Login
11                     },
12                     {
13                       path: '*',
14                       component: NotFound
15                     }
16                 
17                 
18                 # router-link参数
19                     <router-link :to="{'path':'/course-detail/'+item.id }">{{item.name}}</router-link>
20                     <router-link to="/index">首页</router-link>
21     
22                 # 获取传过来的参数
23                     this.$route.params.id
24                 # 重定向
25                     this.$router.push('/index')
26                 
View Code

注意:

如果不想在url显示#,可以在路由里面加上这样一个参数

  mode: 'history'

5、写组件

 1 <template>
 2 
 3   <div>
 4     <h1>登录页面</h1>
 5     <div>
 6       <input type="text" v-model="username" placeholder="用户名">
 7       <input type="text" v-model="password" placeholder="密码">
 8       <a @click="doLogin">提交</a>
 9     </div>
10   </div>
11 </template>
12 
13 <script>
14 
15 export default {
16   # 定义局部字段
17   data () {
18     return {
19       username: '',
20       password: ''
21     }
22   },
23   # 加载时执行
24   mounted:function(){
25   },
26   # 定义局部方法
27   methods:{
28     doLogin() {
29       var that = this
30       this.$axios.request({
31         url: 'http://127.0.0.1:8000/login/',
32         method: 'POST',
33         data: {
34           username: this.username,
35           password: this.password
36         },
37         responseType: 'json'
38       }).then(function (response) {
39         console.log(response.data)
40         // 找到全局变量,把用户名和token赋值到其中。
41         that.$store.commit('saveToken',response.data)
42         // 重定向到index
43         that.$router.push('/index')
44       })
45     }
46   }
47 }
48 </script>
49 
50 <!-- Add "scoped" attribute to limit CSS to this component only -->
51 <style scoped>
52 
53 </style>
View Code

6、发送ajax请求:axios

#发送ajax请求需要安装axios组件
npm install axios
 1 npm install axios
 2 
 3 main.js 
 4     import Vue from 'vue'
 5     import App from './App'
 6     import router from './router'
 7     
 8     import axios from 'axios'
 9     
10     Vue.prototype.$axios = axios
11 
12     Vue.config.productionTip = false
13     ...
14 
15 组件使用:
16     this.$axios.request({
17     url: 'http://127.0.0.1:8000/login/',
18     method: 'POST',
19     data: {
20       username: this.username,
21       password: this.password
22     },
23     responseType: 'json'
24   }).then(function (response) {
25     console.log(response.data)
26     
27     that.$router.push('/index')
28   })
29 
30 PS:重定向 that.$router.push('/index')
View Code

7、vuex:保存所有组件共用的变量

安装  
npm install vuex

 如果想用vuex需要做这么几件事:

  • a、先创建一个文件夹,store----store.js
  • b、要先使用就先导入
  • c、实例化一个对象,并且让别人可以用
  • d、这样每一个组件都可以用username和token了
 1 npm install vuex 
 2 
 3 main.js 
 4 import Vue from 'vue'
 5 import App from './App'
 6 import router from './router'
 7 import axios from 'axios'
 8 
 9 import store from './store/store'    # vuex
10 
11 Vue.prototype.$axios = axios
12 
13 Vue.config.productionTip = false
14 
15 /* eslint-disable no-new */
16 new Vue({
17   el: '#app',
18   store,                            # vuex
19   router,
20   components: { App },
21   template: '<App/>'
22 })
23 
24 src/store/store.js
25 import Vue from 'vue'
26 import Vuex from 'vuex'
27 import Cookie from 'vue-cookies'
28 
29 Vue.use(Vuex)
30 
31 export default new Vuex.Store({
32   // 组件中通过 this.$store.state.username 调用
33   state: {
34     username: Cookie.get('username'),
35     token: Cookie.get('token')
36   },
37   mutations: {
38     // 组件中通过 this.$store.commit(参数)  调用
39     saveToken: function (state, data) {
40       state.username = data.username
41       state.token = data.token
42       Cookie.set('username', data.username, '20min')
43       Cookie.set('token', data.token, '20min')
44 
45     },
46     clearToken: function (state) {
47       state.username = null
48       state.token = null
49       Cookie.remove('username')
50       Cookie.remove('token')
51     }
52   }
53 })
View Code

8、vue-cookies:操作cookie

安装
npm install vue-cookies
 1 npm install vue-cookies 
 2 
 3 
 4 Cookie.get('username')
 5 
 6 Cookie.set('username', data.username, '20min')
 7 Cookie.remove('username')
 8 
 9 
10 src/store/store.js
11 import Vue from 'vue'
12 import Vuex from 'vuex'
13 import Cookie from 'vue-cookies'    # vue-cookies
14 
15 Vue.use(Vuex)
16 
17 export default new Vuex.Store({
18   // 组件中通过 this.$store.state.username 调用
19   state: {
20     username: Cookie.get('username'),    # vue-cookies
21     token: Cookie.get('token')            # vue-cookies
22   },
23   mutations: {
24     // 组件中通过 this.$store.commit(参数)  调用
25     saveToken: function (state, data) {
26       state.username = data.username
27       state.token = data.token
28       Cookie.set('username', data.username, '20min')    # vue-cookies
29       Cookie.set('token', data.token, '20min')    
30 
31     },
32     clearToken: function (state) {
33       state.username = null
34       state.token = null
35       Cookie.remove('username')    # vue-cookies
36       Cookie.remove('token')
37     }
38   }
39 })
View Code

三、代码实现

 前端代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="stylesheet" href="./static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <script src="./static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>

    <title>s6vue</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>
index.html
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/store'  //
import axios from 'axios'    // 要是用axios,就得先导入
Vue.prototype.$axios = axios  //注册,以后就可以用$axios来定义了

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  router,
  components: { App },
  template: '<App/>'
})
main.js
<template>
  <div id="app">
    <!--首页里面永远是固定的东西-->
    <ul class="nav nav-tabs">
      <li><router-link to="/index">首页</router-link>  <!--用于点击查看组件--></li>
      <li><router-link to="/micro">学位课</router-link>  <!--用于点击查看组件--></li>
      <li><router-link to="/course">课程</router-link></li>  <!--用于点击查看组件-->
      <li><router-link to="/news">深科技</router-link></li>  <!--用于点击查看组件-->
      <!--如果已经登录了,就不用在登录了,在页面还是显示当前用户和注销,如果没有登录就显示登录-->
      <li v-if="this.$store.state.username">
        <span><a>欢迎{{ this.$store.state.username }}登录</a></span>
        <span><a @click="logout()">注销</a></span>
      </li>
      <li v-else=""> <router-link to="/login">登录</router-link></li>
    </ul>
   <router-view/>  <!--组件显示的位置-->
  </div>
</template>

<script>
export default {
  name: 'App',
  methods:{
    logout(){
      this.$store.state.username=''
      this.$store.state.token=''
    }
  }
}
</script>

<style>


</style>
app.vue
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Index from '@/components/Index'
import Login from '@/components/Login'
import Micro from '@/components/Micro'
import News from '@/components/News'
import Course from '@/components/Course'
import CourseDetail from '@/components/CourseDetail'
import NotFound from '@/components/NotFound'



Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/index',
      name: 'index',
      component: Index
    },
     {
      path: '/login',
      name: 'Login',
      component: Login
    },
     {
      path: '/course',
      name: 'Course',
      component: Course
    },
     {
      path: '/course-detail/:id/',
      name: 'CourseDetail',
      component: CourseDetail
    },
     {
      path: '/micro/',
      name: 'Micro',
      component: Micro
    },
    {
      path: '/course-detail/:id/',
      name: 'CourseDetail',
      component: CourseDetail
    },
     {
      path: '/news/',
      name: 'News',
      component: News
    },
    {
      path: '*',
      component: NotFound
    }
  ],
  mode:'history'
})
router ---index.js

组件components

<template>
  <div class="hello">
      <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'index',
  data () {
    return {
      msg:"这里是首页"
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>

</style>
Index.vue
<template>
  <div class="">
    <h2>登录页面</h2>
    <p>用户名:<input type="text" placeholder="username" v-model="username"></p>
    <p>密码:<input type="text" placeholder="password" v-model="password"></p>
    <button><a @click="DoLogin()">提交</a></button>
  </div>
</template>

<script>
export default {
  name: 'index',
  data () {
    return {
      username: "",
      password: ""
    }
  },
    methods:{
      DoLogin (){
          var that = this
//          console.log(this.$axios);
          this.$axios.request({  //发送axios请求
            url:'http://127.0.0.1:8082/login/', //请求路径
            method:"POST",//请求方式
            data:{   //要发送 的数据
              username:this.username,
              password:this.password
            },
            responseType:'json'  //期望返回的类型是json的格式
          }).then(function (response) {  //把返回的结果交给回调函数处理
            //登录成功之后,找到全局变量,把用户名和token赋值到其中
            that.$store.commit('saveToken',response.data);
            //重定向(登录成功之后让跳转到index页面)
              that.$router.push('/index')
              //为什么不直接用this呢?这里的this代表的是$axios,用that他代指的是整个Vue对象
          })
      }
    }

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>

</style>
Login.vue
<template>
  <div class="">
      <ul>
        <li v-for="item in courseList">
          <router-link :to="{'path':'/course-detail/'+item.id}">{{item.name}}</router-link>
        </li>
      </ul>
  </div>
</template>

<script>
export default {
  name: 'index',
  data () {
    return {
      msg:'课程页面',
      courseList:[]
    }
  },
   mounted:function () {
      //当组件一加载的时候就应该去数据库去获取数据
      this.initCourses()
  },
  methods:{
    initCourses:function () {
      var that = this
      this.$axios.request({
          url:'http://127.0.0.1:8082/course/',
          method:"GET"
      }).then(function (response) {
        console.log(response);
        that.courseList = response.data.courseList  //把从数据库取的数据赋值到courseList列表里面
      })
    }
  }

}

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>

</style>
Course.vue
<template>
  <div class="hello">
    <div>课程详细</div>
    <h3>{{ title }}</h3>
    <h3>{{ summary }}</h3>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      title:'',
      summary:''
    }
  },
  mounted:function () {
    //当组件一加载就执行的函数
    this.initCoursesDetail()
  },
  methods:{
    initCoursesDetail(){
      var nid = this.$route.params.id  //获取id
      var that = this
      var url = 'http://127.0.0.1:8082/course/' + nid + '.json'
      this.$axios.request({
        url:url,
        methods:'GET',
        responseType:'json'
      }).then(function (response) {
        console.log(response)
        that.title = response.data.title;
        that.summary = response.data.summary
      })
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>
CoursesDetail
<template>
  <div class="hello">
    <h2>欢迎报名学位课</h2>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
Micro.vue
<template>
  <div class="hello">
   <h2>深科技</h2>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
News.vue
<template>
  <div class="hello">
 <h1>找不到页面</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
NotFound

保存全局使用的变量store

import Vue from 'vue'
import Vuex from 'vuex'
import Cookie from 'vue-cookies'

Vue.use(Vuex)


export default new Vuex.Store({
  //组件中通过this.$store.state.username 调用
  state:{
    username:Cookie.get('username'),
    token:Cookie.get('token')
  },
  mutations:{
    //组件中通过this.$store.commit(参数)调用
    saveToken:function (state,data) {  //存放用户名和token的函数
      state.username = data.username   //data代指从后端返回过来的数据
      state.token = data.token
      Cookie.set('username',data.username,'20min')   //把用户名和token存放到cookie中
      Cookie.set('token',data.token,'20min')
    },
    //清空token和cookie
    clearToken:function (state) {
      state.username=null
      state.token= null
      Cookie.remove('username')
      Cookie.remove('token')
    }
  }
})
store.js

后端代码:

"""vue和restful配合 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.LoginView.as_view()),
    url(r'^course/$', views.CourseView.as_view()),
    url(r'^course/(?P<pk>\d+)\.(?P<format>[a-z-9]+)$', views.CourseView.as_view()),
]
urls.py
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import JsonResponse


class LoginView(APIView):

    def get(self,request,*args,**kwargs):
        ret = {
            'code':111,
            'data':'在知识的海洋里一路向前'
        }

        response =  JsonResponse(ret)
        response['Access-Control-Allow-Origin']='*'
        return response

    def post(self,request,*args,**kwargs):
        print(request.body)  #在body里面有值
        print(request.POST)   #在post里面是没有值的
        ret = {
            'code':1000,
            'username':'hc',
            'token':'sdswr3fdfsdfdxqw2fgh',
        }
        response = JsonResponse(ret)
        response['Access-Control-Allow-Origin'] = "*"
        return response

    def options(self, request, *args, **kwargs):
        response = HttpResponse()
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Headers'] = '*'
        # response['Access-Control-Allo w-Methods'] = 'PUT'
        return response


class CourseView(APIView):
    def get(self,request,*args,**kwargs):
        print(args,kwargs)
        pk = kwargs.get('pk')
        if pk:
            print(kwargs.get('pk'))
            ret = {
                'title': "标题标题标题",
                'summary': '老师,太饿了。怎么还不下课'
            }
        else:
            ret = {
                'code':1000,
                'courseList':[
                    {'name':'人生苦短,来学Python','id':1},
                    {'name':'32天学会java,欢迎报名','id':2},
                    {'name':'人工智能即将统领世界...','id':3},
                ]
            }
        response= JsonResponse(ret)
        response['Access-Control-Allow-Origin'] = '*'
        return response
views.py

 

posted @ 2018-02-25 12:13  听风。  阅读(5359)  评论(0)    收藏  举报