一、Vue知识点

1.Vue

1.1 前端发展历史

html(5)+css(3)+javascript(ECMA:5,补充es6语法,最新13,bom:浏览器对象,dom:文档对象)
编写一个页面–》给后端(python,Java,Go)–》后端嵌入模板语法–》后端渲染完数据–》返回给前端展示。

Ajax的出现–》后台发送异步请求

单用Ajax:前后端分离的雏形

Angular框架的出现:出现了“前端工程化”的概念,即前端也是一个工程项目

React,Vue框架:当下比较火的的前端框架(Vue:国内,中小厂用,React:外国,大厂用)

移动开发(Android+IOS)+Web(web+微信小程序)+桌面开发(windows桌面,开发软件):大前端

一套代码,多端运行:谷歌Flutter平台(Dart语言编写,与Java相似)可以运行在IOS,Android,PC端

在Vue框架基础上,uni-app:一套编码在各个平台都能使用

1.2 Vue介绍

是一个js框架,jquery也是一个js框架。
是一个渐进式框架,可以单个页面使用vue也可以整个项目使用
Vue版本:

  • 2.x:老版本
  • 3.x:完整支持ts语法
    M-V-VM思想:
  • Django:MTV
  • MVP:移动端会使用
  • Vue:M-V-VM架构
    -Model:vue对象的data属性里面的数据,这里的数据要显示到页面中,js里面有变量
    -View:vue中数据要显示的HTML页面,在vue中,也称之为“视图模板” (HTML+CSS)
    -ViewModel:vue中编写代码时的vm对象,它是vue.js的核心,负责连接 View 和 Model数据的中转,保证视图和数据的一致性,所以前面代码中,data里面的数据被显示中p标签中就是vm对象自动完成的(双向数据绑定:JS中变量变了,HTML中数据也跟着改变)
    组件化开发、单页面开发:
    -组件化开发:把某些可能会多次使用的 htm,css,js,写成单独的,以后直接引入即可
    -单页面开发:如果是vue项目,整个项目其实就一个 index.html 页面
    -以后都是只有一个index.html 看到的页面变化,不是多个html页面在变化,而是组件的替换

在这里插入图片描述

2 Vue的快速使用

补充:工欲善其事必先利其器—》咱们要开发vue,需要有一个比较趁手 集成开发工具(IDE)
-vscode:微软出的,不仅可以写前端,还可以写python,go… 免费的
-Jetbrains捷克的公司公司出的:全家桶:pycharm,goland,IDEA(java),phpstorm,webstorm(前端)。。。
-收费,挺贵 全家桶的授权:599刀一年 单版本授权 199刀 一年
-破解:pycharm本身跟webstorm师出同门
-直接使用Pycharm—》vue的插件,就可以写vue了----》讲课用,不需要再多下一个编辑器
-直接下载webstorm–》破解方案跟pycharm完全一样

使用Pycharm开发—》下载后有vue代码提示,不下也能开发vue
-新建一个项目(python项目也可以)
-装一个vue的插件:setting中搜plugins—》vue—》安装—》ok—》apply
Vue 就是一个js框架----》把源代码下载下来(cdn),引入到页面中去
-先用vue2的讲:基础内容是一样的
-拿到vue2的源码,放在咱们工程中–》js文件夹下vue.js

在这里插入图片描述

2.1第一个vue项目

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- 引入vue,跟之前引入jquery是一样的-->
    <script src="./js/vue.js"></script>
    <title>标题</title>
</head>
<body>
<div id="app">
    <!--以后在这div内部,就可以写vue的语法了,插值语法,把变量放在{{}}内,它就会把变量渲染在这-->
    <h1>{{name}}</h1>
</div>
</body>
<script>
    // 写js代码,new 得到一个vue对象,传入配置项,传入一个对象,有key,有value
    new Vue({
        el: '#app', // 根据id 找到div,这个div就被vue托管了,以后div中就可以写vue的语法了
        data: {
            name: 'lqz'  // 定义了一个变量 name
        }
    })
</script>
</html>

3 模版语法

# {{}} //插值语法,里面可以放变量/函数/短的表达式
# json 格式:字符串   {"name":"lqz","age":19}
# python 中字典      {'name':'lqz','age':19}
# js 对象(一般不叫字典) {name:"lqz",age:19}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>
    <title>标题</title>
</head>
<body>
<div id="app">
    <h1>渲染变量</h1>
    <p>我的名字:{{name}}</p>
    <p>我的年龄:{{age}}</p>
    <p>数组:{{l}}</p>
    <p>数组取值:{{l[1]}}</p>  //取列表第二个值
    <p>对象:{{obj}}</p>
    <p>对象取值:{{obj['age']}}</p>
    <p>对象取值:{{obj.name}}</p>
    <p>标签:{{s}}</p>
    <h1>渲染函数--后面讲</h1>
    <h1>渲染表达式:三目运算符,一定不要写太长</h1>
    <p>{{age > 20 ? '男人' : '男孩'}}</p>
    <p>{{age == 19}}</p>
</div>
</body>
<script>
    new Vue({
        el: '#app',
        data: {
            name: 'lqz',
            age: 19,
            l: [1, 2, 3], // js中叫数组,python中叫列表
            obj: {name: '彭于晏', age: 40},  // js中叫对象,python中叫字典  对象取值不加引号表示变量
            s: '<input type="text">',
            t: 10 > 9 ? '大于' : '小于'  // 跟python中的三元表达式是一样的  t= 条件 ? '符合条件':'不符合'
            // t:'大于'
        }
    })
</script>
</html>

运行结果:
在这里插入图片描述

4 指令

# vue中有很多指令,放在标签上,以v-开头的,称之为指令

<p v-html='js变量,函数,表达式'> </p>

4.1 文本指令(操作文本相关)

# v-html:把变量的内容当html渲染到标签中去(字符串是标签,会完整渲染)

# v-text:把变量内容当字符串写到到标签中(字符串是标签,不会渲染成标签)
    -可以完成跟 {{}} 一样的功能,但是还是不一样的

# v-show:只能跟 true  或 false  或   表达式运算结果是布尔类型,控制标签的显示与否
        
# v-if :只能跟 true  或 false  或   表达式运算结果是布尔类型,控制标签的显示与否

# vue中面试题:v-if和v-show区别是什么?
    -v-if:如果是false,不显示,标签也不存在(删除和添加标签,效率低)
    -v-show,如果是false,不显示,但是标签存在,只是通过样式 dispaly=none控制的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>
    <title>标题</title>
</head>
<body>
<div id="app">
    <h1>v-html</h1>
    <p>{{s}}</p>
    <p v-html="s"></p>
    <div v-html="s"></div>
    <h1>v-test</h1>
    <p v-text="s">美女</p>
    <h1>v-show和v-if</h1>
    <div v-show="b2">美女</div>
    <div v-if="b1">帅哥</div>
</div>
</body>
<script>
    new Vue({
        el: '#app',
        data: {
            s: '<input type="text">',
            b1: true,
            b2: false
        }
    })
</script>
</html>

运行结果:
在这里插入图片描述

补充:MVVM:model的数据变,view也跟着变;只要view变化,model也跟着变化

# 双向数据绑定
# 把new Vue后的对象赋值给变量vm
  var vm = new Vue({
          el: '#app',
          data: {
              s: '<input type="text">',
              b1: true,
              b2: false
          }
      })

以后从vm中可以通过 vm._data 取到 实例化的时候的data
以后也可以从vm.变量名取到data中的变量
在控制台修改变量的值,页面会立马跟着变化 —》以后只需要修改变量值即可,不需要操作dom了

在这里插入图片描述

4.2 事件指令

# v-on:事件名='函数'    给这个标签绑定一个事件,当触发这个事件,就会执行函数

        -事件:click,blur,dbclick。。。
           -函数 必须写在methods 对象内,可以使用es6的对象写法
           
# 重点:
v-on:事件名='函数'    可以简写成      @事件名='函数'(以后都用它)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="./js/vue.js"></script>
    <title>标题</title>
</head>
<body>
<div id="app">
<!--    <button class="btn btn-danger" v-on:click="handleClick">点我看美女</button>-->
    <button class="btn btn-danger"  @click="handleClick">点我看美女2</button>
    <br>
<!--    写个按钮,一点击就显示美女图片,再点击一次就不显示了-->
    <button @click="handleShow">看我美女显示和消失</button>
    <br>
<!--    <img v-show="zs" src="https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg" alt="" height="500px" width="500px">-->
    <img v-if="zs" src="https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg" alt="" height="500px" width="500px">
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            zs:true,
        },   // 变量写在这里
        methods: {
            // 方式一:es5的语法
            // handleClick: function () {
            //     alert('美女')
            // }
            // 方式二:常用的,es6的语法
            handleClick() {
                alert('美女')
            },
            handleShow(){
                // 修改show的值为  !show
                // this代指的是vm对象,Vue对象
                this.zs=!this.zs
            }
        }, // 函数写在这里
    })
    // es6 语法的对象写法
    // var obj = {'name': 'lqz', 'age': 19}
    // var obj1 = {name: 'lqz', age: 19}
    //
    // name = 'lqz'
    // age = 19
    // var onj2 = {name, age}  // 等同于{name: 'lqz', age: 19}  es6 对象写法
