练习
写一个books接口
带按价格排序,前端页面创建完成,向后端发送请求,获取图书属性,表格显示在前端,前端使用监听属性实现点击价格正序和倒序排列
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='./js/vue.js'></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id='app'>
<button @click="handelClick">价格排序</button>
<ul v-for="book in book_list">
<li>书名:{{book.name}}</li>
<li>价格:{{book.price}}</li>
</ul>
</div>
</body>
<script>
var vue = new Vue({
el: '#app',
data: {
book_list: [],
ordering: 'price'
},
methods: {
handelClick() {
if ('-'.indexOf(this.ordering) >= 0) {
//降序
axios.get('http://127.0.0.1:8000/books/?ordering=' + this.ordering).then(res => {
console.log(res.data)
this.book_list = res.data.data
})
this.ordering = 'price'
} else {
//升
axios.get('http://127.0.0.1:8000/books/?ordering=' + this.ordering).then(res => {
console.log(res.data)
this.book_list = res.data.data
})
this.ordering = '-price'
}
}
},
created() {
axios.get('http://127.0.0.1:8000/books/').then(res => {
console.log(res.data)
this.book_list = res.data.data
})
},
})
</script>
</html>
view.py
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
from .models import Book
from .serilizer import BookSerializer
from rest_framework.response import Response
from rest_framework.filters import OrderingFilter
class BookView(GenericViewSet,ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [OrderingFilter]
ordering_fields = ['price']
def list(self, request, *args, **kwargs):
obj = super().list(request, *args, **kwargs)
return Response({'code':100,'msg':'成功','data':obj.data},headers={'Access-Control-Allow-Origin':'*'})
urls.py
from django.contrib import admin
from django.urls import path
from app01.views import BookView
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('books',BookView,'books')
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns +=router.urls
定义组件
组件创建成功,向后端发送请求,后端返回一张图片地址,显示在组件上(网络图片, media下的图片)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='./js/vue.js'></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id = 'app'>
<child ></child>
</div>
</body>
<script>
var child = {
template:`
<div>
<h1>子组件</h1>
<img :src="url" alt="" height="300px">
</div>
`,
data(){
return {
url:'',
}
},
methods:{},
created(){
axios.get('http://127.0.0.1:8000/img/').then(res=>{
console.log(res.data)
this.url = res.data.url
})
}
}
var vue =new Vue({
el:'#app',
data:{},
methods:{},
components:{child}
})
</script>
</html>
from rest_framework.viewsets import ViewSet
class GetImg(ViewSet):
def list(self,request):
url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F5da5a7c4-e8ef-4975-8581-81e42fdba317%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688648650&t=cfe8b5c2fa170e2a7d4815454cd7956a'
return Response({'code':100,'msg':'成功','url':url},headers={'Access-Control-Allow-Origin':'*'})
from django.contrib import admin
from django.urls import path
from app01.views import BookView,GetImg
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('books',BookView,'books')
router.register('img',GetImg,'img')
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns +=router.urls
media文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='./js/vue.js'></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id = 'app'>
<child ></child>
</div>
</body>
<script>
var child = {
template:`
<div>
<h1>子组件</h1>
<img :src="url" alt="" height="300px">
</div>
`,
data(){
return {
url:'',
}
},
methods:{},
created(){
this.url = 'http://127.0.0.1:8000/media/img/1.jpg'
}
}
var vue =new Vue({
el:'#app',
data:{},
methods:{},
components:{child}
})
</script>
</html>
from django.contrib import admin
from django.urls import path
from django.views.static import serve
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('media/<path:path>', serve,{"document_root":settings.MEDIA_ROOT}),
]
在上面的子组件就中写一个按钮,点击按钮,把子组件的图片地址,传递到父组件中打印出来(alert)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='./js/vue.js'></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id = 'app'>
<child @myevent="handelEvent"></child>
<br>
<h1>父组件</h1>
<img :src="url" alt="">
</div>
</body>
<script>
var child = {
template:`
<div>
<button @click="SendClick">将图片给父组件</button>
<h1>子组件</h1>
<img :src="url" alt="" height="300px">
</div>
`,
data(){
return {
}
},
methods:{
SendClick(){
this.$emit('myevent',this.url)
}
},
created(){
this.url = 'http://127.0.0.1:8000/media/img/1.jpg'
}
}
var vue =new Vue({
el:'#app',
data:{
url:''
},
methods:{
handelEvent(url){
alert(url)
this.url = url
}
},
components:{child}
})
</script>
</html>
动态组件
效果:有三个按钮,分别是首页、订单、商品,点击某一个按钮,展示该页面
笨办法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='./js/vue.js'></script>
</head>
<body>
<div id='app'>
<button @click = "who='home'">首页</button>
<button @click = "who='ordering'">订单</button>
<button @click = "who='goods'">商品</button>
<hr>
<home v-if ='who=="home"'></home>
<ordering v-else-if='who=="ordering"'></ordering>
<goods v-else = 'who=="ordering"'></goods>
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>首页</h1>
</div>`,
data() {
return {}
},
methods: {},
}
var goods = {
template: `
<div>
<h1>商品页面</h1>
</div>`,
data() {
return {}
},
methods: {},
}
var ordering = {
template: `
<div>
<h1>订单页面</h1>
</div>`,
data() {
return {}
},
methods: {},
}
var vue = new Vue({
el: '#app',
data: {
who:'home'
},
methods: {},
components: {home,ordering,goods}
})
</script>
</html>
动态组件-component
1.component标签的is属性等于组件名字,这里就会显示这个组件
<conponent :is="who"></conponent>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='./js/vue.js'></script>
</head>
<body>
<div id='app'>
<button @click = "who='home'">首页</button>
<button @click = "who='ordering'">订单</button>
<button @click = "who='goods'">商品</button>
<hr>
<conponent :is="who"></conponent>
component标签的is属性等于组件名字,这里就会显示这个组件
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>首页</h1>
</div>`,
data() {
return {}
},
methods: {},
}
var goods = {
template: `
<div>
<h1>商品页面</h1>
</div>`,
data() {
return {}
},
methods: {},
}
var ordering = {
template: `
<div>
<h1>订单页面</h1>
</div>`,
data() {
return {}
},
methods: {},
}
var vue = new Vue({
el: '#app',
data: {
who:'home'
},
methods: {},
components: {home,ordering,goods}
})
</script>
</html>
keep-alive的使用
keep-alive可以让输入框内有的内容一致保持,不会因为切换而重置
<keep-alive>
<conponent :is="who"></conponent>
</keep-alive>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src='./js/vue.js'></script>
</head>
<body>
<div id='app'>
<button @click = "who='home'">首页</button>
<button @click = "who='ordering'">订单</button>
<button @click = "who='goods'">商品</button>
<hr>
<keep-alive>
<conponent :is="who"></conponent>
</keep-alive>
</div>
</body>
<script>
var home = {
template: `
<div>
<h1>首页</h1>
</div>`,
data() {
return {}
},
methods: {},
}
var goods = {
template: `
<div>
<h1>商品页面</h1>
</div>`,
data() {
return {}
},
methods: {},
}
var ordering = {
template: `
<div>
<h1>订单页面</h1>
输入搜索内容:<input type="text" v-model="search">
</div>`,
data() {
return {
search:'',
}
},
methods: {},
}
var vue = new Vue({
el: '#app',
data: {
who:'home'
},
methods: {},
components: {home,ordering,goods}
})
</script>
</html>
插槽-slot
1.一般情况下,编写完1个组件之后,组件的内容都是写死的,需要加数据 只能去组件中修改,扩展性很差;然后就出现了插槽这个概念,只需在组件中添加<slot></slot>,就可以在body的组件标签中添加内容
2.使用步骤:
1.在组件的html的任意位置,放个标签
<slot></slot>
2.后期在父组件使用该组件时
<lqz>
放内容
</lqz>
3.放的内容,就会被渲染到slot标签中
基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src = './js/vue.js'></script>
</head>
<body>
<div id = 'app'>
<child>
<div>
动态的div
</div>
</child>
<hr>
<child>
<div>动态的图片</div>
<img src="http://5b0988e595225.cdn.sohucs.com/images/20190603/596657996e8f4f6097aeb69392c7813e.jpeg" alt="" height="300px">
</child>
</div>
</body>
<script>
var child = {
template:`
<div>
<h1>这是组件的h1</h1>
<slot></slot>
<h2>这是组件的h2</h2>
</div>
`,
data(){return {}},
methods: {},
}
var vue = new Vue({
el:'#app',
data:{},
methods:{},
components:{child},
})
</script>
</html>
具名插槽
1.使用步骤:
1.组件中可以留多个插槽,命名
<div>
<h1>我是一个组件</h1>
<slot name="middle"></slot>
<h2>我是组件内部的h2</h2>
<slot name="footer"></slot>
</div>
2.在父组件中使用时,指定某个标签渲染到某个插槽上
<nana>
<div slot="footer">
我是div
</div>
<img src="https://scpic.chinaz.net/files/default/imgs/2023-05-12/23659b1edfc0a984.jpg" alt="" slot="middle">
</nana>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src = './js/vue.js'></script>
</head>
<body>
<div id = 'app'>
<child>
<div slot="min">
动态的div
</div>
<hr slot="min">
<div slot="middle">
<img src="http://5b0988e595225.cdn.sohucs.com/images/20190603/596657996e8f4f6097aeb69392c7813e.jpeg" alt="" height="300px">
</div>
</child>
</div>
</body>
<script>
var child = {
template:`
<div>
<h1>这是组件的h1</h1>
<slot name = 'middle'></slot>
<h2>这是组件的h2</h2>
<slot name = 'min'></slot>
</div>
`,
data(){return {}},
methods: {},
}
var vue = new Vue({
el:'#app',
data:{},
methods:{},
components:{child},
})
</script>
</html>
vue-cli创建项目
简介
1.单页面应用:spa
1.以后vue项目就只有一个 xx.html 页面
2.定义很多组件,不可能都写在 xx.html中
所以就引出:单文件组件(一个组件一个文件)
学习文档:https://v2.cn.vuejs.org/v2/guide/single-file-components.html#ad
2.一个组件中有的东西
1.html内容:以后html都放在 template标签中
2.css内容 :以后都放在 style 标签中
3.js内容: 以后都放在 script标签中
3.使用vue-cli创建vue项目才能使用单文件组件
1.vue脚手架:创建出vue的项目,里面带了很多基础代码
ps:类似于django-admim命令,可以创建出django项目
4.vue-cli脚手架,
1.vue2中使用创建vue项目的软件必须用vue-cli
2.vue3中可以使用vue-cli,也可也使用vite创建,vite号称新一代的构建工具
Vue-cli项目搭建
环境搭建
1.安装nodejs
1.vue-cli是个软件,运行在nodejs环境中,安装nodejs
2.下载地址:
https://nodejs.p2hp.com/download/
https://nodejs.org/zh-cn/
3.安装nodejs
类似于python解释器,一路下一步安装--->选择安装位置--->添加到环境变量(以后再任意位置执行node或npm都会找到)
"""
在cmd中/终端:
查看node版本:node -v
"""
4.安装完,有两个可执行文件
node 等同于 python
npm 等同于 pip
"""
>>>which node # /usr/local/bin/node
>>>node -v # v18.12.1
>>>cd /usr/local/bin # 切换路径
>>>ls # 查看文件下的文件
"""
2.安装cnpm
1.npm安装第三方模块,速度很慢,淘宝做了个cnpm,以后可以使用cnpm替代npm,会去淘宝镜像站下载,速度快
npm install -g cnpm --registry=https://registry.npm.taobao.org
mac:sudo npm install -g cnpm --registry=https://registry.npm.taobao.org
ps:以后 使用npm安装模块的命令全都换成 cnpm
3 在node环境中装vue-cli(类似于装django)
1.指令
cnpm install -g @vue/cli
mac:sudo cnpm install -g @vue/cli
2.装完脚手架,会多出一个命令vue,用来创建vue项目-->等同于djagno-admin命令
创建项目
1.使用脚手架,创建vue项目
vue create 项目名
eg:vue create myfirstvue
2.选择yes
3.选择Babel,Router,vuex
1.Babel:语法转换
2.Router:页面跳转 路由效果
3.vuex:状态管理器,存储数据的
4.选vue版本
5.选package.json
5 之前的设置,保存与不保存都可以
使用vue-cli-ui创建
在终端输入:vue ui
启动出一个服务,直接在浏览器中点点击就可以创建
vue项目目录结构
编写vue项目,使用编辑器--->pycharm
使用pycharm打开vue项目
运行vue项目
1.方式一:命令行中 (一定要注意路径)
npm run serve
"""
终端
cd /Users/na/Documents/myfirstvue
npm run serve
"""
2.方式二:使用pycharm运行 --->点击绿色箭头
配置一个启动脚本,以后点绿色箭头运行即可
vue项目的目录结构
myfirstvue-------------------->项目名
-node_modules--------------->文件夹,放了该项目所有的依赖,很小很多,以后把项目传给别人,这个要删除,别人拿到执行cnpm install安装依赖
-public--------------------->文件夹
--favicon.ico------------->小图标,浏览器上面显示,可以替换
--index.html-------------->spa,这个html是整个项目的一个html,你不要动
-src------------------------>以后动这里面的东西,所有代码都在者
--assets------------------>文件夹,放一些静态资源,图片,js,css
---logo.png
--components-------------->以后小组件写在里面 xx.vue
---HelloWorld.vue------->默认提供了一个组件
--router------------------>装了vueRouter就会有这个文件夹,如果不装就没有,现在不用管
---index.js
--store------------------->装了vuex就会有,不装就没有
---index.js
--views-------------------->文件夹,里面放了所有页面组件
---AboutView.vue--------->关于组件
---HomeView.vue---------->首页组件
--App.vue------------------>根组件
--main.js------------------>项目启动的入口文件,核心
-.gitignore------------------>git相关,后面学了就会了
-babel.config.js------------->babel的配置,不用管
-jsconfig.json
-package.json---------------->重要,存放依赖
-package-lock.json----------->锁定文件
-README.md------------------->项目介绍
-vue.config.js--------------->vue项目的配置文件
"""
总结:以后只需要关注src文件夹下的文件即可
"""
es6导入导出、导入语法
导出语法
1.在项目中:创建包 eg:ln ps:在views文件下
2.在包下面创建文件夹 eg:package.js
3.在文件中写js代码
eg:
var name = 'nana'
function add(a,b){
return a+b
}
4.导出
4.1 默认导出对象
eg:
export default {
add:add,
name:name}
或:
export default {
add,
name
}
4.2 命名导出,导出了两个变量
export const name='cx'
export const add=(a,b)=>a+b
导入语法
1.默认导出的导入
1.在任意的js中导入:import 起个名字 from '路径'
import ln from './ln/package'
2.使用导入的包:起个名字.导出的字段
eg:
var res = ln.add(1,2)
console.log(res)
console.log(ln.name)
ps:样式在main.py中写
2.命名导出的导入
1.在任意的js中
import {name,add} from './lqz/package'
2.直接用即可
eg:
import {name,add} from './ln/package'
console.log(add(2,3))
console.log(name)
vue项目编写规范
修改项目
App.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
HomeView.vue
<template>
<div class="home">
</div>
</template>
<script>
export default {
name: 'HomeView',
}
</script>
AboutView.vue
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
作业
查询所有图书按价格排序的作业,写在HomeView.vue
<template>
<div class="home">
<button @click="handleClick">降序或升序</button>
<ul v-for="book in book_list">
<li>图书id:{{book.id}}</li>
<li>图书名:{{book.name}}</li>
<li>图书价格:{{book.price}}</li>
</ul>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'HomeView',
methods: {
handleClick(){
if (this.ordering){
//升序
axios.get('http://127.0.0.1:8000/books/?ordering=price').then(res=>{
console.log(res.data)
this.book_list=res.data.data
})
}else {
//降序
axios.get('http://127.0.0.1:8000/books/?ordering=-price').then(res=>{
console.log(res.data)
this.book_list=res.data.data
})
}
this.ordering =!this.ordering
}
},
data(){
return {
book_list:[],
ordering:true
}
},
created() {
axios.get('http://127.0.0.1:8000/books/').then(res=>{
console.log(res.data)
this.book_list=res.data.data
})
}
}
</script>
<style>
h1 {
font-size: 80px;
}
</style>
补充
1.在vue项目中使用ajax获取数据:
命令行:cnpm install -S axios
2.在Vue.js中使用axios发送GET请求,你可以在HomeView.vue组件中的<script>标签中导入axios。通常,你可以将导入语句放在文件的顶部:
<script>
import axios from 'axios';
export default {
// 组件的其余部分
}
</script>