目录
- DAY65
- DAY66
- DAY67
- DAY68
- DAY69
- 课堂笔记
- Vue配置bs环境
- 前后端分离跨域交互
- main.js
- vue.config.js
- App.vue
- Car.vue
- CarDetail.vue
- Element.vue
- Home.vue
- router——index.js
- store——index.js
- components——Nav.vue
- components——CarTag.vue
- Django后端app文件夹(admin.py)
- Django后端(apps.py)
- Django后端app文件夹(models.py)
- Django后端app文件夹(views.py)
- Django后端d-proj文件夹urls文件
- Django后端d-proj文件夹settings文件
DAY65
课堂笔记
在day65代码文件夹下—》新建js文件,然后导入在官网下载好的Vue.js文件
```python
"""
1、http与https
http vs tcp:应用层,传输层,http协议传输层采用的是tcp
http特点:无状态,无连接,先客户端发出请求,服务器端一定做出响应
https:在http协议之上增加ssl安全认证
2、前端布局
流式布局
响应式布局
盒模型布局
浮动布局
定位布局
3、ORM
"""
```
## 课程安排
```python
"""
Vue:
基础:指令、实例成员、组件(组件间传参)
项目:基于组件开发、插件(vue-router、vuex、axios、vue-cookies、jq+bs、element-ui)
DRF:
全称:django-restframework:完成前后台 分离式 django项目
知识点:
请求、响应、渲染、解析、异常
序列化组件、三大认证、视图家族(CBV)
分页、筛选、搜索、排序
Luffy:
目的:了解前后台分离项目,了解公司开发项目的模式
知识点:git、多方式登录、第三方短信认证、支付宝、上线
"""
```
## Vue
```python
"""
前台框架:angular、react、vue
vue:有前两大框架优点,摈弃缺点;没有前两个框架健全
vue优点:中文API、单页面应用、组件化开发、数据双向绑定、虚拟DOM、数据驱动思想(相比DOM驱动)
"""
```
## 知识总结
```python
"""
1、vue框架的优势
2、vue如何在页面中引入
1)通过script标签引入vue.js环境
2)创建vue实例
3)通过el进行挂载
3、插值表达式
{{ 变量以及变量的简单运算 }}
4、文本指令
{{ }} | v-text | v-html | v-once
5、方法指令
v-on:事件="变量" | @事件="变量" | @事件="变量()" | @事件="变量($event, ...)"
6、属性指令
v-bind:属性="变量" | :属性="变量"
:title="t1"
:class="c1" | :class="[c1, c2]" | :class="{c1: true}"
:style="s1" | :style="{color: c1, fontSize: f1}"
s1是字典变量,c1和f1变量分别控制字体颜色和大小
7、js补充
function可以作为类,内部会有this
箭头函数内部没有this
{}里面出现的函数称之为方法: 方法名(){}
"""
```
1、vue实例
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Vue实例</title>
<style>
body {
user-select: none;
}
</style>
</head>
<body>
<section>
<div id="d1">
{{ msg }}
<p v-on:click="pClick" v-bind:style="pStyle">{{ info }}</p>
</div>
<hr>
<div class="d2">
{{ }}
</div>
<hr>
<div class="d2">
{{ }}
</div>
</section>
</body>
<script src="js/vue.js"></script>
<script>
`
console.log(Vue);
let app = new Vue({
el: '#d1', // 挂载点:vue实例与页面标签建立关联
});
new Vue({
el: '.d2', // 挂载点采用的是css3选择器语法,但是只能匹配第一次检索到的结果
});
`;
// 总结:
// 1、通常挂载点都采用id选择器(唯一性)
// 2、html与body标签不能作为挂载点(组件知识点解释)
// new Vue({
// el: 'body'
// })
let app = new Vue({
el: 'section',
data: { // data为挂载点内部提供数据
msg: 'message',
info: '信息',
pStyle: {
color: 'yellowgreen'
}
},
methods: {
pClick: function () {
if (app.pStyle.color !== 'yellowgreen') {
app.pStyle.color = 'yellowgreen'
} else {
app.pStyle.color = 'red'
}
console.log(app.msg);
console.log(app.pClick);
console.log(this.msg);
console.log(this.pClick);
}
}
});
// 声明的实例是否用一个变量接收
// 1、在实例内部不需要,用this就代表当前vue实例本身
// 2、在实例外部或其他实例内部需要,定义一个变量接收new Vue()产生的实例
console.log(app.msg)
</script>
</html>
2、插值表达式
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<p>{{ msg }}</p>
<p>{{ num * 10 }}</p>
<p>{{ msg + num }}</p>
<p>{{ msg[1] }}</p>
<p>{{ msg.split('') }}</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: 'msg',
num: 10
}
})
</script>
</html>
3、文本指令
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<!--
文本指令:
1、{{ }}
2、v-text:不能解析html语法的文本,会原样输出
3、v-html:能解析html语法的文本
4、v-once:处理的标签的内容只能被解析一次
-->
<p>{{ msg.split('') }}</p>
<p v-text="msg.split('')">12345</p>
<p v-text="info"></p>
<p v-html="info"></p>
<hr>
<p v-on:click="pClick" v-once>{{ msg + info }}</p>
<p>{{ msg }}</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: 'message',
info: '<i>info</i>'
},
methods: {
pClick: function () {
this.msg = '信息'
}
}
})
</script>
</html>
4、面向对象js
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>面向对象js</title>
</head>
<body>
<h1>面向对象js</h1>
</body>
<script>
// undefined、null、string、number、boolean、object(Array)、function
// var、let、const、不写
// object(Array)、function
function f1() {
console.log('f1 run')
}
f1();
// 构造函数 == 类
function F2(name) {
this.name = name;
this.eat = function (food) {
console.log(this.name + '在' + food);
}
}
let ff1 = new F2("Bob");
console.log(ff1.name);
let ff2 = new F2("Tom");
console.log(ff2.name);
ff1.eat('饺子');
ff2.eat('sao子面');
let obj = {
name: 'Jerry',
// eat: function (food) {
// console.log(this.name + '在' + food)
// },
eat(food) { // 方法的语法
console.log(this.name + '在' + food)
}
};
console.log(obj.name);
obj.eat('hotdog');
</script>
</html>
5、js函数补充
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>函数补充</title>
</head>
<body>
<h1>函数补充</h1>
</body>
<script>
// ES5 ES6
function f() {
d = 40; // 全局变量
}
f();
console.log(d);
const c = 30; // 常量
console.log(c);
if (1) {
var a = 10;
let b = 20; // let、const定义的变量不能重复定义,且具备块级作用域
}
console.log(a);
// console.log(b);
for (let i = 0; i < 5; i++) {
console.log(i);
}
// console.log(i);
// console.log(i);
// console.log(i);
function f1() {
console.log('f1 run');
}
let f2 = function () {
console.log('f2 run');
};
f2();
let f3 = () => {
console.log('f3 run');
};
f3();
// 如果箭头函数没有函数体,只有返回值
let f4 = (n1, n2) => n1 + n2;
let res = f4(10, 25);
console.log(res);
// 如果箭头函数参数列表只有一个,可以省略()
let f5 = num => num * 10;
res = f5(10);
console.log(res);
// 重点:function、箭头函数、方法都具有本质区别
let obj = {
name: 'Jerry',
// eat: function (food) {
// console.log(this);
// console.log(this.name + '在吃' + food)
// },
// eat: food => {
// console.log(this);
// console.log(this.name + '在' + food)
// },
eat(food) { // 方法的语法
console.log(this);
console.log(this.name + '在' + food)
}
};
obj.eat('food');
new Vue({
data: {
res: ''
},
methods: {
fn () {
// axios插件
let _this = this;
this.$axios({
url: '',
method: 'get',
data: {
},
}).then(function (response) {
_this.res = response.data;
})
},
fn1 () {
// axios插件
this.$axios({
url: '',
method: 'get',
data: {
},
}).then(response => {
//this指的是axios插件
this.res = response.data;
})
}
}
})
</script>
</html>
6、事件指令
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<!--
事件指令: v-on:事件名="方法变量"
简写: @事件名="方法变量"
-->
<p v-on:click="f1">{{ msg }}</p>
<p @click="f1">{{ msg }}</p>
<hr>
<!--mouseover mouseenter | mouseout mouseleave-->
<p @mouseover="f2" @mouseout="f3" @mouseup="f5" @mousemove="f6" @contextmenu="f7">{{ action }}</p>
<hr>
<!-- 事件变量,不添加(),默认会传事件对象: $event -->
<!-- 事件变量,添加(),代表要自定义传参,系统不再传入事件对象,但是可以手动传入事件对象 -->
<p @click="f8($event, '第一个')">{{ info }}</p>
<p @click="f8($event, '第二个')">{{ info }}</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: '点击切换',
action: '鼠标事件',
info: '确定点击者'
},
methods: {
f1 () {
this.msg = '点击了'
},
f2 () {
this.action = '悬浮';
console.log('悬浮')
},
f3 () {
this.action = '离开'
},
f4 () {
this.action = '按下'
},
f5 () {
this.action = '抬起'
},
f6 () {
this.action = '移动';
console.log('移动')
},
f7 () {
this.action = '右键';
},
f8 (ev, argv) {
console.log(ev, argv);
this.info = argv + '点击了';
}
}
})
</script>
</html>
7、属性指令
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.d1 {
width: 200px;
height: 200px;
background-color: orange;
}
.d2 {
border-radius: 50%;
}
.d3 {
border-radius: 20%;
}
</style>
</head>
<body>
<div id="app">
<!--属性指令: v-bind:属性名="变量"
简写: :属性名="变量"
-->
<p style="color: red" class="dd1" abc="def" title="悬浮提示">红色字体</p>
<!--1、简单使用-->
<p v-bind:title="pTitle" :abc="def" @click="changeImg">简单使用</p>
<!--<img :src="img_src" alt="">-->
<!--2、class属性绑定-->
<!--c1变量的值就是类名-->
<p :class="c1"></p>
<!--多类名可以用[]语法,采用多个变量来控制-->
<p :class="[c2, c3]"></p>
<!--选择器位可以设置为变量,也可以设置为常量-->
<p :class="['d1', c4]"></p>
<!--{类名: 布尔值}控制某类名是否起作用-->
<!--<p :class="{x1: false}"></p>-->
<!--多种语法混用-->
<p :class="['d1', {d2: is_true}]" @click="is_true = !is_true"></p>
<!--3、style属性绑定(了解)-->
<p :style="myStyle">样式属性</p>
<p :style="{width: w,height: h, backgroundColor: bgc}">样式属性</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
pTitle: '简单使用',
def: '自定义属性',
img_src: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3819296004,574391848&fm=26&gp=0.jpg',
c1: 'd1 d2',
c2: 'd1',
c3: 'd3',
c4: 'd3',
is_true: true,
myStyle: {
width: '100px',
height: '100px',
backgroundColor: 'red'
},
w: '200px',
h: '100px',
bgc: 'green'
},
methods: {
changeImg() {
this.img_src = 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1371195756,4187769521&fm=26&gp=0.jpg'
}
}
})
</script>
</html>
//今日日考:
1.简述一下vue框架的优点
2.vue实例通过什么与页面结构建立关联?有哪些要注意的点
3.写出文本,属性与事件指令
DAY66
课堂笔记
## 复习
```python
"""
1、vue框架的优势
中文API
单一面应用 - 提升移动端app运行速度
数据的双向绑定 - 变量全局通用
数据驱动 - 只用考虑数据,不需要在意DOM结构
虚拟DOM - 缓存机制
2、vue如何在页面中引入
1)通过script标签引入vue.js环境
2)创建vue实例
3)通过el进行挂载
new Vue({
el: '#app', // css3选择器,唯一,html、body不能作为挂载点,一个页面可以有多个实例对应多个挂载点
})
3、插值表达式
{{ 变量以及变量的简单运算 }}
{{ ((num * 10) + 'string').split('')[0] }}
4、文本指令
{{ }} | v-text | v-html | v-once
5、方法指令
v-on:事件="变量" | @事件="变量" | @事件="变量()" | @事件="变量($event, ...)"
@click='btnClick'
btnClick(ev) {}
@click='btnClick(1, 2, $event)'
btnClick(n1, n2, ev) {}
btnClick(...args) {}
6、属性指令
v-bind:属性="变量" | :属性="变量"
:title="t1"
:class="c1" | :class="[c1, c2]" | :class="{c1: true}"
:style="s1" | :style="{color: c1, fontSize: f1}"
s1是字典变量,c1和f1变量分别控制字体颜色和大小
7、js补充
function可以作为类,内部会有this
箭头函数内部没有this
{}里面出现的函数称之为方法: 方法名(){}
function Fn(name){this.name = name}
let f1 = new Fn('Bob')
let f2 = ()=>{}
{
f3(){}
}
"""
```
## 课堂内容
```python
"""
1、表单指令:
v-model="变量" 变量与value有关
普通:变量就代表value值
单选框:变量为多个单选框中的某一个value值
单一复选框:变量为布尔,代表是否选中
多复选框:变量为数组,存放选中的选项value
2、条件指令:
v-show: display:none
v-if: 不渲染
v-if | v-else-if | v-else
3、循环指令:
v-for="(v, i) in str|arr"
v-for="(v, k, i) in dic"
4、sessionStorage | localStorage
5、分隔符:delimiters: ['{{', '}}'],
6、过滤器:
{{ n1, n2 | f1(30) | f2 }}
filters: {
f1(n1,n2,n3) {return 过滤结果},
f2(f1的res) {return 过滤结果},
}
7、计算属性:
computed: {
result() {
// 一个方法属性值依赖于多个变量
return this.n1 + this.n2;
}
}
8、监听属性:
watch: {
full_name(n, o) {
this.first_name = n.split('')[0]
this.last_name = n.split('')[1]
}
}
9、冒泡排序:
for (let i=0; i<arr.length-1; i++) { // 趟数
for (let j=0; j<arr.length-1-i; j++) { // 比较次数
// 处理条件即可
if (arr[j]参数 > stus[j + 1]参数) {
let temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
"""
```
## A作业(必做)
```python
"""
1、按照上方 知识点总结 模块,总结今天所学知识点;
2、先有一下成绩单数据
scores = [
{ name: 'Bob', math: 97, chinese: 89, english: 67 },
{ name: 'Tom', math: 67, chinese: 52, english: 98 },
{ name: 'Jerry', math: 72, chinese: 87, english: 89 },
{ name: 'Ben', math: 92, chinese: 87, english: 59 },
{ name: 'Chan', math: 47, chinese: 85, english: 92 },
]
用table表格标签渲染以上数据,表格第一列是学生总分排名,最后一列是学生总分;
3、还是采用上方相同的数据,采用相同的渲染规则,只渲染所有科目都及格了的学生。
"""
```
## B作业(选做)
```python
"""
1、还是采用上方相同的数据,添加筛选规则:
i)有三个按钮:语文、数学、外语,点击谁谁高亮,且当前筛选规则采用哪门学科
ii)两个输入框,【】~【】,前面天最小分数,后面填最大分数,全部设置完毕后,表格的数据会被更新只渲染满足所有条件的结果
举例:点击语文,输入【86】~【87】,那就只会渲染Jerry和Ben两条数据
"""
```
1、表单指令
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>表单指令</title>
</head>
<body>
<div id="app">
<!--表单指令: v-model="变量" 变量值与表单标签的value相关
v-model可以实现数据的双向绑定:v-model绑定的变量值可以影响表单标签的值,反过来单标签的值也可以影响变量的值
-->
<form action="">
<!--重点-->
<input type="text" name="usr" id="usr" placeholder="请输入账号" v-model="v1">
<input type="text" v-model="v1">
{{ v1 }}
<hr>
<!--1.单选框-->
男:<input type="radio" name="sex" value="male" v-model="v2">
女:<input type="radio" name="sex" value="female" v-model="v2">
{{ v2 }}
<hr>
<!--2.单一复选框-->
卖身契:同意 <input type="checkbox" name="agree" v-model="v3">
{{ v3 }}
<hr>
<!--3.多复选框-->
爱好:<br>
男:<input type="checkbox" name="hobbies" value="male" v-model="v4">
女:<input type="checkbox" name="hobbies" value="female" v-model="v4">
哇塞:<input type="checkbox" name="hobbies" value="other" v-model="v4">
{{ v4 }}
<hr>
<button type="submit">提交</button>
</form>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
v1: '123',
v2: 'male',
v3: false,
v4: ['male', 'female']
}
})
</script>
</html>
2、条件指令
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
<style>
[v-cloak] { display: none; }
.box {
width: 200px;
height: 200px;
}
.r {background-color: red}
.b {background-color: blue}
.g {background-color: green}
.active {
background-color: deeppink;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<!--条件指令:
v-show="布尔变量" 隐藏时,采用display:none进行渲染
v-if="布尔变量" 隐藏时,不再页面中渲染(保证不渲染的数据泄露)
-----------------------------
v-if | v-else-if | v-else
-->
<div class="box r" v-show="is_show"></div>
<div class="box b" v-if="is_show"></div>
<hr>
<div class="wrap">
<div>
<button @click="page='r_page'" :class="{active: page === 'r_page'}">红</button>
<button @click="page='b_page'" :class="{active: page === 'b_page'}">蓝</button>
<button @click="page='g_page'" :class="{active: page === 'g_page'}">绿</button>
</div>
<div class="box r" v-if="page === 'r_page'"></div>
<div class="box b" v-else-if="page === 'b_page'"></div>
<div class="box g" v-else></div>
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
is_show: false,
page: 'r_page'
}
})
</script>
</html>
<!--今日日考:
1.条件质量一共有哪些?有两个相似功能的指令区别在哪?
2.循环指令怎么处理字符串,数组和对象
3.简述计算属性和监听属性
4.简述过滤器-->
3、循环指令
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>循环指令</title>
</head>
<body>
<div id="app">
<!--循环指令:
v-for="ele in string|array|obj"
-->
<span>{{ info }}</span>
<hr>
<i v-for="c in info">{{ c }} </i>
<hr>
<i v-for="(c, i) in info">{{i}}:{{c}}<br></i>
<hr>
<div v-for="e in stus">{{ e }}</div>
<hr>
<div v-for="(e, i) in stus">{{ i }}:{{ e }}</div>
<hr>
<div v-for="v in people">{{ v }}</div>
<hr>
<div v-for="(v, k, i) in people">{{ i }} - {{ k }}:{{ v }}</div>
<hr>
<div v-for="tea in teas">
<span v-for="(v, k, i) in tea"><span v-if="i !== 0"> | </span>{{ k }}:{{ v }}</span>
</div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
info: 'good good study',
stus: ['Bob', 'Tom', 'Jerry'],
people: {
name: '猴子',
age: 36.7,
sex: '女',
},
teas: [
{
name: 'jason',
age: 73,
sex: '男',
},
{
name: 'egon',
age: 74,
sex: '男',
},
{
name: 'owen',
age: 17.5,
sex: '男',
}
]
}
})
</script>
</html>
4、循环指令案例
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>todo list 案例</title>
<style>
li:hover {
color: red;
cursor: pointer;
}
</style>
</head>
<body>
<div id="app">
<input type="text" v-model="comment">
<button type="button" @click="send_msg">留言</button>
<ul>
<li v-for="(msg, i) in msgs" @click="delete_msg(i)">{{ msg }}</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
comment: '',
msgs: localStorage.msgs ? JSON.parse(localStorage.msgs) : [],
},
methods: {
send_msg() {
// 将comment添加到msgs数组中:unshift push 首尾增 | shift pop 首尾删
// this.msgs.push(this.comment);
// 数组操作最全方法:splice(begin_index, count, ...args)
// this.msgs.splice(0, 2);
if (!this.comment) {
alert('请输入内容');
return false;
}
this.msgs.push(this.comment);
this.comment = '';
localStorage.msgs = JSON.stringify(this.msgs);
},
delete_msg(index) {
this.msgs.splice(index, 1);
localStorage.msgs = JSON.stringify(this.msgs);
}
}
})
</script>
<script>
// 前台数据库
// localStorage: 永久存储
// sessionStorage:临时存储(所属页面标签被关闭后,清空)
// 存
// localStorage.n1 = 10;
// sessionStorage.n2 = 20;
// 取
// console.log(localStorage.n1);
// console.log(sessionStorage.n2);
// 数组等类型需要先序列化成JSON
// localStorage.arr = JSON.stringify([1, 2, 3]);
// console.log(JSON.parse(localStorage.arr));
// 清空数据库
// localStorage.clear();
</script>
</html>
5、分隔符(了解)
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
{{ msg }}
[{ msg }]
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
msg: 'message'
},
delimiters: ['[{', '}]'], // 修改插值表达式符号
})
</script>
</html>
6、过滤器
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>过滤器</title>
</head>
<body>
<div id="app">
<!--
总结:
1、在filters成员中定义过滤器方法
2、可以对多个值进行过滤,过滤时还可以额外传入辅助参数
3、过滤的结果可以再进行下一次过滤(过滤的串联)
-->
<p>{{ num | f1 }}</p>
<p>{{ a, b | f2(30, 40) | f3 }}</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
num: 10,
a: 10,
b: 20,
},
filters: {
// 传入所有要过滤的条件,返回值就是过滤的结果
f1 (num) {
console.log(num);
return num * 10;
},
f2 (a, b, c, d) {
console.log(a, b, c, d);
return a + b + c + d;
},
f3 (num) {
return num * num;
}
}
})
</script>
</html>
7、计算属性
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<input type="number" min="0" max="100" v-model="n1">
+
<input type="number" min="0" max="100" v-model="n2">
=
<button>{{ result }}</button>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
n1: '',
n2: '',
// result: 0,
},
/**
* 总结:
* 1、computed计算属性可以声明 方法属性(方法属性一定不能在data中重复声明)
* 2、方法属性 必须在页面中渲染,才会启用绑定的方法,方法属性的值就是绑定方法的返回值
* 3、绑定的方法中出现的所有变量都会被监听,任何一个变化发生值更新都会重新出发绑定方法,从而更新方法属性的值
*
* 一般用来解决的问题:一个变量值依赖于多个变量
*/
computed: {
result () {
console.log('被调用了');
n1 = +this.n1;
n2 = +this.n2;
return n1 + n2;
}
}
})
</script>
</html>
8、监听属性
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<p>姓名:<input type="text" v-model="full_name"></p>
<p>姓:{{ first_name }}</p>
<p>名:{{ last_name }}</p>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
full_name: '',
first_name: '未知',
last_name: '未知',
},
watch: {
// n是监听的属性当前值,o是其上一次的值,监听的属性值每次更新都会回调监听方法
/**
* 总结:
* 1、监听的属性需要在data中声明,监听方法不需要返回值
* 2、监听的方法名就是监听的属性名,该属性值发生更新时就会回调监听方法
* 3、监听方法有两个回调参数:当前值,上一次值
*
* 解决的问题:多个变量值依赖于一个变量值
*/
full_name(n, o) {
name_arr = n.split('');
this.first_name = name_arr[0];
this.last_name = name_arr[1];
},
}
})
</script>
</html>
9、冒泡排序
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
}
})
</script>
<script>
let arr = [3, 2, 5, 4, 1];
console.log(arr);
// 冒泡排序
// 3, 2, 5, 4, 1
// 2, 3, 4, 1, 5
// 2, 3, 1, 4
// 2, 1, 3
// 1, 2
for (let i = 0; i < arr.length - 1; i++) { // 外层循环控制趟数
for (let j = 0; j < arr.length - 1 - i; j++) { // 内存循环控制比较次数
if (arr[j] > arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log(arr);
stus = [
{
name: 'Bob',
grade: 98
},
{
name: 'Tom',
grade: 87
},
{
name: 'Jerry',
grade: 92
},
];
// 按照分数进行排名
for (let i=0; i<stus.length-1; i++) {
for (let j=0; j<stus.length-1-i; j++) {
// 处理条件即可
if (stus[j].grade > stus[j + 1].grade) {
let temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
console.log(stus);
</script>
</html>
模板
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
}
})
</script>
</html>
作业1
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.box {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="app">
<div>
<!--需求:当前点击者高亮-->
<button @click="changeColor('red')">红</button>
<button @click="changeColor('yellow')">黄</button>
<button @click="changeColor('blue')">蓝</button>
</div>
<div class="box" :style="{backgroundColor: bgColor}"></div>
<!--(div>button*3)+.box-->
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
bgColor: 'black'
},
methods: {
changeColor(color) {
this.bgColor = color;
}
}
})
</script>
</html>
作业2
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.wrap {
width: 200px;
height: 200px;
/*background-color: black;*/
color: white;
font: bold 50px/200px 'STSong';
text-align: center;
user-select: none;
cursor: pointer;
}
</style>
</head>
<body>
<div id="app">
<div class="wrap" @click="actionFn" :style="{backgroundColor: bgColor}">{{ count }}</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
count: 0,
bgColor: 'black',
colorArr: ['cyan', 'pink', 'green']
},
methods: {
actionFn() {
this.count ++;
this.bgColor = this.colorArr[this.count % 3]
}
}
})
</script>
</html>
作业3
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.wrap {
border: 3px solid black;
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
margin: 50px auto 0;
position: relative;
}
.red, .green {
width: 100px;
height: 200px;
position: absolute;
}
.red { background-color: red; }
.green { background-color: green; }
.l {
width: 100px;
height: 200px;
left: 0;
}
.t {
width: 200px;
height: 100px;
top: 0;
}
.r {
width: 100px;
height: 200px;
right: 0;
}
.b {
width: 200px;
height: 100px;
bottom: 0;
}
</style>
</head>
<body>
<div id="app">
<div class="wrap" @click="actionFn">
<div class="red" :class="red_class"></div>
<div class="green" :class="green_class"></div>
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
count: 0,
red_class: 'l',
green_class: 'r',
red_arr: ['l', 't', 'r', 'b'],
green_arr: ['r', 'b', 'l', 't'],
},
methods: {
actionFn() {
this.count ++;
this.red_class = this.red_arr[this.count % 4];
this.green_class = this.green_arr[this.count % 4];
}
}
})
</script>
</html>
DAY67
课堂笔记
## 课堂内容
```python
"""
1、表单指令:
v-model="变量" 变量与value有关
普通:变量就代表value值
单选框:变量为多个单选框中的某一个value值
单一复选框:变量为布尔,代表是否选中
多复选框:变量为数组,存放选中的选项value
2、条件指令:
v-show: display:none
v-if: 不渲染
v-if | v-else-if | v-else
前者条件成立,就不管之后分支,当所有条件都不成功,才执行v-else分支
3、循环指令:
v-for="(v, i) in str|arr"
v-for="(v, k, i) in dic"
v:值 k:键 i:索引
4、sessionStorage | localStorage
sessionStorage:生命周期同所属标签(标签关闭被销毁)
localStorage:永久保存
localStorage.key = value
localStorage.clear()
5、分隔符:delimiters: ['[{', '}]'],
6、过滤器:
{{ n1, n2 | f1(30) | f2 }}
filters: {
f1(n1,n2,n3) {return 过滤结果},
f2(f1的res) {return 过滤结果},
}
7、计算属性:
result必须渲染;绑定的方法内部出现的变量更新方法被调用;方法返回值是result的值;result不能在data中重复定义
computed: {
result() {
// 一个方法属性值依赖于多个变量
return this.n1 + this.n2;
}
}
8、监听属性:
监听属性属性更新方法被调用;方法参数为被监听属性当前值,上一次值;多个变量依赖一个变量
watch: {
full_name(n, o) {
this.first_name = n.split('')[0]
this.last_name = n.split('')[1]
}
}
9、冒泡排序:
for (let i=0; i<arr.length-1; i++) { // 趟数
for (let j=0; j<arr.length-1-i; j++) { // 比较次数
// 处理条件即可
if (arr[j]参数 > stus[j + 1]参数) {
let temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
"""
```
## Vue基础知识
```python
"""
组件:
组件概念:vue实例就是组件
根组件、局部组件、全局组件
组件传参:
父传子:自定义组件属性
子传父:自定义组件事件
实例成员:
el、data、methods、computed、watch、filters、delimiters、props、template、components
指令:
{{}}、v-text、v-html、v-once、v-on、v-model、v-bind、v-if、v-show、v-else-if、v-else、v-for、v-cloak
"""
```
## Vue项目环境
```python
"""
vue ~~ Django
node ~~ Python
npm ~~ pip
"""
```
## A作业(必做)
```python
"""
1、按照上方 知识点总结 模块,总结今天所学知识点;
2、有以下广告数据(实际数据命名可以略做调整)
ad_data = {
tv: [
{img: 'img/tv/001.png', title: 'tv1'},
{img: 'img/tv/002.png', title: 'tv2'},
{img: 'img/tv/003.png', title: 'tv3'},
{img: 'img/tv/004.png', title: 'tv4'},
],
phone: [
{img: 'img/phone/001.png', title: 'phone1'},
{img: 'img/phone/002.png', title: 'phone2'},
{img: 'img/phone/003.png', title: 'phone3'},
{img: 'img/phone/004.png', title: 'phone4'},
]
}
i) 有两个大标题,电视和手机,点击对应的标题,渲染对应的数据
ii) 一个字典作为一个显示单位,定义一个子组件进行渲染(涉及父子组件传参)
3、在第2题基础上,页面最下方有一个 h2 标签,用来渲染用户当前选择的广告(点击哪个广告就是选中哪个广告)
i)当没有点击任何广告,h2 标签显示:未选中任何广告
ii)当点击其中一个广告,如tv1,h2 标签显示:tv1被选中
"""
```
## B作业(选做)
```python
"""
1、给自己电脑中配置好vue环境,创建一个vue项目,可以参考课件中的 vue项目创建.md
2、预习视频, 尝试在项目基础上完成A作业(利用vue文件,创建视图组件,页面小组件,组件的导入、渲染以及传参)
"""
```
vue创建项目
## Vue项目环境搭建
```python
"""
node ~~ python:node是用c++编写用来运行js代码的
npm(cnpm) ~~ pip:npm是一个终端应用商城,可以换国内源cnpm
vue ~~ django:vue是用来搭建vue前端项目的
1) 安装node
官网下载安装包,傻瓜式安装:https://nodejs.org/zh-cn/
2) 换源安装cnpm
>: npm install -g cnpm --registry=https://registry.npm.taobao.org
3) 安装vue项目脚手架
>: cnpm install -g @vue/cli
注:2或3终端安装失败时,可以清空 npm缓存 再重复执行失败的步骤
npm cache clean --force
"""
```
## Vue项目创建
```
1) 进入存放项目的目录
>: cd ***
2) 创建项目
>: vue create 项目名
3) 项目初始化
```
![](img/vue项目创建.png)
## pycharm配置并启动vue项目
```
1) 用pycharm打开vue项目
2) 添加配置npm启动
```
![](img/配置vue启动.png)
## vue项目目录结构分析
```
├── v-proj
| ├── node_modules // 当前项目所有依赖,一般不可以移植给其他电脑环境
| ├── public
| | ├── favicon.ico // 标签图标
| | └── index.html // 当前项目唯一的页面
| ├── src
| | ├── assets // 静态资源img、css、js
| | ├── components // 小组件
| | ├── views // 页面组件
| | ├── App.vue // 根组件
| | ├── main.js // 全局脚本文件(项目的入口)
| | ├── router
| | | └── index.js// 路由脚本文件(配置路由 url链接 与 页面组件的映射关系)
| | └── store
| | | └── index.js// 仓库脚本文件(vuex插件的配置文件,数据仓库)
| ├── README.md
└ └── package.json等配置文件
```
## vue组件(.vue文件)
```python
# 1) template:有且只有一个根标签
# 2) script:必须将组件对象导出 export default {}
# 3) style: style标签明确scoped属性,代表该样式只在组件内部起作用(样式的组件化)
```
```vue
<template>
<div class="test">
</div>
</template>
<script>
export default {
name: "Test"
}
</script>
<style scoped>
</style>
```
## 全局脚本文件main.js(项目入口)
```js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
```
##### 改写
```js
import Vue from 'vue' // 加载vue环境
import App from './App.vue' // 加载根组件
import router from './router' // 加载路由环境
import store from './store' // 加载数据仓库环境
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
store,
render: function (readFn) {
return readFn(App);
},
});
```
1、组件
## 复习
```python
"""
1、vue框架的优势
中文API
单一面应用 - 提升移动端app运行速度
数据的双向绑定 - 变量全局通用
数据驱动 - 只用考虑数据,不需要在意DOM结构
虚拟DOM - 缓存机制
2、vue如何在页面中引入
1)通过script标签引入vue.js环境
2)创建vue实例
3)通过el进行挂载
new Vue({
el: '#app', // css3选择器,唯一,html、body不能作为挂载点,一个页面可以有多个实例对应多个挂载点
})
3、插值表达式
{{ 变量以及变量的简单运算 }}
{{ ((num * 10) + 'string').split('')[0] }}
4、文本指令
{{ }} | v-text | v-html | v-once
5、方法指令
v-on:事件="变量" | @事件="变量" | @事件="变量()" | @事件="变量($event, ...)"
@click='btnClick'
btnClick(ev) {}
@click='btnClick(1, 2, $event)'
btnClick(n1, n2, ev) {}
btnClick(...args) {}
6、属性指令
v-bind:属性="变量" | :属性="变量"
:title="t1"
:class="c1" | :class="[c1, c2]" | :class="{c1: true}"
:style="s1" | :style="{color: c1, fontSize: f1}"
s1是字典变量,c1和f1变量分别控制字体颜色和大小
7、js补充
function可以作为类,内部会有this
箭头函数内部没有this
{}里面出现的函数称之为方法: 方法名(){}
function Fn(name){this.name = name}
let f1 = new Fn('Bob')
let f2 = ()=>{}
{
f3(){}
}
"""
```
## 课堂内容
```python
"""
1、表单指令:
v-model="变量" 变量与value有关
普通:变量就代表value值
单选框:变量为多个单选框中的某一个value值
单一复选框:变量为布尔,代表是否选中
多复选框:变量为数组,存放选中的选项value
2、条件指令:
v-show: display:none
v-if: 不渲染
v-if | v-else-if | v-else
3、循环指令:
v-for="(v, i) in str|arr"
v-for="(v, k, i) in dic"
4、sessionStorage | localStorage
5、分隔符:delimiters: ['{{', '}}'],
6、过滤器:
{{ n1, n2 | f1(30) | f2 }}
filters: {
f1(n1,n2,n3) {return 过滤结果},
f2(f1的res) {return 过滤结果},
}
7、计算属性:
computed: {
result() {
// 一个方法属性值依赖于多个变量
return this.n1 + this.n2;
}
}
8、监听属性:
watch: {
full_name(n, o) {
this.first_name = n.split('')[0]
this.last_name = n.split('')[1]
}
}
9、冒泡排序:
for (let i=0; i<arr.length-1; i++) { // 趟数
for (let j=0; j<arr.length-1-i; j++) { // 比较次数
// 处理条件即可
if (arr[j]参数 > stus[j + 1]参数) {
let temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
"""
```
## A作业(必做)
```python
"""
1、按照上方 知识点总结 模块,总结今天所学知识点;
2、先有一下成绩单数据
scores = [
{ name: 'Bob', math: 97, chinese: 89, english: 67 },
{ name: 'Tom', math: 67, chinese: 52, english: 98 },
{ name: 'Jerry', math: 72, chinese: 87, english: 89 },
{ name: 'Ben', math: 92, chinese: 87, english: 59 },
{ name: 'Chan', math: 47, chinese: 85, english: 92 },
]
用table表格标签渲染以上数据,表格第一列是学生总分排名,最后一列是学生总分;
3、还是采用上方相同的数据,采用相同的渲染规则,只渲染所有科目都及格了的学生。
"""
```
## B作业(选做)
```python
"""
1、还是采用上方相同的数据,添加筛选规则:
i)有三个按钮:语文、数学、外语,点击谁谁高亮,且当前筛选规则采用哪门学科
ii)两个输入框,【】~【】,前面天最小分数,后面填最大分数,全部设置完毕后,表格的数据会被更新只渲染满足所有条件的结果
举例:点击语文,输入【86】~【87】,那就只会渲染Jerry和Ben两条数据
"""
```
2、子组件
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>子组件</title>
<style>
body, h2 {
margin: 0;
}
.wrap {
width: 880px;
margin: 0 auto;
}
.wrap:after {
content: '';
display: block;
clear: both;
}
.box {
width: 200px;
border-radius: 10px;
overflow: hidden;
background-color: #eee;
float: left;
margin: 10px;
}
.box img {
width: 100%;
}
.box h2 {
text-align: center;
font-weight: normal;
font-size: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="wrap">
<local-tag></local-tag>
<local-tag></local-tag>
<local-tag></local-tag>
<local-tag></local-tag>
<global-tag></global-tag>
<global-tag></global-tag>
<global-tag></global-tag>
<global-tag></global-tag>
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
// 声明局部组件:局部组件要在其父组件中注册才能使用
// 1、声明组件 2、注册组件 3、渲染组件 => 全局组件不需要注册
let localTag = {
template: `
<div class="box" @click="fn">
<img src="img/phone/001.jpg" alt="">
<h2>美女</h2>
</div>
`,
methods: {
fn() {
console.log(this)
}
}
};
Vue.component('global-tag', {
template: `
<div class="box" @click="fn">
<img src="img/phone/002.jpg" alt="">
<h2>大长腿</h2>
</div>
`,
methods: {
fn() {
console.log(this)
}
}
});
new Vue({
el: '#app',
data: {},
components: { // 注册组件
localTag,
}
})
</script>
</html>
3、组件化
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>组件化</title>
<style>
body, h2 {
margin: 0;
}
.wrap {
width: 880px;
margin: 0 auto;
}
.wrap:after {
content: '';
display: block;
clear: both;
}
.box {
width: 200px;
border-radius: 10px;
overflow: hidden;
background-color: #eee;
float: left;
margin: 10px;
}
.box img {
width: 100%;
}
.box h2 {
text-align: center;
font-weight: normal;
font-size: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="wrap">
<local-tag></local-tag>
<local-tag></local-tag>
<local-tag></local-tag>
<local-tag></local-tag>
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
let localTag = {
template: `
<div class="box" @click="fn">
<img src="img/phone/001.jpg" alt="">
<h2>捶了美女{{ count }}下</h2>
</div>
`,
data() { // 局部或全局取件,一个组件可能会被复用多次,每个组件都应该有自己独立的变量名称空间
return {
count: 0,
}
}, // 数据需要组件化,作为方法的返回值(方法执行后会产生一个局部作用域)
methods: {
fn() {
console.log(this);
this.count++;
}
}
};
new Vue({
el: '#app',
data: {},
components: {
localTag,
}
});
`
class A:
name = 'Owen'
def __init__(self, name):
self.name = name
a1 = A('1')
a2 = A('2')
a1.name
a2.name
`;
</script>
</html>
4、组件传参—父传子
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>父传子</title>
<style>
body, h2 {
margin: 0;
}
.wrap {
width: 880px;
margin: 0 auto;
}
.wrap:after {
content: '';
display: block;
clear: both;
}
.box {
width: 200px;
border-radius: 10px;
overflow: hidden;
background-color: #eee;
float: left;
margin: 10px;
}
.box img {
width: 200px;
height: 240px;
}
.box h2 {
text-align: center;
font-weight: normal;
font-size: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="wrap">
<local-tag v-for="dog in dogs" :dog="dog" def="12345" :xyz="dog.name"></local-tag>
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
let dogs = [
{
name: '二哈1号',
img: 'img/100.jpg',
},
{
name: '二哈2号',
img: 'img/200.jpg',
},
{
name: '二哈3号',
img: 'img/300.jpg',
},
{
name: '二哈4号',
img: 'img/400.jpg',
},
{
name: '二哈1号',
img: 'img/100.jpg',
},
{
name: '二哈2号',
img: 'img/200.jpg',
},
{
name: '二哈3号',
img: 'img/300.jpg',
},
{
name: '二哈4号',
img: 'img/400.jpg',
}
];
// 1)子组件可以通过props自定义组件属性(采用反射机制,需要填写字符串,但是使用时可以直接作为变量)
// 2)子组件会在父组件中渲染,渲染时,将父组件的变量绑定给子组件的自定义属性,将可以将变量值传递给子组件
let localTag = {
props: ['dog', 'def', 'xyz'],
template: `
<div class="box" @click="fn">
<img :src="dog.img" alt="">
<h2>捶{{ dog.name }}{{ count}}下</h2>
<!--<h3>{{ abc }}</h3>-->
<!--<h3>{{ def }}</h3>-->
<!--<h3>{{ xyz }}</h3>-->
</div>
`,
data() {
return {
count: 0,
}
},
methods: {
fn() {
console.log(this.dog);
this.count++;
}
}
};
new Vue({
el: '#app',
data: {
dogs,
},
components: {
localTag,
}
});
</script>
</html>
5、组件传参—子传父
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>子传父</title>
</head>
<body>
<div id="app">
<h1>{{ h1 }}</h1>
<h3>{{ h3 }}</h3>
<!--自定义组件标签的事件
自定义事件是属于子组件的,子组件在父组件中渲染并绑定事件方法,所以事件方法由父组件来实现
子组件如何触发自定义事件:this.$emit('自定义事件名', 触发事件回调的参数们)
子组件触发自定义事件,携带出子组件的内容,在父组件中实现自定义事件的方法,拿到子组件传递给父组件的消息
-->
<tag @action="actionFn"></tag>
<hr>
<tag2 @h1a="aFn1" @h3a="aFn3"></tag2>
</div>
</body>
<script src="js/vue.js"></script>
<script>
let tag = {
template: `
<div>
<input type="text" v-model="t1">
<input type="text" v-model="t2">
<button @click="changeTitle">修改标题</button>
</div>
`,
data() {
return {
t1: '',
t2: '',
}
},
methods: {
changeTitle() {
if (this.t1 && this.t2) {
// console.log(this.t1, this.t2);
this.$emit('action', this.t1, this.t2);
this.t1 = '';
this.t2 = '';
}
}
}
};
let tag2 = {
template: `
<div>
主标题内容:<input type="text" v-model="t1" @input="t1Fn">
子标题内容:<input type="text" v-model="t2">
</div>
`,
data() {
return {
t1: '',
t2: '',
}
},
methods: {
t1Fn() {
this.$emit('h1a', this.t1);
}
},
watch: {
t2 () {
this.$emit('h3a', this.t2);
}
}
};
new Vue({
el: '#app',
data: {
h1: '主标题',
h3: '子标题'
},
components: {
tag,
tag2,
},
methods: {
actionFn(a, b, c) {
// console.log('触发了', a, b, c);
this.h1 = a;
this.h3 = b;
},
aFn1(a) {
if (!a) {
this.h1 = '主标题';
return;
}
this.h1 = a;
},
aFn3(a) {
if (!a) {
this.h3 = '子标题';
return;
}
this.h3 = a;
},
}
})
</script>
</html>
作业1
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>1</title>
</head>
<body>
<div id="app">
<table border="1" style="margin: auto" rules="all">
<tr>
<th>排名</th>
<th>姓名</th>
<th>数学</th>
<th>语文</th>
<th>英语</th>
<th>总分</th>
</tr>
<!--有几个人,就循环渲染几行-->
<tr v-for="(score, i) in scores">
<td>{{ i + 1 }}</td>
<td v-for="v in score">{{v}}</td>
</tr>
</table>
</div>
</body>
<script src="js/vue.js"></script>
<script>
`
let scores = null;
$.ajax({
url:'',
success(response) {
scores = response.data
}
});
`;
// 模拟当前页面加载成功,从后台获取操作的数据
let scores = [
{ name: 'Bob', math: 97, chinese: 89, english: 67 },
{ name: 'Tom', math: 67, chinese: 52, english: 98 },
{ name: 'Jerry', math: 72, chinese: 87, english: 89 },
{ name: 'Ben', math: 92, chinese: 87, english: 59 },
{ name: 'Chan', math: 47, chinese: 85, english: 92 },
];
// 补充:for in遍历的是取值关键 | for of遍历的是值
// 添加总分
for (score of scores) {
score.total = score.math + score.chinese + score.english;
}
// console.log(scores);
// 按照总分排序
for (let i=0; i<scores.length-1; i++) {
for (let j=0; j<scores.length-1-i; j++) {
if (scores[j].total < scores[j+1].total) {
let temp = scores[j];
scores[j] = scores[j+1];
scores[j+1] = temp;
}
}
}
console.log(scores);
new Vue({
el: '#app',
data: {
// 属性名与值为变量的变量名相同,可以简写省略值
scores,
}
})
</script>
</html>
作业2
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>2</title>
</head>
<body>
<div id="app">
<table border="1" style="margin: auto" rules="all">
<tr>
<th>排名</th>
<th>姓名</th>
<th>数学</th>
<th>语文</th>
<th>英语</th>
<th>总分</th>
</tr>
<!--有几个人,就循环渲染几行-->
<tr v-for="(score, i) in scores" v-if="score.math>=60&&score.chinese>=60&&score.english>=60">
<td>{{ i + 1 }}</td>
<td v-for="v in score">{{v}}</td>
</tr>
</table>
</div>
</body>
<script src="js/vue.js"></script>
<script>
`
let scores = null;
$.ajax({
url:'',
success(response) {
scores = response.data
}
});
`;
// 模拟当前页面加载成功,从后台获取操作的数据
let scores = [
{ name: 'Bob', math: 97, chinese: 89, english: 67 },
{ name: 'Tom', math: 67, chinese: 52, english: 98 },
{ name: 'Jerry', math: 72, chinese: 87, english: 89 },
{ name: 'Ben', math: 92, chinese: 87, english: 59 },
{ name: 'Chan', math: 47, chinese: 85, english: 92 },
];
// 补充:for in遍历的是取值关键 | for of遍历的是值
// 添加总分
for (score of scores) {
score.total = score.math + score.chinese + score.english;
}
// console.log(scores);
// 按照总分排序
for (let i=0; i<scores.length-1; i++) {
for (let j=0; j<scores.length-1-i; j++) {
if (scores[j].total < scores[j+1].total) {
let temp = scores[j];
scores[j] = scores[j+1];
scores[j+1] = temp;
}
}
}
console.log(scores);
new Vue({
el: '#app',
data: {
// 属性名与值为变量的变量名相同,可以简写省略值
scores,
}
})
</script>
</html>
作业3
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>3</title>
<style>
.active {
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<div style="width: 400px; margin: 20px auto">
<button @click="subject = 'math'" :class="{active: subject === 'math'}">数学</button>
<button @click="subject = 'chinese'" :class="{active: subject === 'chinese'}">语文</button>
<button @click="subject = 'english'" :class="{active: subject === 'english'}">英语</button>
<input type="number" min="0" max="100" v-model="min">
~
<input type="number" min="0" max="100" v-model="max">
</div>
<table width="400" border="1" style="margin: auto" rules="all">
<tr>
<th>排名</th>
<th>姓名</th>
<th>数学</th>
<th>语文</th>
<th>英语</th>
<th>总分</th>
</tr>
<tbody v-if="subject === 'math'">
<tr v-for="(score, i) in scores" v-if="score.math>=min && score.math<=max || (!min || !max)">
<td>{{ i + 1 }}</td>
<td v-for="v in score">{{v}}</td>
</tr>
</tbody>
<tbody v-else-if="subject === 'chinese'">
<tr v-for="(score, i) in scores" v-if="score.chinese>=min && score.chinese<=max || (!min || !max)">
<td>{{ i + 1 }}</td>
<td v-for="v in score">{{v}}</td>
</tr>
</tbody>
<tbody v-else-if="subject === 'english'">
<tr v-for="(score, i) in scores" v-if="score.english>=min && score.english<=max || (!min || !max)">
<td>{{ i + 1 }}</td>
<td v-for="v in score">{{v}}</td>
</tr>
</tbody>
<tbody v-else>
<tr v-for="(score, i) in scores">
<td>{{ i + 1 }}</td>
<td v-for="v in score">{{v}}</td>
</tr>
</tbody>
</table>
</div>
</body>
<script src="js/vue.js"></script>
<script>
`
let scores = null;
$.ajax({
url:'',
success(response) {
scores = response.data
}
});
`;
// 模拟当前页面加载成功,从后台获取操作的数据
let scores = [
{ name: 'Bob', math: 97, chinese: 89, english: 67 },
{ name: 'Tom', math: 67, chinese: 52, english: 98 },
{ name: 'Jerry', math: 72, chinese: 87, english: 89 },
{ name: 'Ben', math: 92, chinese: 87, english: 59 },
{ name: 'Chan', math: 47, chinese: 85, english: 92 },
];
// 补充:for in遍历的是取值关键 | for of遍历的是值
// 添加总分
for (score of scores) {
score.total = score.math + score.chinese + score.english;
}
// console.log(scores);
// 按照总分排序
for (let i=0; i<scores.length-1; i++) {
for (let j=0; j<scores.length-1-i; j++) {
if (scores[j].total < scores[j+1].total) {
let temp = scores[j];
scores[j] = scores[j+1];
scores[j+1] = temp;
}
}
}
console.log(scores);
new Vue({
el: '#app',
data: {
// 属性名与值为变量的变量名相同,可以简写省略值
scores,
min: '',
max: '',
subject: '',
}
})
</script>
</html>
DAY68
课堂笔记
## 复习
```python
"""
1、组件:
html、css、js的集合体
vue实例就代表组件
组件用template实例成员管理html结构,有且只有一个根标签
子组件可以复用,所以数据要组件化处理,data的值由方法的返回值提供
2、分类:
根组件:new Vue({}),顶级组件
全局组件: Vue.component('组件名', {}),不用注册可以在任何地方使用
局部组件:let 组件名 = {},只有在注册的父组件中才能使用
3、组件间传参:
父传子:自定义属性
<tag :info="msg"></tag>
let tag = {
props: ['info'],
}
new Vue({
data: {msg: 12345}
components: {
tag,
}
})
子传父:自定义事件
<tag @action="fn"></tag>
let tag = {
data: {msg: 12345},
methods: {
tag_fn() {
this.$emit('action', this.msg)
}
}
}
new Vue({
components: {
tag,
},
methods: {
fn(info) {}
}
})
4、vue项目环境
官网下载安装node => 将npm换源为cnpm => cnpm install -g @vue/cli
=> vue项目创建...
"""
```
## 知识点总结
```python
"""
1、创建项目:vue create 项目名 - babel、vue-router、vuex
2、项目目录:
node_modules依赖(不同电脑依赖需要重新构建)
views:页面组件
components:小组件
router/index.js:路由配置文件 - 路径与页面组件对应关系
App.vue:根组件,固定五行话(看代码)
main.js:项目总脚本文件 - 配置所有环境,加载根组件
3、vue请求生命周期:
浏览器请求/user => router插件映射User.vue组件 => User.vue组件替换App.vue中的<router-view />占位符
注: i) 可以用 <router-link to="/user">用户页</router-link>完成标签跳转
ii) this.$router.push('/user')完成逻辑跳转
4、vue组件的生命周期钩子:组件 创建 到 销毁 中的时间节点回调的方法
created(){} | mounted(){}
5、路由跳转
this.$router.push({name: '路由名', query: {拼接的参数}})
this.$router.go(number)
6、路由配置
{
path: '/course/detail',
name: 'course-detail',
component: CourseDetail
}
{
path: '/detail',
redirect: '/course/detail'
}
this.$router.push('/course/detail'); == this.$router.push('/detail');
this.$router.push('/course/detail?pk=1'); => this.$route.query.pk
```````````````````````````````````````````````````````````````````````
{
path: '/course/detail/:pk',
name: 'course-detail',
component: CourseDetail
}
this.$router.push('/course/detail/10'); => this.$route.params.pk
7、js类的原型:类属性
8、配置全局css样式
import '@/assets/css/global.css'
require('@/assets/css/global.css');
路由知识点概况:
1)路由配置:router/index.js
2)路由跳转与路由渲染:router-link、router-view、$router.push、$router.go
3)路由传参:两种传参
"""
```
## A作业(必做)
```python
"""
1、按照上方 知识点总结 模块,总结今天所学知识点;
2、
Home.vue页面组件显示基本信息:欢迎来到汽车系统
Car.vue页面组件,完成Cars的列表数据渲染
Nav.vue小组件,完成Home与Car页面的导航跳转
3、
CarDetail页面组件,完成某一个汽车详细信息的渲染
(Car页面点击具体的car进入详情页,把点击的car的主键传入到详情页)
"""
```
## B作业(选做)
```python
"""
1、预习vue前后台交互插件:axios
"""
```
作业
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>作业</title>
<style>
body, h2 {
margin: 0;
}
.wrap {
width: 880px;
margin: 0 auto;
}
.wrap:after {
content: '';
display: block;
clear: both;
}
.box {
width: 200px;
border-radius: 10px;
overflow: hidden;
background-color: #eee;
float: left;
margin: 10px;
}
.box img {
width: 100%;
height: 240px;
}
.box h2 {
text-align: center;
font-weight: normal;
font-size: 20px;
}
.nav, h2 {
text-align: center;
}
.active {
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<div class="nav">
<button @click="page = 'tv'" :class="{active: page === 'tv'}">tv</button>
<button @click="page = 'phone'" :class="{active: page === 'phone'}">phone</button>
</div>
<div class="wrap" v-if="page === 'tv'">
<tag v-for="tv in ad_data.tv" :ad="tv" :key="tv.title" @action="change_select"></tag>
</div>
<!-- v-for指令,需要给循环的标签或组件添加 key 属性,完成缓存的建立 -->
<div class="wrap" v-else-if="page === 'phone'">
<tag v-for="phone in ad_data.phone" :ad="phone" :key="phone.title" @action="change_select"></tag>
</div>
<h2 class="footer">{{ select_ad }}</h2>
</div>
</body>
<script src="js/vue.js"></script>
<script>
ad_data = {
tv: [
{img: 'img/tv/001.jpg', title: 'tv1'},
{img: 'img/tv/002.jpg', title: 'tv2'},
{img: 'img/tv/003.jpg', title: 'tv3'},
{img: 'img/tv/004.jpg', title: 'tv4'},
],
phone: [
{img: 'img/phone/100.jpg', title: 'phone1'},
{img: 'img/phone/200.jpg', title: 'phone2'},
{img: 'img/phone/300.jpg', title: 'phone3'},
{img: 'img/phone/400.jpg', title: 'phone4'},
]
};
let tag = {
props: ['ad'],
template: `
<div class="box" @click="send_ad(ad)">
<img :src="ad.img" alt="">
<h2>{{ ad.title }}</h2>
</div>
`,
methods: {
send_ad(ad) {
this.$emit('action', ad);
}
}
};
new Vue({
el: '#app',
data: {
ad_data,
page: 'tv',
select_ad: '未选中'
},
components: {
tag,
},
methods: {
change_select(ad) {
// this.select_ad = ad.title + '被选中';
this.select_ad = `${ad.title}被选中`;
}
}
})
</script>
</html>
js原型补充
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
</div>
</body>
<script src="js/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
}
})
</script>
<script>
function A() {}
let a1 = new A();
let a2 = new A();
// 为A类添加原型 => 类似于类属性
A.prototype.num = 100;
console.log(a1.num);
console.log(a2.num);
// ES6语法下类
class B {
constructor(name) {
this.name = name;
}
}
let b1 = new B('Tom');
let b2 = new B('Ben');
B.prototype.count = 666;
console.log(b1.count);
console.log(b2.count);
console.log(b1.name);
console.log(b2.name);
// 推导
Vue.prototype.$ajax = 12345;
// this.$ajax
</script>
</html>
router——index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Course from '../views/Course'
import CourseDetail from '../views/CourseDetail'
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/home',
redirect: '/', // 路由的重定向
},
{
path: '/course',
name: 'course',
component: Course
},
{
// 第一种路由传参
// path: '/course/detail',
// 第二种路由传参
path: '/course/:pk/detail',
name: 'course-detail',
component: CourseDetail
}
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
});
export default router
store——index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {}
})
views—main.js
// import 别名 form '资源'
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
Vue.config.productionTip = false;
// 配置全局样式:@就代表src文件夹的绝对路径,官方提倡require加载静态文件
// import '@/assets/css/global.css'
require('@/assets/css/global.css');
// new Vue({
// router,
// store,
// render: h => h(App)
// }).$mount('#app');
new Vue({
el: '#app',
router: router,
store: store,
render: function (read_vue_fn) {
return read_vue_fn(App)
}
});
// 项目的生命周期:
/**
* 1、启动项目,加载主脚本文件 main.js
* 加载Vue环境,创建根组件完成渲染
* 加载系统已有的第三方环境:router、store
* 加载自定义的第三方环境与自己配置的环境:后期项目不断添加
*
* 2、router被加载,就会解析router文件夹下的index.js脚本文件,完成 路由-组件 的映射关系
*
* 3、新建视图组件.vue(在views文件夹中),在路由中配置(在router的index.js中),设置路由跳转(在导航栏组件中Nav.vue)
*/
views—App.vue
<template>
<div id="app">
<!--页面组件占位符-->
<router-view></router-view>
</div>
</template>
components——Nav.vue
<template>
<div class="nav">
<div class="content">
<ul>
<li class="logo">
<img src="@/assets/img/logo.svg" alt="" @click="goHome">
</li>
<li class="route">
<router-link to="/">主页</router-link>
</li>
<li class="route">
<!--<router-link to="/course">课程页</router-link>-->
<router-link :to="{name: 'course'}">课程页</router-link>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: "Nav",
methods: {
goHome() {
// console.log('去向主页');
// console.log(this.$router); // 控制路由跳转
// console.log(this.$route); // 控制路由数据
if (this.$route.path !== '/') {
// this.$router.push('/'); // 往下再跳转一页
this.$router.push({
name: 'home'
});
// this.$router.go(2); // go是历史记录前进后退,正为前进,负为后退,数字为步数
}
}
}
}
</script>
<style scoped>
.nav {
width: 100%;
height: 60px;
background-color: #eee;
}
.content {
width: 1200px;
margin: 0 auto;
/*background-color: red;*/
height: 60px;
}
.content ul li {
float: left;
}
.logo {
padding-top: 10px;
padding-right: 50px;
cursor: pointer;
}
.route {
padding: 15px 10px 0;
}
.route a {
padding-bottom: 5px;
border-bottom: 3px solid transparent;
}
.route a.router-link-exact-active {
color: orange;
border-bottom-color: orange;
}
</style>
components——CourseTag.vue
<template>
<div class="course-tag">
<img :src="course.img" alt="" @click="goDetail(course.id)">
<!--第一种路由传参-->
<!--<router-link :to="`/course/detail?pk=${course.id}`">{{ course.title }}</router-link>-->
<!--<router-link :to="{-->
<!--name: 'course-detail',-->
<!--query: {pk: course.id}-->
<!--}">{{ course.title }}-->
<!--</router-link>-->
<!--第二种路由传参-->
<router-link :to="`/course/${course.id}/detail`">{{ course.title }}</router-link>
</div>
</template>
<script>
export default {
name: "CourseTag",
props: ['course'],
methods: {
goDetail(pk) {
// this.$router.push(`/course/detail?pk=${pk}`);
this.$router.push({
name: 'course-detail',
query: {pk: pk}
});
}
}
}
</script>
<style scoped>
.course-tag {
width: 200px;
border-radius: 10px;
overflow: hidden;
background-color: #eee;
float: left;
margin: 10px;
}
.course-tag img {
width: 100%;
height: 240px;
}
.course-tag a {
text-align: center;
font-weight: normal;
font-size: 20px;
display: block;
}
</style>
DAY69
课堂笔记
## 复习
```python
"""
1、环境
node:官网下载安装包,傻瓜式安装 - https://nodejs.org/zh-cn/ => 附带按照了npm
cnpm:npm install -g cnpm --registry=https://registry.npm.taobao.org
vue/cli:cnpm install -g @vue/cli
2、项目创建
cd 存放项目的目录
vue create 项目名 => 需要安装的组件babel、vue-router、vuex
3、配置项目启动
pycharm打开项目,配置npm启动
4、main.js完成vue环境的加载、完成根组件的渲染、加载vue-router、vuex等环境、加载自定义环境
5、vue-router配置路由:
<router-link to=""></router-link> | this.$router.push() 完成跳转
<router-view /> 完成页面组件的占位
在router/index.js中 完成路由配置 路径-视图组件 映射关系
两种路由传参
配置 跳转 获取
path:'/user' to="/user?pk=1" $route.query.pk
path:'/user/:pk' to="/user/1" $route.params.pk
:to="{name: 'user'}"
6、组件生命周期钩子:组件从创建到销毁的整个生命周期中特殊时间节点回调的方法
created(){完成后台数据的请求}
mounted(){完成极其耗时的后台数据请求}
7、js原型
Vue.prototype.count = 100
所有Vue实例都可以访问count
"""
```
## vue的ajax插件:axios
```python
"""
1)安装插件(一定要在项目目录下):
>: cnpm install axios
2)在main.js中配置:
import axios from 'axios'
Vue.prototype.$axios = axios;
3)在任何一个组件的逻辑中发送ajax请求:
this.$axios({
url: 'http://127.0.0.1:8000/cars/',
method: 'get',
}).then(response => {
console.log(response);
// this.cars = response.data;
}).catch(error => { // 网络状态码为4xx、5xx
console.log(error);
});
"""
```
## CORS跨域问题(同源策略)
```python
"""
同源:http协议相同、ip服务器地址相同、app应用端口相同
跨域:协议、ip地址、应用端口有一个不同,就是跨域
Django默认是同源策略,存在跨越问题。
Django的解决方案:
1)Django按照cors模块:
>: pip install django-cors-headers
2)在settings注册模块,配置中间件:
INSTALLED_APPS = [
...
'corsheaders'
]
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware'
]
3)在settings开启允许跨越:
CORS_ORIGIN_ALLOW_ALL = True
"""
```
## Vue配置ElementUI
```python
"""
1)安装插件(一定要在项目目录下):
>: cnpm install element-ui
2)在main.js中配置:
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
3)使用:
灵魂:复制粘贴
"""
```
## Vue配置jq+bs:见其课件
## A作业(必做)
```python
"""
1、整理今天所学知识点
2、将vue知识点系统回顾一下:vue指令、vue成员、vue生命周期钩子、vue项目的请求生命周期、vue文件组件(结构、语法、导入、页面与小组件)、父子组件间的传参(Cars页面渲染多个Car组件)、路由(占位、跳转、传参)、配置各种第三方插件(element、jq+bs、axios)
3、完成基础前后台分类的数据展示类网站
封装导航栏Nav小组件,完成各页面的跳转,在需要导航栏的页面中渲染Nav小组件
在主页Home组件中,写一个轮播图(bs和element都要提供),完成后台数据的轮播展示
将汽车主页数据渲染以及详情页数据渲染的数据,都放在后台(用mysql数据库存储),完成后台数据的渲染,前台父子组件以及组件间的传参
"""
```
## B作业(选做)
```python
"""
1、尝试将bbs重构为前后台分类项目
2、好好预习drf视频(重中之重重)
"""
```
Vue配置bs环境
## 安装插件
#### jQuery
```
>: cnpm install jquery
```
#### vue/cli 3 配置jQuery:在vue.config.js中配置(没有,手动项目根目录下新建)
```js
const webpack = require("webpack");
module.exports = {
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
Popper: ["popper.js", "default"]
})
]
}
};
```
#### BootStrap
```
>: cnpm install bootstrap@3
```
#### vue/cli 3 配置BootStrap:在main.js中配置
```js
import "bootstrap"
import "bootstrap/dist/css/bootstrap.css"
```
前后端分离跨域交互
## 分离的前后台交互
### 后台处理跨域
##### 安装插件
```
>: pip install django-cors-headers
插件参考地址:https://github.com/ottoyiu/django-cors-headers/
```
##### 项目配置:dev.py
```python
# 注册app
INSTALLED_APPS = [
...
'corsheaders'
]
# 添加中间件
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware'
]
# 允许跨域源
CORS_ORIGIN_ALLOW_ALL = True
```
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false;
// 全局css
require('@/assets/css/global.css');
// 全局js
import settings from '@/assets/js/settings'
Vue.prototype.$settings = settings;
// 配置axios
import axios from 'axios'
Vue.prototype.$axios = axios;
// 配置element-ui
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
// 配置bootstrap,前提要配置jQuery
import "bootstrap"
import "bootstrap/dist/css/bootstrap.css"
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app');
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"]
})
]
}
};
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
//固定五句话
Car.vue
<template>
<div class="car">
<Nav />
<div class="wrap">
<CarTag v-for="car in cars" :car="car" />
</div>
</div>
</template>
<script>
import Nav from '@/components/Nav'
import CarTag from '@/components/CarTag'
export default {
name: "Car",
components: {
Nav,
CarTag,
},
data() {
return {
cars: []
}
},
created() {
// 完成ajax请求后台,获得数据库中的数据
this.$axios({
url: this.$settings.base_url + '/cars/',
method: 'post',
params: { // url拼接参数:任何请求都可以携带
a: 1,
b: 2,
c: 3
},
data: { // 数据包参数:get请求是无法携带的
x: 10,
y: 20,
}
}).then(response => {
// console.log('正常', response);
this.cars = response.data;
}).catch(error => { // 网络状态码为4xx、5xx
console.log('异常', error.response);
});
}
}
</script>
<style scoped>
.wrap {
width: 1100px;
/*background-color: green;*/
margin: 10px auto 0;
}
.wrap:after {
display: block;
content: '';
clear: both;
}
</style>
CarDetail.vue
<template>
<div class="car-detail">
<div v-if="car.msg">
<h1>{{ car.msg }}</h1>
</div>
<div v-else-if="car.id">
<img :src="car.img" alt="">
<h2>{{ car.title }}</h2>
<h3>${{ car.price }}w</h3>
<h3>{{ car.info }}</h3>
</div>
</div>
</template>
<script>
export default {
name: "CarDetail",
data() {
return {
car: {}
}
},
created() {
// 拿到路由传递来的car主键
let pk = this.$route.query.pk || this.$route.params.pk;
// 主键不存在,就直接结束方法
if (!pk) return false;
// 主键存在才请求后台
this.$axios({
url: this.$settings.base_url + `/car/${pk}/`,
}).then(response => {
this.car = response.data
}).catch(error => {
console.log(error.response)
})
}
}
</script>
<style scoped>
.car-detail {
/* vw:屏幕宽度 vh:屏幕高度*/
/*width: 100vw;*/
/*height: 100vh;*/
/*background-color: orange;*/
}
</style>
Element.vue
<template>
<div class="element">
<h1>element-ui组件</h1>
<hr>
<el-row type="flex" :gutter="20" justify="center">
<el-col :span="6">
<div class="grid-content bg-purple"></div>
</el-col>
<!--<el-col :span="8">-->
<!--<div class="grid-content bg-purple-light"></div>-->
<!--</el-col>-->
<el-col :span="6" :offset="8">
<div class="grid-content bg-purple"></div>
</el-col>
</el-row>
<hr>
<el-container>
<el-aside width="200px">Aside</el-aside>
<el-container>
<el-header>Header</el-header>
<el-main>Main</el-main>
<el-footer>Footer</el-footer>
</el-container>
</el-container>
<hr>
<i class="icon el-icon-platform-eleme"></i>
<hr>
<el-row>
<el-button @click="fn" round>圆角按钮</el-button>
<el-button type="primary" round>主要按钮</el-button>
<el-button type="success" round>成功按钮</el-button>
<el-button type="info" round>信息按钮</el-button>
<el-button type="warning" round>警告按钮</el-button>
<el-button type="danger" round>危险按钮</el-button>
</el-row>
<hr>
<el-carousel indicator-position="outside">
<el-carousel-item v-for="item in 4" :key="item">
<h3>{{ item }}</h3>
</el-carousel-item>
</el-carousel>
<hr>
<h2>bootstrap环境</h2>
<i class="btn btn-primary">按钮</i>
<div class="dropup">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu2" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
Dropup
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
</template>
<script>
export default {
name: "Element",
methods: {
fn() {
/*
this.$message({
message: '弹出框',
type: 'warning',
duration: 1000,
showClose: true,
onClose: () => {
this.$message('弹出框关闭了')
}
})
*/
this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
center: true
}).then(() => {
this.$message({
type: 'success',
message: '删除成功!'
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
}
}
</script>
<style scoped>
.el-carousel__item h3 {
color: #475669;
font-size: 18px;
opacity: 0.75;
line-height: 300px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}
.el-carousel__item:nth-child(2n+1) {
background-color: #d3dce6;
}
.icon {
font-size: 100px;
color: orange;
}
.grid-content {
height: 60px;
}
.bg-purple-dark {
background: #99a9bf;
}
.bg-purple {
background: #d3dce6;
}
.bg-purple-light {
background: #e5e9f2;
}
.el-header, .el-footer {
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
line-height: 160px;
}
body > .el-container {
margin-bottom: 40px;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
</style>
Home.vue
<template>
<div class="home">
<Nav />
<h1>
<span @click="goCarPage">欢迎来到汽车系统</span>
</h1>
</div>
</template>
<script>
import Nav from '../components/Nav'
export default {
name: "Home",
components: {
Nav
},
methods: {
goCarPage() {
if (this.$route.path !== '/car') {
this.$router.push('/car')
}
}
}
}
</script>
<style scoped>
h1 {
/*background-color: red;*/
text-align: center;
margin-top: 160px;
}
h1 span {
/*background-color: orange;*/
cursor: pointer;
font: bold 60px/70px 'STSong';
}
</style>
router——index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home'
import Car from '../views/Car'
import CarDetail from '../views/CarDetail'
import Element from '../views/Element'
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/car',
name: 'car',
component: Car
},
{
path: '/car/detail/:pk',
name: 'car-detail',
component: CarDetail
},
{
path: '/element',
name: 'element',
component: Element
}
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
});
export default router
store——index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
components——Nav.vue
<template>
<div class="nav">
<ul>
<li>
<router-link to="/">主 页</router-link>
</li>
<li>
<router-link to="/car">汽 车</router-link>
</li>
<li>
<router-link to="/element">饿 了 么</router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "Nav"
}
</script>
<style scoped>
.nav {
height: 60px;
background-color: #eee;
}
.nav ul {
width: 1100px;
margin: 0 auto;
}
.nav li {
float: left;
padding: 15px 20px 0;
}
.nav a {
border-bottom: 3px solid transparent;
padding-bottom: 2px;
}
.nav a.router-link-exact-active {
color: orange;
border-bottom-color: orange;
}
</style>
components——CarTag.vue
<template>
<div class="car-tag">
<router-link :to="`/car/detail/${car.id}`">
<img :src="car.img" alt="">
<h3>
<span>{{ car.title }}</span>
</h3>
</router-link>
</div>
</template>
<script>
export default {
name: "CarTag",
props: ['car'],
}
</script>
<style scoped>
.car-tag {
/*border: 1px solid black;*/
border-radius: 10px;
overflow: hidden;
width: 200px;
/*height: 280px;*/
float: left;
margin-right: 25px;
margin-bottom: 25px;
background-color: beige;
cursor: pointer;
}
.car-tag a.router-link-active {
display: block;
}
.car-tag:nth-child(5n) {
margin-right: 0;
}
.car-tag img {
width: 200px;
height: 125px;
}
.car-tag h3 {
margin: 5px auto;
text-align: center;
}
</style>
Django后端app文件夹(admin.py)
from django.contrib import admin
from . import models
admin.site.register(models.Car)
Django后端(apps.py)
from django.apps import AppConfig
class AppConfig(AppConfig):
name = 'app'
Django后端app文件夹(models.py)
from django.db import models
class Car(models.Model):
title = models.CharField(max_length=64)
price = models.DecimalField(max_digits=11, decimal_places=2)
img = models.ImageField(upload_to='car', default='default.jpg')
info = models.TextField()
class Meta:
db_table = 'old_boy_car'
verbose_name = '汽车'
verbose_name_plural = verbose_name
def __str__(self):
return self.title
Django后端app文件夹(views.py)
from django.http import JsonResponse
from django.conf import settings
from . import models
def get_cars(request, *args, **kwargs):
# print(request.method)
# print(request.GET)
# print(request.POST)
# print(request.body)
# return JsonResponse({'msg': 'get ok'})
car_query = models.Car.objects.values('id', 'title', 'img')
car_list = list(car_query)
for car in car_list:
car['img'] = '%s%s%s' % ('http://localhost:8000', settings.MEDIA_URL, str(car.get('img')))
return JsonResponse(car_list, safe=False)
def get_car(request, *args, **kwargs):
pk = kwargs.get('pk')
car_obj = models.Car.objects.filter(pk=pk).values('id', 'title', 'img', 'price', 'info').first()
if car_obj:
car_obj['img'] = '%s%s%s' % ('http://localhost:8000', settings.MEDIA_URL, str(car_obj.get('img')))
return JsonResponse(car_obj, json_dumps_params={'ensure_ascii': False})
return JsonResponse({'msg': '数据不存在'})
Django后端d-proj文件夹urls文件
from django.conf.urls import url
from django.contrib import admin
from django.views.static import serve
from django.conf import settings
from app import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^cars/$', views.get_cars),
url(r'^car/(?P<pk>\d+)/$', views.get_car),
url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
]
Django后端d-proj文件夹settings文件
注掉csrf中间件
# 'django.middleware.csrf.CsrfViewMiddleware',
# 打开跨越
CORS_ORIGIN_ALLOW_ALL = True
# ap:国际化配置
# TODO 国际化配置
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = False
# media
MEDIA_URL = '/media/'
# 项目media文件夹的绝对路径
MEDIA_ROOT = os.path.join(BASE_DIR, 'media'