</script>
</html>

4.3 属性指令

# v-bind:属性名="变量"
-标签会有很多属性 <a href=""></a>   <img src="" >  <p name="xxx"></p> <button class="btn">点我</button>

-可以绑定标签的任意属性
-v-bind可以简写成 : -----> :属性='变量'
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>
    <title>标题</title>
</head>
<body>
<div id="app">
    <!--    <img v-bind:src="url" alt="">-->
    <h1>点我随机弹美女图片</h1>
    <button @click="handleClick">点我</button>
    <br>
<!--    <img v-bind:src="url" alt="" width="500px" height="500px">-->
    <img :src="url" alt="" width="500px" height="500px">
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            url: 'https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg',
            l: ['https://img2.woyaogexing.com/2022/10/13/05e406595e217e0c!400x400.jpg',
                'https://img2.woyaogexing.com/2022/10/13/c03408591b068c18!400x400.jpg',
                'https://img2.woyaogexing.com/2022/10/13/f810d999375f7f1c!400x400.jpg']
        },
        methods: {
            handleClick() {
                // 随机从生成0--3的数字
                this.url = this.l[Math.floor(Math.random()*3)];
            }
        }
    })
</script>
</html>

5 style和class属性

# 属性指令:style和class属性特殊一点


#  // class属性可以绑定:字符串,数组(常用,class由多个类组成,数组跟它最搭),对象
#  // style 属性可以绑定: 字符串,数组,对象(常用)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>
    <title>标题</title>
    <style>
        .red {
            color: crimson;
        }
        .back {
            background: greenyellow;
        }
        .size {
            font-size: 50px;
        }
    </style>
</head>
<body>
<div id="app">
    <h1>class的三种绑定方式</h1>
    <!--    <div :class="class_str">-->
    <!--    <div :class="class_list">-->
    <div :class="class_obj">
        我是一个div
    </div>
    <hr>
    <h1>style的三种绑定方式</h1>
    <!--    <div style="font-size: 50px;background: pink;color: green">-->
    <!--    <div :style="style_str">-->
    <!--    <div :style="style_list">-->
    <div :style="style_obj">
        我是第二个div
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            // class:字符串,数组(常用,class由多个类组成,数组跟它最搭),对象
            class_str: 'red size',
            class_list: ['red', 'size'], // 如果咱么向数组末尾最近一个类名,div样式就变了
            class_obj: {red: true, size: false, back: false},
            // style :字符串,数组,对象
            style_str: 'font-size: 50px;background: pink',
            style_list: [{'font-size': '50px'}, {'background': 'pink'}, {'color': 'green'}],
            // style_list: [{fontSize: '50px'}, {background: 'pink'}, {color: 'green'}], // 跟上面一样,如果是 - 相连的两个单词可以改成驼峰形式
            style_obj: {fontSize: '50px', background: 'pink', color: 'green'}, // style 来讲,它用的多
        },
        methods: {}
    })
</script>
</html>

6 条件渲染

# 指令:实现符合某个条件,就显示某个标签
v-if  v-else-if   v-else

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>
    <title>标题</title>
    <style>
    </style>
</head>
<body>
<div id="app">
    <p v-if="score>90">优秀</p>
    <p v-else-if="score>70 && score<=90">良好</p>
    <p v-else-if="score>60 && score<=70">及格</p>
    <p v-else>不及格</p>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            score: 98,
        },
    })
</script>
</html>

7 列表渲染

# v-for 指令
    -可以循环:数组   v-for="(url,index) in urls"      位置不能换
  -可以循环:对象   v-for="(value,key) in obj"       如果只接收一个值,这个值就是value
  -可也循环:数字   v-for="i in num"       从1开始,循环到数字的个数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>
    <title>标题</title>
    <style>
    </style>
</head>
<body>
<div id="app">
    <h1>把所有美女,一行行显示在页面中</h1>
    <ul>
        <!--        <li v-for="url in urls">-->
        <li v-for="(url,index) in urls">
            <h3>第{{index + 1}}张美女</h3>
            <img :src="url" alt="" height="100px" width="100px">
        </li>
    </ul>
    <h1>循环对象</h1>
<!--    <p v-for="(value,key) in obj">key值为:{{key}},value值为:{{value}}</p>-->
    <p v-for="value in obj">value值为:{{value}}</p>
    <h1>循环数字</h1>
    <p v-for="i in num">循环到了第:{{i}}</p>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            urls: ['https://img2.woyaogexing.com/2022/10/13/05e406595e217e0c!400x400.jpg',
                'https://img2.woyaogexing.com/2022/10/13/c03408591b068c18!400x400.jpg',
                'https://img2.woyaogexing.com/2022/10/13/f810d999375f7f1c!400x400.jpg'],
            obj: {name: 'lqz', age: 19, bobby: '篮球'} ,  // hash类型  hashmap  map  字典  对象 都是没有顺序
            num:4
        },
    })
</script>
</html>

在这里插入图片描述

8 使用v-if和v-for写个购物车显示与不显示的案例

实现点击按钮显示购物车表格:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

    <title>标题</title>

</head>
<body>


<div id="app">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <div v-if="!good_list.length==0">
                    <table class="table table-striped table-bordered">
                        <thead>
                        <tr>
                            <th>商品id号</th>
                            <th>商品名字</th>
                            <th>商品价格</th>
                            <th>商品数量</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr v-for="good in good_list">
                            <th scope="row">{{good.id}}</th>
                            <td>{{good.name}}</td>
                            <td>{{good.price}}</td>
                            <td>{{good.num}}</td>
                        </tr>

                        </tbody>

                    </table>
                </div>
                <div v-else>
                    空空如也
                </div>

                <hr>
                <button @click="handleClick">点我刷新购物车</button>
            </div>

        </div>


    </div>


</div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            good_list: []
        },
        methods: {
            handleClick() {
                // 跟后端交互,拿到了数据
                this.good_list = [
                    {id: 1, name: '小汽车', price: 100000, num: 1},
                    {id: 2, name: '钢笔', price: 6, num: 10},
                    {id: 3, name: '脸盆', price: 12, num: 6},
                    {id: 4, name: '水杯', price: 66, num: 5},
                ]

            }
        }
    })

</script>

</html>

9 v-model数据双向绑定

只针对input框有用
#text文本类型的双向数据绑定
-使用 :value=‘变量’ 单向数据绑定,页面变化,变量不会跟着变
-使用 v-model=‘变量’ 双向数据绑定,页面变化,变量变化都会相互影响

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

    <title>标题</title>

</head>
<body>


<div id="app">

    <h1>v-model 只针对于input</h1>
    请输入内容:<input type="text" v-model="v"> ---->{{v}}


</div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            v: '美女'
        },
    })

</script>

</html>

10 事件处理

    事件:click, dbclick   blur,   input,      change。。。
           单击   双击   失去焦点   输入内容      发生变化
  # input框会有blur, input, change 事件
blur和change的区别:
blur:失去焦点触发
change:内容发射变化时触发
input:输入内容就会触发
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>

    <title>标题</title>

</head>
<body>


<div id="app">

    <h1>失去焦点事件blur</h1>
    <!--    请输入名字:<input type="text" v-model="name" @blur="handleBlur">-->
    <h1>change事件:数据发生变化才会触发</h1>
    <!--    请输入名字:<input type="text" v-model="name" @change="handleChange">-->
    <h1>input事件:只要输入内容会触发</h1>
    请输入名字:<input type="text" v-model="name" @input="handleInput">


</div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: '彭于晏'
        },
        methods: {
            handleBlur() {
                alert(this.name)
            },
            handleChange() {
                console.log(this.name)  // 跟python中print一样
            },
            handleInput(){
                console.log(this.name)
            }
        }
    })

</script>

</html>

10.1 事件处理–过滤案例

实现输入查询的字母,过滤出前面与查询字母匹配的所有结果

// 补充:数组的内置方法,filter,传匿名函数进去,匿名函数如果返回true这个就保留,如果返回false,就不保留

// var search = 'a'
// var l = ['a', 'at', 'atom', 'atommon', 'be', 'beyond', 'cs', 'csrf', 'csrffe']
// var ll = l.filter(function (item) {
//     return item.indexOf(search) > -1
// })
// console.log(ll)

// 补充:字符串有个indexOf,返回索引,如果大于-1,表示字字符串在当前字符串中
// var s='lqz is handsome'
// var res=s.indexOf('zoo') // 如果me在字符串中,就返回me在字符串的索引位置
// console.log(res)


// es6 的箭头函数
// 传统写法
// var a=function (name,age){
//     console.log(name)
// }
// a("lxx")
// //es6 箭头函数  匿名函数的另一种写法
//  var a=  (name,age) =>{
//     console.log(name)
// }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>

    <title>标题</title>

</head>
<body>


<div id="app">

    <h1>过滤案例</h1>
    <input type="text" v-model="search" @input="handleInput">
    <ul>
        <li v-for="item in newdataList">{{item}}</li>
    </ul>


