1. 下载框架/组件/库
* 1. 下载项目中需要使用的框架个组件.
1. axion 网络请求的第三方框架 (之前测试前后端通信已经安装过了)
cnpm install axios -S
2. vue操作cookies 的组件
cnpm install vue-cookies -S
3. element-ui ui库
cnpm install element-ui -S
4. jquery框架(bootstrap需要使用)
cnpm install jquery -S (不适合 vue.js 开发的项目, 不在推荐去使了)
5. bootstrap框架
cnpm install bootstrap@3 -S
* 2. 在main.js导入下载的框架/组件/库
import axios from 'axios'
Vue.prototype.$axios = axios
import cookies from 'vue-cookies'
Vue.prototype.$cookies = cookies;
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
* 3. juery的带入需要单独配置, 在项目根目录下新建vue.config.js文件
如果文件已经创建了, 在后面将代码添加即可.
const webpack = require("webpack");
module.exports = {
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.$": "jquery",
Popper: ["popper.js", "default"]
})
]
}
};
2. vue路由跳转方式
方式1: html中路由跳转
<router-link to="/">
</router-link>
方式2: js点击事件中控制路由跳转
@click='func()'
this.$router.push('/');
3. Load storage 与 Session Storage
Load storage: 数据存放在本地, 可以永久存储.
Session Storage: 数据临时存储,页面关闭, 数据清除
可以在开发者工作中的Application中查看Load storage 与 Session Storage 都是windows对象, 可以通过
对象.属性 = 值 为对象创建属性
对象.属性 取值
4. 头部组件
4.1 组件代码
将img目录复制到在assets文件下
在components小组件中新建Head.vue
<template>
<div class="header">
<div class="slogan">
<p>老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活p>
div>
<div class="nav">
<ul class="left-part">
<li class="logo">
<router-link to="/">
<img src="../assets/img/head-logo.svg" alt="">
router-link>
li>
<li class="ele">
<span @click="goPage('/free-course')" :class="{active: url_path === '/free-course'}">免费课span>
li>
<li class="ele">
<span @click="goPage('/actual-course')" :class="{active: url_path === '/actual-course'}">实战课span>
li>
<li class="ele">
<span @click="goPage('/light-course')" :class="{active: url_path === '/light-course'}">轻课span>
li>
ul>
<div class="right-part">
<div>
<span>登录span>
<span class="line">|span>
<span>注册span>
div>
div>
div>
div>
template>
<script>
export default {
name: "Header",
data() {
return {
url_path: sessionStorage.url_path || '/',
}
},
methods: {
goPage(url_path) {
if (this.url_path !== url_path) {
this.$router.push(url_path);
}
sessionStorage.url_path = url_path;
},
},
created() {
sessionStorage.url_path = this.$route.path;
this.url_path = this.$route.path;
}
}
script>
<style scoped>
.header {
background-color: white;
box-shadow: 0 0 5px 0 #aaa;
}
.header:after {
content: "";
display: block;
clear: both;
}
.slogan {
background-color: #eee;
height: 40px;
}
.slogan p {
width: 1200px;
margin: 0 auto;
color: #aaa;
font-size: 13px;
line-height: 40px;
}
.nav {
background-color: white;
user-select: none;
width: 1200px;
margin: 0 auto;
}
.nav ul {
padding: 15px 0;
float: left;
}
.nav ul:after {
clear: both;
content: '';
display: block;
}
.nav ul li {
float: left;
}
.logo {
margin-right: 20px;
}
.ele {
margin: 0 20px;
}
.ele span {
display: block;
font: 15px/36px '微软雅黑';
border-bottom: 2px solid transparent;
cursor: pointer;
}
.ele span:hover {
border-bottom-color: orange;
}
.ele span.active {
color: orange;
border-bottom-color: orange;
}
.right-part {
float: right;
}
.right-part .line {
margin: 0 10px;
}
.right-part span {
line-height: 68px;
cursor: pointer;
}
style>
4.2 使用组件
在home页面组件中使用, (页面组件之前的测试代码删除掉!)
使用组件可以是 <Head></Head> 也可以是 <Head/>
5. 全局css样式/全局配置文件
5.1 全局css样式
全局css样式将一些标签的默认样式清除.
* 1. 在assets新建css目录, cs目录中新建global.css
body, h1, h2, h3, h4, h5, h6, p, table, tr, td, ul, li, a, form, input, select, option, textarea {
margin: 0;
padding: 0;
font-size: 15px;
}
a {
text-decoration: none;
color: #333;
}
ul {
list-style: none;
}
table {
border-collapse: collapse;
}
* 2. 在main.js中配置
import '@/assets/css/global.css'
5.2 全局配置文件
将一些常用的配置写在一个文件中, 最终将这文件中的信息写入到Vue对象的属性中方便调用.
* 1. 在assets下新建js目录, js目录中新建settings.js 文件
export default {
base_url: 'http://127.0.0.1:8000'
}
* 2. 在main.js配置文件中导入全局配置文件, 并将信息加入到Vue对象中.
import settings from '@/assets/js/settings'
Vue.prototype.$settings = settings;
6. 底部组件
6.1 组件代码
在components小组件中新建Footer.vue
6.2 使用组件
在home页面组件中使用.
使用组件可以是 <Footer></Footer> 也可以是 <Footer/>
7. 轮播图组件
7.1 组件代码
在components小组件中新建Carousel.vue
7.2 使用组件
7.3 轮播图接口
轮播图的所有图片都是向后端发送请求获取.
1. 创建APP
* 1. 新建home app应用
PS F:\synchro\Project\luffy> cd luffy/apps
PS F:\synchro\Project\luffy\luffy\apps> python ../../manage.py startapp home
* 2. 将新建的app添加到引用列表中
INSTALLED_APPS = [
...
'home',
]
2. 设置数据表
* 1. 在apps下的utils的目录下新建models.py 数据库的基础字段
继承这个类之后, 该表拥有以下字段, 只想被继承不想生成表需要定义Meta类中, 类中定义abstract抽象类.
create_time 创建时间
update_time 最后一次更新时间
is_delete 是否删除
is_show 是否展示
display_order 显示顺序
from django.db import models
class BaseModel(models.Model):
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='最后一次更新时间')
is_delete = models.BooleanField(default=False, verbose_name='是否删除')
is_show = models.BooleanField(default=False, verbose_name='是否展示')
display_order = models.IntegerField(verbose_name='显示顺序')
class Meta:
abstract = True
* 2. 在home 目录的models.py 中继承继承字段类, 创建轮播图表
除了基础字段之后额外添加以下字段, 在后台打印对象的时候展示名字需要定义__str__方法.
在Meta类中定义verbose_name_plural设置表在后台显示的名字
name 图片的名字
img 上传图片
link 点击图片跳转的地址
info 图片的描述信息
from django.db import models
from utils.model import BaseModel
class CarouselModel(BaseModel):
name = models.CharField(max_length=32, verbose_name='图片名称')
img = models.ImageField(upload_to='Carousel', verbose_name='轮播图', help_text='图片尺寸必须是: 3840*800', null=True)
link = models.CharField(max_length=128, verbose_name='跳转地址')
info = models.TextField(verbose_name='图片信息')
def __str__(self):
return self.name
class Meta:
verbose_name_plural = '轮播图表'
* 3. 数据库迁移
python manage.py makemigrations
python manage.py migrate
3. 模型序列化器
在项目名目录下的utils目录下新建Serializer.py 序列模块文件
from rest_framework import serializers
from home import models
class CarouselModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.CarouselModel
fields = ['name', 'link', 'img']
4. 视图类
获取图片的接口, 过滤不需要显示的数据, 再排序, 在通过指定获取取返回值.
* 1. 在settings目录下新建const.py 文件 (记录一些常量)
CAROUSEL_SHOW_QUANTITY = 3
* 2. 在settings的dev.py 配置文件中导入const.py文件
from .const import *
CAROUSEL_SHOW_QUANTITY = CAROUSEL_SHOW_QUANTITY
* 3. 在home apps的视图层中写视图类.
from rest_framework.generics import ListAPIView
from . import models
from utils import Serializer, api_response
from django.conf import settings
class CarouselAPI(ListAPIView):
queryset = models.CarouselModel.objects.filter(is_delete=False, is_show=False).order_by('display_order')[
:settings.CAROUSEL_SHOW_QUANTITY]
serializer_class = Serializer.CarouselModelSerializer
@staticmethod
def response(serializer_data):
return api_response.ResponseDataFormat(data=serializer_data)
ListModelMixin源码中使用在视图类中定义的方法.
class ListModelMixin:
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return self.response(serializer.data)
另一种方式: 在数图类中定义ListModelMixin的list方法, 先调用父类的ListModelMixin的list(也就是内置的)
得到一个Response对象, 充对象中将数据取出放进自己定义的response对象中返回.
class CarouselAPI(ListAPIView):
queryset = models.CarouselModel.objects.filter(is_delete=False, is_show=False).order_by('display_order')[
:settings.CAROUSEL_SHOW_QUANTITY]
serializer_class = Serializer.CarouselModelSerializer
def list(self, request, *args, **kwargs):
res = super().list(request, *args, **kwargs)
print(res)
return api_response.ResponseDataFormat(data=res.data)
5. 请求路由
* 1. 路由分发, 在项目名下的总路由文件中配置路由分发.
...
urlpatterns = [
re_path('^xadmin/', xadmin.site.urls),
re_path('^media/(?P.*)', serve, {'document_root': settings.MEDIA_ROOT}),
re_path('user/', include('user.urls')),
re_path('home/', include('home.urls'))
]
* 2. 在home app目录中新建urls.py 子路由文件
from django.urls import re_path
from home import views
urlpatterns = [
re_path(r'api/Carousel/', views.CarouselAPI.as_view())
]
6. 注册表到后台
* 1. 在home的admin.py 中把轮播图表中注册到xadmin后台管理中
import xadmin
from . import models
xadmin.site.register(models.CarouselModel)
7. 后台管理
* 1. 启动程序 登入到后台 http://127.0.0.1:8000/xadmin/
* 2. 为轮播图表添加数据
序号: 1
图片名称: Carouse1
轮播图: 选中图片
跳转地址: free-course
图片简介: 点击图片跳转到免费课程的路由地址
序号: 2
图片名称: Carouse2
轮播图: 选中图片
跳转地址: actual-course
图片简介: 点击图片跳转到实战课程的路由地址
序号: 3
图片名称: Carouse3
轮播图: 选中图片
跳转地址: light-course
图片简介: 点击图片跳转到轻课的路由地址
8. 接口测试
启动程序访问轮播图的接口 http://127.0.0.1:8000/home/api/Carousel/
7.4 前端获取数据
前端 轮播图组件的生命周期钩子函数created中发送axios请求获取数据.
<template>
<div id="Carousel">
<el-carousel indicator-position="outside" height="400px">
<el-carousel-item v-for="(item, index) in carousel_list" :key="index">
<router-link :to="item.link">
<img :src="item.img" :alt="item.name" >
router-link>
el-carousel-item>
el-carousel>
div>
template>
<script>
export default {
name: 'Carousel',
data() {
return {
carousel_list: []
}
},
created() {
this.$axios.get(this.$settings.base_url + '/home/api/Carousel/').then(response => {
this.carousel_list = response.data.data
}).catch(error => {
alert(error)
})
}
}
script>
<style scoped>
.el-carousel__item {
height: 400px;
min-width: 1200px;
}
.el-carousel__item img {
height: 400px;
margin-left: calc(50% - 1920px / 2);
}
style>
7.5 图片跳转路由
* 1. src目录views目录下新建页面组件
FreeCourse.vue 免费课程页面组件
ActualCourse.vue 实战课程页面组件
LightCourse.vue 轻课页面组件
<template>
<div>
<Head>Head>
<h1>实战课程页面h1>
<Footer>Footer>
div>
template>
<script>
import Head from '@/components/Head'
import Footer from '@/components/Footer'
export default {
name: "actual-course.vue",
components: {
Head,
Footer,
}
}
script>
<style scoped>
style>
<template>
<div>
<Head>Head>
<h1>免费课程页面h1>
<Footer>Footer>
div>
template>
<script>
import Head from '@/components/Head'
import Footer from '@/components/Footer'
export default {
name: "free-course.vue",
components: {
Head,
Footer,
}
}
script>
<style scoped>
style>
<template>
<div>
<Head>Head>
<h1>轻课页面h1>
<Footer>Footer>
div>
template>
<script>
import Head from '@/components/Head'
import Footer from '@/components/Footer'
export default {
name: "light-course.vue",
components: {
Head,
Footer,
}
}
script>
<style scoped>
style>
* 2. src目录下的router目录下的index.js文件中 添加路由
免费课程页面路由
实战课程页面路由
轻课程页面路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import FreeCourse from '../views/FreeCourse.vue'
import ActualCourse from '../views/ActualCourse'
import LightCourse from '../views/LightCourse'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/free-course',
name: 'FreeCourse',
component: FreeCourse
},
{
path: '/actual-course',
name: 'ActualCourse',
component: ActualCourse
},
{
path: '/light-course',
name: 'LightCourse',
component: LightCourse
},
]
const router = new VueRouter({
routes
})
export default router