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="/">主&nbsp;页</router-link>
            </li>
            <li>
                <router-link to="/car">汽&nbsp;车</router-link>
            </li>
            <li>
                <router-link to="/element">饿&nbsp;了&nbsp;么</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'