</div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            search: '',
            dataList: ['a', 'at', 'atom', 'atommon', 'be', 'beyond', 'cs', 'csrf', 'csrffe'],
            newdataList: ['a', 'at', 'atom', 'atommon', 'be', 'beyond', 'cs', 'csrf', 'csrffe']
        },
        methods: {
            handleInput() {
                // this 指向问题
                // 这个位置this是vue对象
                // var _this = this
                // this.dataList = this.dataList.filter(function (item) {
                //     console.log('----', _this) // 这个位置this本来是浏览器对象,赋值外面的this给_this才能使用外面Vue对象的this
                //     return item.indexOf(_this.search) > -1
                // })

                // 使用es6的语法解决
                this.newdataList = this.dataList.filter(item => {
                    // console.log('----', this) // 如果使用剪头函数,this还是vue(剪头函数没有自己的this)
                    return item.indexOf(this.search) > -1
                })
            }
        }
    })



</script>

</html>

11 事件修饰符

# 放在事件后的
@click.once='函数'

.stop        只处理自己的事件,不再冒泡给父标签(阻止事件冒泡)
.self        只处理自己的事件,子控件冒泡的事件不处理
.prevent    阻止a链接的跳转
.once        事件只会触发一次(适用于抽奖页面)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>

    <title>标题</title>

</head>
<body>


<div id="app">

    <h1>点击子标签,父标签的事件也触发:事件冒泡</h1>
    <h2>阻止事件冒泡:点子标签,父标签不触发 stop</h2>
    <ul @click="handleUl">
        <li @click.stop="handleLi">点我看美女</li>
        <li>点我看帅哥</li>
    </ul>

    <h1>点击子标签,父标签的事件也触发:事件冒泡</h1>
    <h2>子标签的冒泡不处理:父标签写self,父标签只处理自己的事件,冒泡的事件不管</h2>
    <ul @click.self="handleUl">
        <li @click="handleLi">点我看美女</li>
        <li>点我看帅哥</li>
    </ul>

    <h1>prevent 阻止a链接的跳转</h1>
    <a href="http://www.liuqingzheng.top" @click.prevent="handleA">点我看美女</a>

    <h1>once 只执行一次</h1>
    <button @click.once="handleButton">点我秒杀</button>


</div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleLi() {
                console.log("li被点击了")
            },
            handleUl() {
                console.log("ul被点击了")
            },
            handleA() {
                console.log('a被点击了,不会再跳转了')
            },
            handleButton() {
                alert('秒杀成功')
            }
        }
    })

</script>

</html>

12 按键修饰符

# 事件:input,change   除此之外还有 【按键】被按下和被抬起的事件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>

    <title>标题</title>

</head>
<body>


<div id="app">

    <h1>按键修饰符</h1>
    
<!--    <input type="text" @keyup="handleKeyUp($event)">    摁键抬起时触发-->
<!-- 只有摁enter键才触发 -->
    <input type="text" @keyup.enter="handleKeyUp($event)">
    <input type="text" @keyup.esc="handleKeyUp($event)">
    <input type="text" @keyup.="handleKeyUp($event)">


</div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {},
        methods:{
            handleKeyUp(event){
                console.log('sdasfd')
               if(event.code=='Enter') {
                   console.log('enter键被抬起了,开始搜索')
               }
            }
        }

    })

</script>

</html>

13 表单控制

# form表单---》input标签,单选,多选按钮


# 1 checkbox的单选---》v-model绑定一个布尔值---》只要选中布尔就为true,反之亦然
# 2 radio的单选----》v-model绑定字符串----》选中字符串就是value对应的值
# 3 checkbox的多选---》v-model绑定一个数组---》多个选中,数组就有多个值
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>表单控制之checkbox单选</h1>

        <p>用户名:<input type="text" v-model="username"></p>
        <p>密码:<input type="password" v-model="password"></p>
        <p><input type="checkbox" v-model="isCheck">记住密码</p>
        <p>
            <input type="radio" v-model="gender" value="1"><input type="radio" v-model="gender" value="2"><input type="radio" v-model="gender" value="0">未知
        </p>
        <p>爱好(多选):</p>
        <p>
            <input type="checkbox" v-model="hobby" value="篮球"> 篮球
            <input type="checkbox" v-model="hobby" value="足球"> 足球
            <input type="checkbox" v-model="hobby" value="橄榄球"> 橄榄球
            <input type="checkbox" v-model="hobby" value="乒乓球"> 乒乓球
        </p>
<!--        <hr>-->
<!--        密码是否选中:{{isCheck}}-->
<!--        <hr>-->
<!--        性别是:{{gender}}-->
<!--        <hr>-->
<!--        爱好是:{{hobby}}-->

        <hr>
        <input type="submit" value="提交" @click="handleSubmit">



</div>

</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            username: '',
            password: '',
            isCheck: false,
            gender: '',
            hobby:[],
        },
        methods: {
            handleSubmit(){
                //假设发送ajax到后端了
                console.log(this.username)
                console.log(this.password)
                console.log(this.isCheck)
                console.log(this.gender)
                console.log(this.hobby)
            }
        },


    })
</script>
</html>

14 购物车案例

14.1 js的循环方式

# python,js,go,java  for循环的区别

  -python中只for循环有基于迭代的循环,没有基于索引的循环
        for xx in 可迭代对象  # 基于迭代
  -js :
          for xx in 对象  # 基于迭代
        for i=0;i<10;i++  # 基于索引
  -go:
        for i=0;i<10;i++  # 基于索引
        for item range 变量  # 基于迭代
      
  -java:
          for i=0;i<10;i++  # 基于索引  1.8之前只有这种
        for xx in 对象  # 基于迭代   1.8后的语法


# 1 方式一:最基本的
for (let i=0; i<3; i++) {
  console.log(i)
}

# 2 in 循环  es5的语法
for(let 成员 in 对象){
    循环的代码块
  
  
# 3 for of   es6的循环
  for(item of arr){
    console.log('item =>', item)
  }
  
 
# 4 数组foreach循环 (数组)
   var a=[33,22,888]
   a.forEach(function (value,index){
        console.log(value)
        console.log(index)
    })

# 5 jq  $each 循环
$.each(可迭代对象,function (key,value) {
  });
 
var a=[33,22,888]
 // var obj={name:'lqz',age:19}
 $.each(a,function (key,value){
       console.log(key)
       console.log(value)
   })

14.2 基本购物车

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="./js/vue.js"></script>
    <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<div class="app">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <div style="margin-top: 30px">
                    <h1>购物车案例</h1>
                    <table class="table table-bordered">
                        <thead>
                        <tr>
                            <th>商品id</th>
                            <th>商品名字</th>
                            <th>商品价格</th>
                            <th>商品数量</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr v-for="good in goodList">
                            <th>{{good.id}}</th>
                            <td>{{good.name}}</td>
                            <td>{{good.price}}</td>
                            <td>{{good.count}}</td>
                            <td><input type="checkbox" v-model="buyGoods" :value="good"></td>
                        </tr>
                        </tbody>
                    </table>
                    <hr>
                    选中的商品:{{buyGoods}}
                    <hr>
                    总价格是:{{getPrice()}}
                </div>


            </div>

        </div>

    </div>

</div>

</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            goodList: [
                {id: '1', name: '小汽车', price: 150000, count: 2},
                {id: '2', name: '鸡蛋', price: 2, count: 1},
                {id: '3', name: '饼干', price: 10, count: 6},
                {id: '4', name: '钢笔', price: 15, count: 5},
                {id: '5', name: '脸盆', price: 30, count: 3},
            ],
            buyGoods:[],
        },
        methods:{
            getPrice(){
                var total=0
                // 方式一:数组的循环:循环计算选中的商品价格
                // this.buyGoods.forEach(function (v,i){
                //     total+=v.price*v.count
                // })

                // 方式二:es6 的 of 循环
                for (item of this.buyGoods){
                    // console.log(item)
                    total+=item.price*item.count
                }
                return total
            }
        }


    })


    // var a=[33,22,888]
    // a.forEach(function (value,index){
    //     console.log(value)
    //     console.log(index)
    // })
    // 对象没有forEach

    // jq 的循环
   //  var a=[33,22,888]
   //  // var obj={name:'lqz',age:19}
   // $.each(a,function (key,value){
   //     console.log(key)
   //     console.log(value)
   // })
</script>
</html>

14.3 购物车带全选,全不选

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <div style="margin-top: 30px">
                    <h1>购物车案例</h1>
                    <table class="table table-bordered">
                        <thead>
                        <tr>
                            <th>商品id</th>
                            <th>商品名字</th>
                            <th>商品价格</th>
                            <th>商品数量</th>
                            <th><input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr v-for="good in goodList">
                            <th>{{good.id}}</th>
                            <td>{{good.name}}</td>
                            <td>{{good.price}}</td>
                            <td>{{good.count}}</td>
                            <td><input type="checkbox" v-model="buyGoods" :value="good" @change="handleCheckOne"></td>
                        </tr>
                        </tbody>
                    </table>
                    <hr>
                    选中的商品:{{buyGoods}}
                    <hr>
                    总价格是:{{getPrice()}}
                </div>


            </div>

        </div>

    </div>

</div>

</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            goodList: [
                {id: '1', name: '小汽车', price: 150000, count: 2},
                {id: '2', name: '鸡蛋', price: 2, count: 1},
                {id: '3', name: '饼干', price: 10, count: 6},
                {id: '4', name: '钢笔', price: 15, count: 5},
                {id: '5', name: '脸盆', price: 30, count: 3},
            ],
            buyGoods:[],
            checkAll:false,
        },
        methods:{
            getPrice(){
                var total=0
                // 方式二:es6 的 of 循环
                for (item of this.buyGoods){
                    // console.log(item)
                    total+=item.price*item.count
                }
                return total
            },
            handleCheckAll(){
                if(this.checkAll){
                    // 用户全选了,只需要把 buyGoods的值变为goodList
                    this.buyGoods=this.goodList
                }else {
                    this.buyGoods=[]
                }
            },
            handleCheckOne(){
                // 判断buyGoods长度,是否等于goodList,如果等于说明用户全选了,把checkAll设置为true
                // 否则设置为false
                // if(this.buyGoods.l ength==this.goodList.length){
                //     // 说明用户通过单选,选全了
                //     this.checkAll=true
                // }else {
                //     this.checkAll=false
                // }
                // 简写成
                this.checkAll=(this.buyGoods.length==this.goodList.length)
            }
        }


    })

</script>
</html>

14.4 购物车带加减

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <div style="margin-top: 30px">
                    <h1>购物车案例</h1>
                    <table class="table table-bordered">
                        <thead>
                        <tr>
                            <th>商品id</th>
                            <th>商品名字</th>
                            <th>商品价格</th>
                            <th>商品数量</th>
                            <th><input type="checkbox" v-model="checkAll" @change="handleCheckAll"></th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr v-for="good in goodList">
                            <th>{{good.id}}</th>
                            <td>{{good.name}}</td>
                            <td>{{good.price}}</td>
                            <td><button @click="handleJian(good)">-</button>{{good.count}}<button @click="good.count++">+</button></td>
                            <td><input type="checkbox" v-model="buyGoods" :value="good" @change="handleCheckOne"></td>
                        </tr>
                        </tbody>
                    </table>
                    <hr>
                    选中的商品:{{buyGoods}}
                    <hr>
                    总价格是:{{getPrice()}}
                </div>


            </div>

        </div>

    </div>

</div>

</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            goodList: [
                {id: '1', name: '小汽车', price: 150000, count: 2},
                {id: '2', name: '鸡蛋', price: 2, count: 1},
                {id: '3', name: '饼干', price: 10, count: 6},
                {id: '4', name: '钢笔', price: 15, count: 5},
                {id: '5', name: '脸盆', price: 30, count: 3},
            ],
            buyGoods:[],
            checkAll:false,
        },
        methods:{
            getPrice(){
                var total=0
                // 方式二:es6 的 of 循环
                for (item of this.buyGoods){
                    // console.log(item)
                    total+=item.price*item.count
                }
                return total
            },
            handleCheckAll(){
                if(this.checkAll){
                    // 用户全选了,只需要把 buyGoods的值变为goodList
                    this.buyGoods=this.goodList
                }else {
                    this.buyGoods=[]
                }
            },
            handleCheckOne(){
                // 判断buyGoods长度,是否等于goodList,如果等于说明用户全选了,把checkAll设置为true
                // 否则设置为false
                // if(this.buyGoods.length==this.goodList.length){
                //     // 说明用户通过单选,选全了
                //     this.checkAll=true
                // }else {
                //     this.checkAll=false
                // }
                // 简写成
                this.checkAll=(this.buyGoods.length==this.goodList.length)
            },
            handleJian(item){
                if(item.count<=1){
                    alert('太少了,受不了了')
                }else {
                    item.count--
                }
            }
        }


    })

</script>
</html>

15 v-model进阶

# v-model 进阶之 
lazy:双向数据绑定,只要修改输入框的值,就再更新数据,耗费资源,加了lazy后,等不输入了,变量再变化
number:输入框,只接收数字部分,如果输入了  123asdfasd,只保留123 数字部分.如果开头就输入字母则能输入
trim:  去掉输入内容前后的空白
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>v-model进阶</h1>
  <p><input type="text" v-model.lazy="a">{{a}}</p>
  <p><input type="text" v-model.number="b">{{b}}</p>
  <p><input type="text" v-model.trim="c">{{c}}</p>


</div>

</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
          a:'',
          b:'',
          c:'',

        },



    })
</script>
</html>

16 Vue生命周期及自定义组件

 vue的实例:vm
  以及后面学的组件:vc
  它们有生命周期:从创建开始,到销毁
  
  vue中总共生命周期有8个钩子函数(4对),依次调用
  
 # 面向过程编程
  # OOP编程:面向对象编程
  # AOP编程:面向切面编程(对面向对象编程的补充),java的spring框架大量的使用
          -python中装饰器  AOP编程的体现
           -drf源码,反序列化的源码,钩子函数,aop体现
  
  # 钩子的意思:aop的体现
  beforeCreate    创建Vue实例,组件实例对象创建 之前调用
  created    创建Vue实例成功后调用(咱们用的对,可以在此处发送ajax请求后端数据)
  
  beforeMount    渲染DOM之前调用
  mounted    渲染DOM之后调用
  ---初始化完成了----
  
  beforeUpdate    重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
  updated    重新渲染完成之后调用
  ---一直在转圈----
  
  ----销毁组件---
  beforeDestroy    销毁之前调用
  destroyed    销毁之后调用
 

  ##### 组件### :自己写的有html,有样式,有js的好看的可以复用的东西
  -完整看到组件的生命周期
  -vm实例的生命周期看不完整

  

  ###### 重点:
    -使用created多一些:在这里面发送ajax请求,data的数据好了后,再发请求,去后端拿数据
    -updated:数据变化,页面更新完后,执行它
    -destroyed:组件销毁,会触发它,也会用,例如:
        -组件创建了,起了个定时器,不停地打印hello world(每隔一段时间执行一个函数,延迟调用)
          -如果组件销毁了,定时器没有被销毁,会出现定时器还在执行的情况,
        -所以要在destroyed中把定时器取消掉,资源清理工作
    -vm实例和组件实例都有8个生命周期钩子函数
    -只要写了钩子函数,就会执行,不写就不会执行
 
  
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">


    <button @click="handleShow">点我,组件显示和消失</button>
    <hr>
    <lqz v-if="show"></lqz>
    <hr>


</div>

</body>
<script>

    // 定义一个组件  `` es6语法的模版字符串  `lqz is ${变量}`
    Vue.component('lqz', {
            template: `
              <div>
              <h1>我是一个好看的组件{{ name }}</h1>
              <button @click="handleClick">点我看美女</button>
              </div>`,
            data() {
                return {
                    name: '彭于晏',
                    t:'',
                }
            },
            methods: {
                handleClick() {
                    this.name = 'lqz'
                }
            },
            beforeCreate() {
                console.log('beforeCreate')
                console.log(this.$data) // 数据部分
                console.log(this.$el) // 模版
            },
            created() {
                console.log('created')
                console.log(this.$data) // 数据部分
                console.log(this.$el) // 模版
                // 启动一个定时器(实时前后端通信,web微信,开启了定时器一直在向后端发请求拿数据)
                this.t=setInterval(function (){
                    console.log('hello world')
                },3000)   // 过一段时间就执行,一直执行
                // setTimeout() //延迟调用,执行一次
            },
            beforeMount() {
                console.log('beforeMount')
                console.log('当前el状态:', this.$el)
                console.log('当前data状态:', this.$data)
            },
            mounted() {
                console.log('mounted')
                console.log('当前el状态:', this.$el)
                console.log('当前data状态:', this.$data)

            },
            beforeUpdate() {
                console.log('beforeUpdate')
                console.log('当前el状态:', this.$el)
                console.log('当前data状态:', this.$data)
            },
            updated() {
                console.log('updated')
                console.log('当前el状态:', this.$el)
                console.log('当前data状态:', this.$data)
            },
            beforeDestroy() {
                console.log('beforeDestroy')
                console.log('当前el状态:', this.$el)
                console.log('当前data状态:', this.$data)
            },
            destroyed() {
                console.log('destroyed')
                console.log('当前el状态:', this.$el)
                console.log('当前data状态:', this.$data)
                // 释放掉定时器
                clearInterval(this.t)
                this.t=null


            },
        }
    )


    var vm = new Vue({
        el: '.app',
        data: {
            show: true
        },
        methods: {
            handleShow() {
                this.show = !this.show
            }
        },
        // beforeCreate() {
        //     console.log('vm 实力创建之前')
        // },
        // created() {
        //     console.log('vm 实力创建了')
        //
        // }


    })
</script>
</html>

17 前后端交互(ajax,fetch和axios)

 跨域问题: 前后端分离的项目会出现
浏览器有个安全策略:不允许向不同域(地址+端口号)发送请求获取数据,即浏览器的 同源策略
 解决跨域:
后端的cors(跨域资源共享)技术:就是在响应头中加入允许即可
def test(request):
    res=JsonResponse({'name':'lqz','age':19})
    res['Access-Control-Allow-Origin']='*'  //允许任何域发送请求
    return res

nginx做代理。。。
    
    
 # 原生js发送ajax请求,jq发送ajax请求,fetch发送ajax请求,axios发送ajax请求:
    -原生:new XMLHttpRequest()   老api,坑很多
      -jq基于它封装,封装出了$.ajax ,屏蔽了很多问题
      -官方觉得XMLHttpRequest坑很多,搞了个fetch,跟XMLHttpRequest是平级的,比它好用,但是不支持ie
      -axios继续基于XMLHttpRequest封装了一个发送ajax请求的模块

17.1 方式一:使用jq的ajax方法

# 原生js写ajax,jq帮咱们写好了,处理好了浏览器版本间的不兼容,可以直接用

$.ajax({
                    url: 'http://127.0.0.1:8000/test/',
                    type: 'get',
                    success: data => {
                        // 后端返回json格式字符串,$.ajax拿到字符串,转成了js的对象,给了data
                        this.name = data.name
                        this.age = data.age
                    }
                })

17.2 方式二:使用fetch

fetch('http://127.0.0.1:8000/test/').then(res => res.json()).then(res => {
                console.log(res)
                this.name = res.name
                this.age = res.age
            })

17.3 方式三:使用axios(js模块)

  #引入该模块
   <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
 
  
  axios.get('http://127.0.0.1:8000/test/').then(res=>{
            console.log(res.data) // 真正后端给的数据(res.data 才是真正的数据)
            this.name=res.data.name
            this.age=res.data.age
          })

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div class="app">
    <h1>前后端交互</h1>
    <button @click="handleClick">点我,从后端获取数据</button>
    <hr>
    用户名:{{name}}
    <hr>
    年龄:{{age}}


</div>

</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            name: '',
            age: 0
        },
        methods: {
            handleClick() {
                // 发起ajax请求
                $.ajax({
                    url: 'http://127.0.0.1:8000/test/',
                    type: 'get',
                    success: data => {
                        // 后端返回json格式字符串,$.ajax拿到字符串,转成了js的对象,给了data
                        this.name = data.name
                        this.age = data.age
                    }
                })
            }
        },
        created() {
            //方式一:使用jq的ajax发送请求,用的很少
            //   $.ajax({
            //       url: 'http://127.0.0.1:8000/test/',
            //       type: 'get',
            //       success: data => {
            //           // 后端返回json格式字符串,$.ajax拿到字符串,转成了js的对象,给了data
            //           this.name = data.name
            //           this.age = data.age
            //       }
            //   })


            // 方式二:js官方提供了一个fetch方式发送ajax请求
            // var a = function (data) {
            //     return data + 'lqz'
            // }
            // 等价于var a = data => data + 'lqz'

            // fetch('http://127.0.0.1:8000/test/').then(res => res.json()).then(res => {
            //     console.log(res)
            //     this.name = res.name
            //     this.age = res.age
            // })

          // 方式三:axios发送请求
          axios.get('http://127.0.0.1:8000/test/').then(res=>{
            console.log(res.data) // 真正后端给的数据(res.data 才是真正的数据)
            this.name=res.data.name
            this.age=res.data.age
          })
        }


    })
</script>
</html>

17.4 显示电影小案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div class="app">

    <div>
        <ul>
            <li v-for="film in filmsList">
                <h3>电影标题:{{film.name}}</h3>
                <img :src="film.poster" alt="" width="200px" height="400px">
                <p>简介:{{film.synopsis}}</p>
            </li>
        </ul>
    </div>

</div>

</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            filmsList: []
        },
        methods: {},
        created() {
            axios.get('http://127.0.0.1:8000/films/').then(res => {
                this.filmsList=res.data.data.films
            })
        }


    })
</script>
</html>

18 计算属性

计算属性:在computed里写方法
1 .方法以后当属性用
2 .只有关联的数据变化,才重新运算
3. 有缓存,数据没有变化,页面再更新它也不变化

案例:有个input,输入英文后,把首字母变成大写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>计算属性</h1>
    <!--    最简单方式-->
    <h2>最简单方法首字母变大写</h2>
    <!--    <input type="text" v-model="name">-&ndash;&gt;{{name.slice(0, 1).toUpperCase() + name.slice(1)}}-->
    <h2>使用函数实现,页面只要更新,这个函数就会重新执行,比较耗费资源</h2>
    <!--    <input type="text" v-model="name">-&ndash;&gt;{{getUpper()}}-->

    <input type="text" v-model="age">--->{{age}}

    <h3>通过计算属性实现:计算属性只有在它的相关依赖发生改变时才会重新求值</h3>
    <input type="text" v-model="name">--->{{upperName}}

</div>

</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            name: '',
            age: 0
        },
        methods: {
            getUpper() {
                console.log('我执行了')
                return this.name.slice(0, 1).toUpperCase() + this.name.slice(1)
            }
        },
        computed: {
            upperName() {
                console.log('我是计算属性,我执行了')
                return this.name.slice(0, 1).toUpperCase() + this.name.slice(1)
            }
        }


    })
</script>
</html>

18.2 通过计算属性,重写过滤案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="./js/vue.js"></script>

    <title>标题</title>

</head>
<body>


<div id="app">

    <h1>过滤案例</h1>
    <input type="text" v-model="search">
    <ul>
        <li v-for="item in newdataList">{{item}}</li>
    </ul>


</div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            search: '',
            dataList: ['a', 'at', 'atom', 'atommon', 'be', 'beyond', 'cs', 'csrf', 'csrffe'],

        },
        // 只要input框中数据发生变化search,newdataList会重新运算,只要一运算,v-for重新循环,实现了联动
        computed:{
            newdataList(){
                return this.dataList.filter(item => {
                     return item.indexOf(this.search) > -1
                })
            }
        }
    })



</script>

</html>

19 监听属性

watch: {
categoryType: function (val) {
console.log(‘name发生了变化’)
console.log(val)
// 向后端发送请求,请求回相应分类的数据,展示
}
}

只要categoryType发送变化,就会执行对应的函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>监听属性</h1>
    <span @click="categoryType='美女'">美女</span>|
    <span @click="categoryType='帅哥'">帅哥</span>|
    <span @click="categoryType='老头'">老头</span>



    <div>
       
    </div>
</div>

</body>
<script>
    var vm = new Vue({
        el: '.app',
        data: {
            categoryType: '',
        },
        watch: {
            categoryType: function (val) {
                console.log('name发生了变化')
                console.log(val)
                // 向后端发送请求,请求回相应分类的数据,展示
            }
        }


    })
</script>
</html>

20 组件化开发基础

#作用:扩展 HTML 元素,封装可重用的代码,目的是复用 -例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html -组件把js,css,html放到一起,有逻辑,有样式,有html

#多组件页面和单组件页面 -官方推荐,以后一个组件是一个 xx.vue 文件 —》编译 Single-Page application,缩写为 SPA:以后vue项目只有一个页面,看到的页面变化都是组件间的切换

20.1 全局组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>全局组件</h1>
    <navbar></navbar>




</div>

</body>
<script>
    // 定义一个全局组件,在任意组件中都可以使用
    var obj = {
        template: `
          <div>
          <button @click="handleBack">后退</button>
          我是一个组件-->{{name}}
          <button>前进</button>
          </div>
        `,
        data() {
            return {
                name:'lqz'
            }
        }, // 重点,data必须是个函数,返回一个对象,组件可以在多个地方重复使用,如果就是对象,导致多个组件共用同一个对象的数据,出现错乱
        methods: {
            handleBack(){
                alert('后退了')
            }
        },
        // 学的所有放在vm对象中的,都可以用
    }
    Vue.component('navbar', obj)


    var vm = new Vue({
        el: '.app',
        data: {},


    })
</script>
</html>

20.2 局部组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>全局组件</h1>
    <navbar></navbar>
    <hr>
    <lqz></lqz>


</div>

</body>
<script>
    // 定义一个全局组件,在任意组件中都可以使用
    var obj = {
        template: `
          <div>

          <button @click="handleBack">后退</button>
          我是一个组件-->{{ name }}
          <button>前进</button>
          </div>
        `,
        data() {
            return {
                name: 'lqz'
            }
        }, // 重点,data必须是个函数,返回一个对象,组件可以在多个地方重复使用,如果就是对象,导致多个组件共用同一个对象的数据,出现错乱
        methods: {
            handleBack() {
                alert('后退了')
            }
        },
        // 学的所有放在vm对象中的,都可以用
        components: {} // 全局组件里定义局部组件
    }
    Vue.component('navbar', obj)


    var vm = new Vue({
        el: '.app',
        data: {},
        components: {
            lqz: {
                template: `
                  <div>
                  <h3>我是局部组件</h3>
                  <button>点我看美女</button>
                  </div>`,
                data() {
                    return {}
                },
                methods: {}
            }
        }


    })
</script>
</html>

21 组件通信

各个组件间,数据,方法,都是隔离的

21.1 父组件与子组件通信之父传子(自定义属性)

子组件自定义属性绑定父组件的值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
<h1>通过自定义属性,实现父传子</h1>
    <h3>父组件中name:{{name}}</h3>
    <hr>
    
    <navbar :myname="name" :age="age"></navbar>
    <hr>

</div>

</body>
<script>
    // 定义一个全局组件,在任意组件中都可以使用

    Vue.component('navbar', {
        template: `
        <div>
        <button>前进</button>
        名字是:{{myname}}--->年龄是:{{age}}
        <button>后退</button>
        </div>`,
        props:['myname','age']                  //传自定义属性
    })


    var vm = new Vue({
        el: '.app',
        data: {
            name:'彭于晏',
            age:99
        },


    })
</script>
</html>

21.2 父子通信之子传父(自定义事件)

# 子组件点击按钮=>子组件执行函数this.$emit('自定义事件名字') =》注册在组件上的【自定义事件】对应的函数执行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>通过自定义事件,实现子传父</h1>
    <h3>父组件中收到子组件传递对值为:{{name}}</h3>
    <hr>
    <navbar @myevent="handleReceive"></navbar>
    <hr>

</div>

</body>
<script>
    Vue.component('navbar', {
        template: `
          <div>

          <input type="text" v-model="iname">---{{ iname }}
          <br>
          <button @click="handleClick">点我吧iname传递到父组件中</button>

          </div>`,
        data() {
            return {
                iname: ''
            }
        },
        methods: {
            handleClick() {
                // 触发自定义事件的执行,并且传入当前组件中的iname
                this.$emit('myevent', this.iname)
                // alert(this.iname)
            }
        }
    })

    var vm = new Vue({
        el: '.app',
        data: {
            name: '',
        },
        methods: {
            handleReceive(iname) {
                this.name = iname
            }
        }


    })

  //子组件点击按钮=>子组件执行函数this.$emit('自定义事件名字') =》注册在组件上的【自定义事件】对应的函数执行
</script>
</html>

21.3 ref属性

# 组件间通信---》通过ref属性,vue提供了一个ref属性,可以放在任意标签
    -放在普通标签,通过  this.$refs.ref对应的名字    就能拿到原生dom对象,使用原生操作该dom
  -放在自定义组件上,通过 this.$refs.ref对应的名字 就能拿到 组件对象,就可以调用对象的函数,使用对象的变量
      -父组件中,拿到了子组件对象,对象中的属性,方法可以直接用,直接改
  
     
  
# 通过ref,子传父
    -因为在父中,可以拿到子的对象,子对象中的所有变量,方法,都可以直接用
# 通过ref,实现父传子
    -因为在父中,可以拿到子的对象, 子对象.变量=父的变量
  

# vuex---》实现跨组件间通信

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>ref实现组件间通信</h1>
    {{name}}<br>
    <input type="text" v-model="name" ref="myinput">
    <button @click="handleClick">点我打印</button>
    <hr>
    <navbar ref="mynavbar"></navbar>
    <hr>
    <button @click="handleClick1">点我</button>


</div>

</body>
<script>
    Vue.component('navbar', {
        template: `
          <div>
          <input type="text" v-model="iname">---{{ iname }}
          <br>
          </div>`,
        data() {
            return {
                iname: ''
            }
        },
        methods: {
            handleClick() {
                console.log('执行了')
                return 'xxx'
            }
        }
    })
    var vm = new Vue({
        el: '.app',
        data: {
            name: '',
        },
        methods: {
            handleClick() {
                console.log(this.$refs.myinput)
                console.log(this.$refs.myinput.value)
                this.$refs.myinput.value = 'lqz is big'
                alert(this.name)
            },
            handleClick1(){
                console.log(this.$refs.mynavbar) // 相当于拿到了再组件中的this(组件对象)
                console.log(this.$refs.mynavbar.iname)
                // this.name=this.$refs.mynavbar.iname
                // 父组件中直接执行子组件的方法
                // this.$refs.mynavbar.handleClick() // 调用子组件的方法
                this.$refs.mynavbar.iname='sssss'


            }
        }


    })

</script>
</html>

22 动态组件

元素,动态地绑定多个组件到它的 is 属性
保留状态,避免重新渲染

# 场景: 组件是谁不确定,通过 is 确定显示那个组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>动态组件</h1>
    <ul>
        <li @click="myType='home'">首页</li>
        <li @click="myType='goods'">商品</li>
        <li @click="myType='shopping'">购物</li>
    </ul>
    <!--    动态组件,is是哪个组件名字,这里就会显示那个组件-->
    <component :is="myType"></component>


</div>

</body>
<script>

    Vue.component('home', {
        template: `
            <div>
                <h2>首页</h2>
            </div>`
    })

    Vue.component('goods', {
        template: `
            <div>
                <h2>商品</h2>
            </div>`
    })

    Vue.component('shopping', {
        template: `
            <div>
                <h2>购物</h2>
            </div>`
    })


    var vm = new Vue({
        el: '.app',
        data: {
            myType: 'home',
        },


    })

    //子组件点击按钮=>子组件执行函数this.$emit('自定义事件名字') =》注册在组件上的【自定义事件】对应的函数执行
</script>
</html>

22.1 keep-alive

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>动态组件</h1>
    <ul>
        <li @click="myType='home'">首页</li>
        <li @click="myType='goods'">商品</li>
        <li @click="myType='shopping'">购物</li>
    </ul>
    <!--    动态组件,is是哪个组件名字,这里就会显示那个组件-->
    <keep-alive>
        <component :is="myType"></component>

    </keep-alive>
</div>

</body>
<script>

    Vue.component('home', {
        template: `
            <div>
                <h2>首页</h2>
            </div>`
    })

    Vue.component('goods', {
        template: `
            <div>
                <h2>商品</h2>
                要搜索的商品:<input type="text">
            </div>`
    })

    Vue.component('shopping', {
        template: `
            <div>
                <h2>购物</h2>
            </div>`
    })


    var vm = new Vue({
        el: '.app',
        data: {
            myType: 'home',
        },


    })

    //子组件点击按钮=>子组件执行函数this.$emit('自定义事件名字') =》注册在组件上的【自定义事件】对应的函数执行
</script>
</html>

23 slot插槽

23.1 不具名插槽

将home里的内容放在slot所在位置
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>插槽</h1>
    <hr>
    <home>
        <div>
            <img src="https://pic.maizuo.com/usr/movie/0c5874a81c7969c8eb7ddee7b6ff46b3.jpg" alt="" width="200px"
                 height="300px">
        </div>
    </home>
    <hr>

    <home>
        <div>
            我是div
        </div>
    </home>

</div>

</body>
<script>

    Vue.component('home', {
        template: `
            <div>
                <h2>首页</h2>
                <slot></slot>
            </div>`
    })

    var vm = new Vue({
        el: '.app',
        data: {
            myType: 'home',
        },
    })

</script>
</html>

23.2 具名插槽

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div class="app">
    <h1>插槽</h1>
    <hr>
    <home>
        <img src="https://pic.maizuo.com/usr/movie/0c5874a81c7969c8eb7ddee7b6ff46b3.jpg" alt="" width="200px"
             height="300px" slot="bottom">
        <div slot="top">
            我是div
        </div>
    </home>
    <hr>


</div>

</body>
<script>

    Vue.component('home', {
        template: `
            <div>
                <slot name="top"></slot>
                <p>我是子组件</p>
                <slot name="bottom"></slot>

            </div>`
    })

    var vm = new Vue({
        el: '.app',
        data: {
            myType: 'home',
        },


    })


</script>
</html>

23.3 使用v-slot: 指定插槽

App.vue:

<template>
  <div id="app">
    <h1>我是App</h1>
    <hr>
    <Child>
      <img slot="top" src="https://tva1.sinaimg.cn/large/00831rSTly1gd1u0jw182j30u00u043b.jpg" alt="" width="200px"
           height="200px">

<!--      <template slot="bottom">-->
<!--  与slot=""效果一样,建议使用v-slot,使用<template>指定插槽不会渲染,template无显示效果-->
      <template v-slot:bottom>
        <form action="" >
          <p>用户名:<input type="text"></p>
          <p>密码:<input type="password"></p>
          <button>登录</button>
        </form>
        <p>我是p标签</p>
      </template>

    </Child>

    <hr>
  </div>
</template>


<script>

import Child from './components/Child'

export default {
  name: 'App',
  data() {
    return {
      name: 'lqz'
    }
  },

  methods: {},
  components: {Child},
}
</script>

<style scoped>

h1 {
  background-color: aqua;
}
</style>

child.vue:
<template>
  <div>
    <slot name="top"></slot>
    <h1>我是child组件</h1>
    <slot name="bottom"></slot>

  </div>
</template>

<script>
export default {
  name: "Child"
}
</script>

<style scoped>

</style>

24 Vue-CLI 项目搭建

# 页面中写--》不好---》工程化---》vue是一个前端项目---》webpack支持---》vue官方提供了一个工具
# vue-cli:vue的脚手架,快速创建一个vue项目,带了很多文件
# 解释:
    vue2 中,都是使用vue-cli
  vue3中,可以使用vue-cli创建,官方更推荐使用 vite ,更块,更小
  

  
# Vue-CLI 是基于nodejs的
    -nodejs:是一门后端编程语言
  -js:前端运行在浏览器中,浏览器中有js的解释器,但是这个解释器只能运行在浏览器中,不能运行在操作系统之上
  -于是就有人,把v8引擎,让它能够运行在操作系统之上+c语言写的:文件,网络,操作系统操作的代码
  -nodejs:js语法,运行在操作系统上,后端语言
  -跟python一样,是一个解释型语言---》解释器
  
  
  -LTS:长期支持版本,https://nodejs.org/en/download/
  
# 搭建node环境
  -下载相应平台的版本
      -一路下一步,安装即可,自动加入环境变量(在任意位置都可以执行这俩命令)
    -装完后会释放两个可执行文件
        node:  等同于 python
        npm:   等同于 pip
      
      
      
# 安装 vue-cli:脚手架
# pip install django ---》去国外下载很慢,npm也是很慢,加速
# 【可以不用】以后使用淘宝定制的cnpm替代npm,去淘宝镜像站下载,速度块
# 执行:
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 这句话执行完了,以后,就有俩可以安装第三方模块的命令  npm:慢    cnpm:块
# 以后装任何第三方模块,建议使用cnpm,但是使用npm一样的,只是速度差距
cnpm install -g @vue/cli



# 使用vue脚手架,创建vue项目,装完脚手架,就会有个  vue  命令
vue create 项目名  # 注意路径

# 使用编辑器打开创建好的项目(pycharm)

# 另一种图形化创建项目的方式
vue ui

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

24.1 vue项目目录文件介绍

vue2_test # 项目名 node_modules #
类似于学的python的虚拟环境,主要放了,当前项目所有的以来,很多小文件,给别人发送项目需要把它删掉,如果删掉,执行命令 npm
install 重新下载 public # 文件夹
favicon.ico # 网站小图标
index.html # 单页面应用(spa)

src # 重点:文件夹,以后咱们的代码,都写在这里,js,组件,启动文件。。。
assets # 文件夹,放静态资源,图片,js,css
logo.png # 图片
components # 文件夹,内部放所有的小组件,非页面组件
HelloWorld.vue # 写了一个默认的HelloWorld的组件,是以 .vue结尾都
router # 文件夹,vue-router模块安装了就会有,主要做路由配置
index.js # vue-router的js文件
store # 文件夹,vuex模块安装了就会有,主要做vuex的配置
index.js # vuex的js文件
views # 文件夹,放组件,放页面组件
AboutView.vue # 关于的页面组件
HomeView.vue # 首页的页面组件
App.vue # 根组件 vm对象就是它,它管理了index.html的id为app的div
main.js # 整个入口,非常重要,很多全局配置。。。 .gitignore # git忽略文件相关 babel.config.js# babel的配置,咱们不用管 jsconfig.json # 不需要关注
package.json # 重要:项目依赖的所有第三方模块 等同于python中 requirements.txt
# 执行了 npm install -S axios,这里面就会多这一条 package-lock.json # 锁定版本 README.md # 项目介绍 vue.config.js #
vue的配置文件 等同于 django中setting.py

24.2 vue项目启动

# 方式一:
    -在命令行中敲:
      npm run serve
    
 # 方式二:使用pycharm的点击绿色剪头执行

在这里插入图片描述

24.3 vue项目开发流程

# 以后组件化开发,就是写一个个的组件:页面组件,小组件

# App.vue :根组件

# 以后就是写组件,组件就是  xx.vue
## 第一部分
<template>
  <div id="app">  # 组件必须套在一个标签内部,之前咱们用反引号写的html内容
  </div>
</template>

## 第二部分:
<script>
export default {
  # 以后在这个对象中写咱们之前学的data,methods,watch,computed,生命周期钩子
  name: 'App',
  data() {
    return {
      name: 'lqz'
    }
  },
  methods: {
    handleClick() {
      this.name = '彭于晏'
    }

  }
}
</script>

## 第三部分:这里面写样式
<style>
h1 {
  background-color: red;
}
</style>




# 使用步骤

##1  以后,只要创建组件  HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    x的值是:{{x}},y的值是:{{y}}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: ['msg'],  # 父传子,自定义属性,接受
  data(){
    return {
      x:10,
      y:20
    }
  }
}
</script>



## 2 在根组件App.vue 中使用这个组件
<template>
  <div id="app">
    <h1>我是h1</h1>
    {{ name }}
    <br>
    <button @click="handleClick">点我名字变化</button>
    <hr>
    <HelloWorld :msg="msg"></HelloWorld>  # 自定义属性实现父传子
  </div>
</template>

<style>
h1 {
  background-color: red;
}
</style>

<script>
// 把HelloWorld组件导入
import HelloWorld from "@/components/HelloWorld.vue";
export default {
  name: 'App',
  data() {
    return {
      name: 'lqz',
      msg:'你好啊'
    }
  },
  methods: {
    handleClick() {
      this.name = '彭于晏'
    }

  },
  components:{ # 注册局部组件
    HelloWorld
  }
}
</script>

25 es6导入导出语法

# 写vue项目,大量的看到:他们是es6的导入和导出语法
        import App from './App.vue'
        export default{}
    
# 总结:
    1 以后可以在任意位置写xx.js,可以定义变量,定义函数
  2 导出某些变量,函数
   export default {
     name,print
   }
    
   2.1 默认导出和命名导出
  #默认导出   不用名名字
    export default {}
    # 命名导出
  export const a =10
    
  3 在想用的地方导入
      import 别名  form '路径'  # . 和 ..
  4 使用
    别名.name
    别名.print()
    
    

    
 # 补充:如果一个包下有一个名为index.js 的文件,可以只导入到包这一层
import lqz from './lqz' #  简写成,index.js 可以省略,以后看到的index.js 等同于python的包中的__init__.py
lqz.showName()

26 axios与后端交互处理跨域,携带数据,携带请求头

26.1 使用axios与后端交互

# 1 安装
npm install -S axios
# 2 在想用的地方导入使用即可
import axios from 'axios'
# 3 使用发送请求即可
  axios.get('http://127.0.0.1:8000/user/').then(res=>{
        console.log(res)
        this.name=res.data.name
        this.age=res.data.age
      })


# 解决跨域很多种:浏览器的同源策略
    -1 后端使用cors技术
  -2 使用nginx转发
  -3 前端做代理:之上测试阶段使用,上线后没有

26.2 处理跨域

# 1  django中使用django-cors-headers,解决跨域
# 2 安装 pip3 install django-cors-headers
# 3 在app的注册中加入
INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)
# 4 在中间件中加入
MIDDLEWARE = [ 
    ...
    'corsheaders.middleware.CorsMiddleware',
    ...
]

# 5 配置文件中加入
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
    '*'
)
CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)
#请求头带token时需要加入token 
CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)

26.3 post请求携带数据

handleSubmit() {
      axios.post('http://127.0.0.1:8000/user/', {
        username: this.username,
        password: this.password
      }).then(res => {
        console.log(res.data)
        if (res.data.code == 100) {
          // 登录成功跳转到百度
          location.href = 'http://www.baidu.com'
        } else {
          alert(res.data.msg)
        }
      })
    }

26.4 携带请求头

# 请求头中带token

handleSubmit1() {
      axios.post('http://127.0.0.1:8000/user/',
          {
            username: this.username,
            password: this.password
          },
          {
            headers: {token: 'asdfasdfasd'}
          }
      ).then(res => {
        console.log(res.data)
        if (res.data.code == 100) {
          // 登录成功跳转到百度
          location.href = 'http://www.baidu.com'
        } else {
          alert(res.data.msg)
        }
      })
    }

27 props配置项指定默认值

# props是组件间通信,父传子,自定义属性时,子组件间中接收父组件中传入的数据使用的配置项
# 三种使用方式
基本使用
限制类型
限定类型、限定必传、限定默认值
<template>
  <div>
    <hr>
    <button>后退</button>
    {{ title }}----收到父组件传入的: {{ msg }}
    <button @click="handleClick">前进</button>
    <hr>


  </div>
</template>

<script>
export default {
  name: "Child",
  //1 基本使用
  // props: ['msg'],
  // 2 属性认证,限制类型
  // props:{
  //   msg:String  // 接受的msg必须是string类型
  // },
  // 3 限定类型,限定必传,限定默认值
  props: {
    msg: {
      type: String, //类型
      required: false, //必要性
      default: '老王' //默认值
    },
    xx:Boolean,
  },
  data() {
    return {
      title: '好看的首页'
    }
  },
  methods: {
    handleClick() {
      alert('前进')
    }
  }
}
</script>

<style scoped>

</style>

28 minxin混入

# minxin 混入:可以把多个组件共用的配置提取成一个混入对象

# 提取混入对象
1 第一步:抽取共用的代码,定义混入  mixin的index.js下写了
export const hunhe = {
    methods: {
        handleShowName() {
            alert(this.name)
        }
    },
}

2 第二步:注册混入,全局注册(只要注册了,所有组件都可以用)
// 全局注册混入,以后所有组件中都能用,在main.js中
import {hunhe} from '@/mixin'
Vue.mixin(hunhe)

3 第三步:注册混入,局部注册,在组件中注册了,这个组件可以用(在组件中)
import {hunhe} from "@/mixin";
mixins: [hunhe]

29 插件

# 插件功能:用于增强Vue,vuex,vue-router,elementui都是基于插件的形式使用的

# 实现一个插件
1 定义一个插件,插件内部加入混入
import Vue from 'vue'
export default {
    install(a) {
        console.log(a)
        // 写代码,加入混入
        Vue.mixin({
            methods: {
                handleShowName() {
                    alert(this.name)
                }
            }
        })
        // 写代码,给Vue对象上放变量
        // Vue.prototype.xxx = 'lqz is handsome'

        // 写代码,给vue对象上放个函数

        // Vue.prototype.hello = () => {
        //     alert('hello')
        // }


        // 通过插件,把axios对象放到vue实例上
        Vue.prototype.$http = axios


        // 自定义指令  v-xx

        // 定义很多全局组件
        // Vue.component('lqz', {
        //     template: `
        //         <div>
        //         <h2>我是全局组件</h2>
        //         </div>`
        // })
        
    }
}


2 应用插件  在main.js中引入应用插件,就可以在vue组件中使用
import plugins from './plugins'
Vue.use(plugins) // 自动调用插件内的install,完成对Vue的强化

30 scoped样式

只在当前组件生效,不会影响到其他组件,造成污染。
例:当前h1样式只在本组件有效,不会应用到<Child>组件
<template>
  <div id="app">
    <h1>我是App</h1>
    <hr>
    <Child></Child>
  </div>
</template>


<script>

import Child from './components/Child'
export default {
  name: 'App',
  data() {
    return {
      name: 'lqz'
    }
  },
  // created() {
  //   // console.log(this.xxx)
  //   // this.hello()
  //   this.$http.get('').then(res=>{
  //
  //   })
  // },
  methods: {
  },
  components: {Child},
}
</script>
#style加上scoped
<style scoped>

h1{
  background-color: aqua;
}
</style>

31 项目中使用bootstrap,elementui

除了这个外,还有很多
-iView:https://www.iviewui.com/view-ui-plus/guide/introduce
-app端的ui组件库:http://vant3.uihtm.com/#/zh-CN/home

31.1 elementui的使用步骤

#  1 安装   npm install element-ui -S

# 2 在main.js中引入
// 使用elemenui
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);  // 使用插件,多出很多ui组件,全局的


# 3 在组件中使用,直接去官网复制代码,贴进去即可
    注意复制全:templage,script,style内容

31.2 boostrap使用步骤

# 1 安装
npm install jquery
npm install bootstrap@3

# 2 在main.js中引入
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'

# 3 使用jquery,在vue的配置文件中vue.config.js
const {defineConfig} = require('@vue/cli-service')
const webpack = require("webpack");
module.exports = {
    configureWebpack: {
        plugins: [
            new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery",
                "window.jQuery": "jquery",
                "window.$": "jquery",
                Popper: ["popper.js", "default"]
            })
        ]
    }
};


# 4 以后在组件中直接使用bootsrtap的样式即可

32 localStorage和sessionStorage

在这里插入图片描述

# 前端存数据的地方
    -cookie中:借助第三方插件,自己用js写
  -sessionStorage:关闭浏览器,它就没了
  -localStorage:永久存在,手动删除,或浏览器存满了、
# 通过这三个东西就可以实现组件间通信 


# 使用:sessionStorage
#放数据
sessionStorage.setItem('name', 'lqz')
#取数据
sessionStorage.getItem('name')
#清空
sessionStorage.clear()  
#删除
sessionStorage.removeItem('name')

# 使用:localStorage
#例如:不登陆加购商品到购物车,此时存在前端localStorage中
localStorage.setItem('name', 'lqz')
localStorage.getItem('name')
localStorage.clear()  // 清空
localStorage.removeItem('name')

33 vuex的使用

是一个插件,状态管理器,用于存取数据
Vuex 可以帮助我们管理共享状态,可以实现跨组件通信(屏蔽了组件的父子关系)

在这里插入图片描述

# 使用
# 1.新建store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
    // 存数据的地方
    state: {
        sum: 0
    },
    // 厨师,真正的干货
    mutations: {
        JIA(state, value) {
            state.sum += value
        }
    },
    // 服务员,中转站
    actions: {
        jia(context, value) {
            // context 上下文
            // value 组件中调用时,传入的值
            // 判断是否有权限改请求一下后端接口,获取了,有权限,
            context.commit('JIA', value)

        }
    },
})

#2.在main.js中使用
import store from './store'
new Vue({
    router,
    store,  # 把store放在这里
    render: h => h(App)
}).$mount('#app')

#3.在任意组件中,想获取state中的数据
    this.$store.state.变量  即可
  
#4.在任意组件中修改数据
this.$store.dispatch("actions中定义的函数",参数)
它就会触发  actions中定义的函数  的执行,内部执行了 context.commit('JIA', value)
它又会触发  mutations中定义的函数执行,内部对sum进行了修改


#5.在任意组件中修改数据也可以
this.$store.commit('JIA',2)

34 vue-router使用

# spa:单页面应用,很多页面组件,来回切换,借助于vue-router

# 使用
1 router下新建index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/views/Home'

Vue.use(VueRouter)


// 这个地方注册路由,最重要的地方
const routes = [
    {
    path: '/home',
    name: 'home',
    component: Home
  },
    {
    path: '/about',
    name: 'about',
    component: About
  },
    {
    path: '/login',
    name: 'login',
    component: Login
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

2 在main.js中注册
import router from './router'
new Vue({
    router,
    render: h => h(App)
}).$mount('#app')


3 写好一个个页面组件
 Home.vue
 About.vue
 Login.vue
  
  
4 以后访问路径
http://192.168.1.5:8080/home   显示Home组件
http://192.168.1.5:8080/about  显示About组件
http://192.168.1.5:8080/login  显示Login组件




5 以后在任意组件中
    this.$router,拿到的就是导出的router对象

35 Vue3常用api之setup

# setup 中可以写变量,写函数,只要reurn了,在模版中就可以使用

setup() {
    // 定义变量  const不能改 let 跟var一样
    let name = 'lqz'
    let age = 19  //
    // 定义函数
    function handleAdd(){
      age=age+1    // 数据变了,页面没变
      console.log(age)
    }
    // 要在模版中使用必须,return出去
    return {name,age,handleAdd}
  }

36 常用api之ref和reactive

# 上面没有响应式:数据变,页面变,页面变数据变

# 基本数据类型使用ref包裹一下,使之变成响应式
在模版中直接使用
在setup中 使用对象.value获取真正的值

# 对象,数组类型,使用reactive包裹
模版中直接使用


<template>
  <!--组件不需要放在一个标签内了-->

  {{ x }}
  <br>
  <h2>{{ name }}==={{ age }}</h2>
  <button @click="handleAdd">点我年龄+1</button>
  <hr>
  <h2>名字是:{{ person.name }},年龄是:{{ person.age }}</h2>
  <button @click="handleChange">点我修改刘亦菲名字</button>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import {ref, reactive} from 'vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  data() {
    return {
      x: 100
    }
  },
  // 以后vue3不建议使用data,methods。。。 配置项api了
  // 建议使用setup,组合式api
  setup() {
    // 定义变量  const不能改 let 跟var一样
    const name = ref('lqz')
    const age = ref(19)  //
    const person = reactive({
      name: '刘亦菲',
      age: 36
    })

    // 定义函数
    function handleAdd() {
      age.value = age.value + 1    // 数据变了,页面没变
      console.log(age)
    }

    function handleChange(){
      person.name+='?'
      console.log(person.name)
    }

    // 要在模版中使用必须,return出去
    return {name, age, handleAdd, person,handleChange}
  }
}
</script>

37 计算和监听属性

# computed 配置项完成计算属性
# watch    配置项完成监听属性
以上的照常用

# 推荐使用组合式api

<template>
  <!--组件不需要放在一个标签内了-->
  <h2>{{ fullName }}</h2>
  <button @click="handleChange">点我修改姓</button>
  <hr>
  {{ sum }}
  <button @click="sum++">点我sum1</button>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import {ref, reactive, computed, watch,onBeforeMount,onMounted} from 'vue'

export default {
  name: 'App',


  setup() {
    console.log('beforecreate和created')

    const sum = ref(10)
    const person = reactive({
      firstName: '刘',
      lastName: '清政'
    })

    let fullName = computed(() => {
      return person.firstName + person.lastName
    })

    watch(sum, (newValue, oldValue) => {
      console.log('老数据', oldValue)
      console.log('新数据', newValue)
    })


    onMounted(() => {
      console.log('页面挂在后执行')
    })
    function handleChange() {
      person.firstName = '王'
    }

    return {person, fullName, handleChange, sum}
  }
}
</script>

38 toRef

解压对象,使用setup()中的属性时不需要使用.属性,直接使用属性
<template>
  <!--组件不需要放在一个标签内了-->
  <h2>{{ name }}===={{age}}===={{isShow}}</h2>

</template>

<script>
import {ref, reactive, toRefs} from 'vue'

export default {
  name: 'App',


  setup() {

    const data = reactive({
      name: '刘',
      age: '清政',
      isShow:false
    })



    // es6语法中的对象解压
    return {
      ...toRefs(data)  // 解压开,return// name:data.name,
      // age:data.age,
      // isShow:data.isShow,
    }
  }
}
</script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值