• vue2+vue3天禹老师版复习笔记


    文章目录

    1.Vue2基础

    Vue官网

    1.1.初始Vue

    <head>
        <meta charset="UTF-8">
        <title>初始Vuetitle>
        
        <script type="text/javascript" src="../js/vue.js">script>
    head>
    <body>
        
        <div id="root">
            <h1>hello {{name}}h1>
        div>
        
        <script type="text/javascript">
            //阻止Vue在启动时生成生产提示
            Vue.config.productionTip = false
    
            //创建Vue实例 参数是配置对象
            new Vue({
                el: '#root', //element用于指定当前Vue实例为哪个容器服务
                data: {name: 'Vue'}, //存储数据,提供给el指定容器使用
            })
        script>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    总结:

    ​ 1.想让Vue工作必须先创建Vue实例,并且传入配置对象

    ​ 2.容器中的代码依旧符合html规范

    ​ 3.Vue实例和容器只能一一对应

    ​ 4.{{xxx}}中的xxx要写js表达式,并且xxx可以自动读取data中的所有属性

    1.2.模板语法

    <body>
        <div id="root">
            <h1>你好,{{name}}h1>
            <hr>
            <a v-bind:href="web.url">点我跳转到{{web.name}}a>
             
            <a :href="web.url.toUpperCase()">点我跳转到{{web.name}}a>
        div>
    
        <script>
            Vue.config.productionTip = false
    
            new Vue({
                el: '#root',
                data: {
                    name: 'jack',
                    web:{
                        name: '百度',
                        url: 'http://www.baidu.com'
                    }
                    
                }
            })
        script>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    总结:

    ​ Vue模板语法分为两大类:

    ​ 1.插值语法:{{xxx}} xxx为js表达式

    ​ 2.指令语法:v-xxx xxx为js表达式

    1.3.数据绑定

    <body>
        <div id="root">
            单向数据绑定:<input type="text" v-bind:value="name">
            双向数据绑定:<input type="text" v-model:value="name">
            
            
            单向数据绑定:<input type="text" :value="name">
            双向数据绑定:<input type="text" v-model="name">
        div>
    
        <script>
            Vue.config.productionTip = false
    
            new Vue({
                el: '#root',
                data: {
                    name:'单向绑定'
                }
            })
        script>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    总结:

    Vue中有两种数据绑定的方式:

    ​ 1.单向绑定(v-bind):数据只能从data流向页面

    ​ 2.双向绑定(v-model):数据不仅能从data流向页面也能从页面流向data

    ​ v-bind:属性="" —简写→ :属性=""

    ​ v-model:value="" —简写→ v-model=""

    1.4.MVVM模型

    请添加图片描述
    MVVM模型:

    ​ M(模型Model):对应data中的数据

    ​ V(试图View):模板

    ​ VM(视图模型ViewModel):Vue实例对象

    总结:

    ​ data中的所有属性最后都出现在vm实例对象上

    ​ vm实例上的所有属性及Vue原型上所有属性都可以在Vue模板中直接使用

    1.5.el和data的两种写法

    el的两种写法

    
    <script>
        Vue.config.productionTip = false
    
        const vm = new Vue({
            el: '#root', 
            data: {}
        })
    script>
    
    
    <script>
        Vue.config.productionTip = false
    
        const vm = new Vue({
            data: {}
        })
        vm.$mount("#root")
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    data的两种写法

    
    <script>
        Vue.config.productionTip = false
    
        const v = new Vue({
            el: '#root', 
            data: {
                name: 'jack'
            }
            
        })
    script>
    
    
    <script>
        Vue.config.productionTip = false
    
        const v = new Vue({
            el: '#root',
            data: function(){    //简写形式-> data(){...}
                return {
                    name: 'jack'
                }
            }
        })
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    总结:

    el的两种写法:

    ​ 1.new Vue的时候配置el属性

    ​ 2.先创建Vue实例,然后再通过vm.$mount("选择器")指定容器

    data的两种写法:

    ​ 1.对象式

    ​ 2.函数式

    关于data函数式写法的重要原则:

    ​ 由Vue管理的函数只能写普通函数,不能使用箭头函数

    ​ 一旦写了箭头函数,this就不再指向Vue实例

    1.6.回顾defineProperty方法

    <body>
        <script type="text/javascript">
            let num = 18
    
            let person = {
                name: "张三",
                sex: "男",
                // age: num 无法动态的修改age属性的值
            }
    
            //给person对象添加age属性
            Object.defineProperty(person,"age",{
                // value: 18,
                // writable:true,//控制属性是否可以被修改
                // enumerable: true,//控制属性是否可以枚举
                // configurable:true,//控制属性是否可以被删除
                get(){ //当读取person的age属性时自动调用
                    return num;
                },
                set(value){ //当修改person的age属性时自动调用
                    num = value
                }
                //get()和set()不能与value和writable属性共存
            })
        script>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    折叠代码

    //#region
    //.....
    //#endregion
    
    • 1
    • 2
    • 3

    1.7.数据代理

    <script type="text/javascript">
        
        let obj = {x:100}
        let obj2 = {y:200}
    
        Object.defineProperty(obj2,"x",{
            get(){
                return obj.x
            },
            set(value){
                obj.x = value
            }
        })
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    在代理对象上通过Object.defineProperty()添加被代理对象的属性

    通过obj2对象可以操作obj对象中的x属性,这就是数据代理

    1.8.Vue中的数据代理

    <script>
        Vue.config.productionTip = false
    
        let data = {
                name: "张三",
                age: "20"
            }
    
        const vm = new Vue({
            el: '#root',
            data
        })
    
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    验证vm中的_data就是配置对象中的data
    在这里插入图片描述
    vm上添加的getter/setter
    在这里插入图片描述

    如何实现数据代理?

    ​ 以name属性为例,当访问vm.name时会调用name属性的getter方法返回data中的name值

    ​ 当修改vm.name时会调用name属性的setter方法修改data中的name属性值
    在这里插入图片描述
    总结:

    ​ 通过vm对象代理data对象的中属性

    ​ 原理:

    ​ 通过Object.defineProperty()把data对象的所有属性添加到vm上

    ​ (data相当于上例中的obj对象 vm相当于上例中的obj2对象)

    ​ 为每个添加到vm对象上的属性提供getter 和 setter 方法

    ​ 在getter/setter方法内部操作data中对应的属性

    在这里插入图片描述

    1.9.事件处理

    <body>
        <div id="root">
            <button v-on:click="showInfo">点我显示信息button>
            
            <button @click="showInfo">点我显示信息button>
            
            <button @click="showInfo2($event,66)">点我显示信息(传参)button>
        div>
    
        <script>
            Vue.config.productionTip = false
    
            new Vue({
                el: '#root',
                data: {},
                methods: {
                    showInfo(event){
                    	//默认传递event事件对象
                        console.log(event);//事件对象
                        console.log(this);//此处的this指向vm对象
                    },
                    showInfo2(event,number){
                        console.log(event,number);
                    }
                }
            })
        script>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    事件的基本使用:

    ​ 1.使用v-on:xxx@xxx绑定事件,xxx是事件名

    ​ 2.事件的回调函数需要配置在methods对象中,最终会出现在vm上

    ​ 3.methods中配置的函数不要使用箭头函数

    ​ 4.传递参数时,默认不传递event对象,如果需要传递event对象,必须使用$event传递

    事件修饰符

    事件修饰符说明
    prevent阻止默认事件
    stop阻止事件冒泡
    once事件只触发一次
    capture使用事件的捕获模式
    self只有event.target是当前操作元素时才触发事件
    passive事件的默认行为立即执行 无需等待回调函数执行完毕
    <body>
        <div id="root">
            <a href="http://www.baidu.com" @click.prevent="show">百度a>
            
            <a href="http://www.baidu.com" @click.prevent.once="show">百度a>
        div>
    
        <script>
            Vue.config.productionTip = false
    
            new Vue({
                el: '#root',
                data: {},
                methods: {
                    show(e){
                        //阻止默认行为,效果同 @click.prevent
                        //e.preventDefault()
                        alert('abc')
                    }
                }
            })
        script>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    基础知识补充

    css:
    	overflow: auto; 空间不够显示滚动条
    事件:
    	
        scroll: 滚动条滚动时触发事件 wheel: 鼠标滚轮滚动时触发事件
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8

        键盘事件

        Vue中常用的按键别名

        按键别名
        回车enter
        删除delete
        退出esc
        空格space
        换行tab
        上/下/左/右up / down / left / right

        特殊的键:

        ​ Tab只能配合keydown使用

        ​ 系统修饰键:ctrl、alt、shift、meta(win)

        ​ 配合keyup使用:按下修饰键的同时按下其他键,然后释放其他键,事件才能被触发

        ​ 配合keydown使用:正常触发事件

        <body>
            <div id="root">
                <input type="text" placeholder="按下键盘显示提示" @keydown.enter="showTip">
                
                <input type="text" placeholder="按下键盘显示提示" @keydown.CapsLock="showTip">
                <input type="text" placeholder="按下键盘显示提示" @keydown.caps-lock="showTip">
                
                <input type="text" placeholder="按下Ctrl+Y显示提示" @keyup.ctrl.y="showTip">
        		<input type="text" placeholder="按下x或y显示提示" @keydown.x.y="showTip">
        
            div>
        
            <script>
                Vue.config.productionTip = false
        
                new Vue({
                    el: '#root',
                    data: {},
                    methods: {
                        showTip(event){
                            console.log(event.key,event.keyCode);
                        }
                    }
                })
        
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30

        在Vue中也可以使用keyCode去指定具体的按键(不推荐)

        <input type="text" placeholder="按下键盘显示提示" @keydown.13="showTip">
        
        • 1

        键盘上各个键对应的keyCode(了解)

        keykeycode
        Escape27
        CapsLock20
        Shift16
        Control17
        Delete46
        Backspace8
        空格32
        Tab9
        Enter(回车)13
        左/上/右/下37/38/39/40
        a/b/c/d/…65/66/67/68/…
        0/1/2/3/4/…48/49/50/51/52/…

        自定义别名按键(了解)

        <body>
            <div id="root">
                <input type="text" placeholder="按下键盘显示提示" @keydown.huiche="showTip">
            div>
        
            <script>
                Vue.config.productionTip = false
                //自定义回车按键的别名
                Vue.config.keyCodes.huiche = 13
                new Vue({
                    el: '#root',
                    data: {},
                    methods: {
                        showTip(event){
                            console.log(event.key,event.keyCode);
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20

        1.10.计算属性

        姓名案例:当输入框中的内容发生变化时,姓名也会发生相应的变化
        在这里插入图片描述

        
        <body>
            <div id="root">
                姓:<input type="text" v-model="firstName"><br>
                名: <input type="text" v-model="lastName"><br>
                姓名:<span>{{firstName}}-{{lastName}}span>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                new Vue({
                    el: '#root',
                    data: {
                        firstName: '张',
                        lastName: '三'
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20

        使用插值语法虽然可以实现这个案例,但是当需求发生变化时,{{xxx}}中的表达式可能会变得很复杂,代码可读性差

        
        <body>
            <div id="root">
                姓:<input type="text" v-model="firstName"><br><br>
                名:<input type="text" v-model="lastName"><br><br>
                姓名:<span>{{fullName()}}span>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                new Vue({
                    el: '#root',
                    data: {
                        firstName: '张',
                        lastName: '三'
                    },
                    methods: {
                        fullName(){
                            //这里可以对firstName/lastName操作
                            return this.firstName+'-'+this.lastName
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26

        上面这种方式效率较低

        
        <body>
            <div id="root">
                姓:<input type="text" v-model="firstName"><br><br>
                名:<input type="text" v-model="lastName"><br><br>
                姓名:<span>{{fullName}}span>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        firstName: '张',
                        lastName: '三'
                    },
                    //计算属性配置项
                   computed:{
                        //写在data中的是属性    
                        //写在computed中的是计算属性
                        fullName:{ //fullName就是计算属性
                            get(){
                                //什么时候调用
                                //1.初次读取fullName时
                                //2.所依赖的数据发生变化时
                                return this.firstName+'-'+this.lastName
                            },
                            set(value){
                                //set不是必须的
                                //fullName发生变化时调用
                                const arr = value.split('-')
                                this.firstName = arr[0]
                                this.lastName = arr[1]
                            }
                        }
                   }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40

        计算属性的简写形式

        如果计算属性只读不改才可以使用简写形式

        computed:{
        	fullName(){
        		return this.firstName+'-'+this.lastName
        	}
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5

        总结:

        ​ 计算属性的定义:要用的属性不存在,要通过已有的属性计算得来

        ​ 计算属性最终会出现在vm身上,可直接使用

        ​ 相比于methods方法实现,这种方式内部有缓存机制,效率更高

        1.11.监视属性(侦听属性)

        天气案例:点击按钮切换天气(将炎热改为凉爽)
        在这里插入图片描述

        <body>
            <div id="root">
                <h1>今天天气很{{weather}}h1>
                <button @click="changeWeather">点击切换天气button>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        isHot: true
                    },
                    computed: {
                        weather(){
                            return this.isHot ? '炎热' : '凉爽'
                        }
                    },
                    methods: {
                        changeWeather(){
                            this.isHot = !this.isHot
                        }
                    },
                    //监视属性的配置项
                    watch: {
                        //key为要监视的属性
                        isHot:{
                            //初始化时是否执行handler函数
                            immediate: false,
                            //handler函数可以接收被监视属性被修改前后的值
                            handler(newValue,oldValue){
                                console.log('天气被修改了',newValue,oldValue);
                            }
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39

        监视属性的另外一种写法(创建好vm对象后,使用$watch()函数添加监视属性)

        这种方式适合在创建vue实例对象时不明确要监视哪个属性

        vm.$watch('isHot',{
             immediate: false,
             handler(newValue,oldValue){
                console.log('天气被修改了',newValue,oldValue);
             }
        })
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6

        监视属性的简写形式

        当监视属性只配置handler属性>时才能使用简写形式

        watch: {
            isHot (newValue,oldValue){
                console.log('天气被修改了',newValue,oldValue);
            }
        }
        //另一种简写形式
        vm.$watch('isHot',function(newValue,oldValue){
            console.log('天气被修改了',newValue,oldValue);
        })
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9

        深度监视

        案例:点击按钮数值加1,并在控制台中打印变化的值
        在这里插入图片描述

        <body>
            <div id="root">
                <h1>a的值是{{numbers.a}}h1>
                <h1>b的值是{{numbers.b}}h1>
                <button @click="numbers.a++">点击a+1button>
                <button @click="numbers.b++">点击b+1button>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        numbers: {
                            a:10,
                            b:20
                        }
                    },
                    watch: {
                        //a: { 当监视的是多级结构中的属性,这样写就无法监视到
                        'numbers.a':{ //正确写法
                            handler(newValue,oldValue){
                                console.log('a的值变化了',newValue,oldValue);
                            }
                        },
                        numbers:{
                            deep: true, //开启深度监视,用于监视多级结构中的属性
                            handler(){
                                console.log('numbers中的值变化了');
                            }
                        }
                    }
                })
        
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37

        总结:
        1.Vue中的watch默认不监视对象内部的属性值的改变
        2.配置deep:true可以监视到对象内部属性的改变

        计算属性VS监视属性

        姓名案例watch实现

        
        <body>
            <div id="root">
                姓:<input type="text" v-model="firstName"><br><br>
                名:<input type="text" v-model="lastName"><br><br>
                姓名:<span>{{fullName}}span>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        firstName: '张',
                        lastName: '三',
                        fullName:'张-三'
                    },
                    watch:{
                        firstName(newVal){
                            this.fullName = newVal +'-'+ this.lastName
                        },
                        lastName(newVal){
                            this.fullName = this.firstName +'-'+ newVal
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29

        新需求:在修改完姓之后3秒页面的全名再发生变化

        //这种写法是错误的	
        computed:{
        	fullName(){
        		setTimeOut(()=>{
        			return this.firstName+'-'+this.lastName
        		},3000)
        	}
        }
        //这种写法是正确的	
        watch:{
            firstName(newVal){
                setTimeOut(()=>{
        			this.fullName = newVal +'-'+ this.lastName
        		},3000)
            },
            lastName(newVal){
                this.fullName = this.firstName +'-'+ newVal
            }
        }
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20

        总结:

        ​ 1.computed能完成的功能 使用watch也都能完成

        ​ 2.watch能完成的功能 computed不一定能完成 例如watch可以进行异步操作

        ​ 3.计算属性中不能开启异步任务去维护数据

        ​ 4.两个重要的小原则:

        ​ 4.1所有被Vue管理的函数最好写成普通函数

        ​ 4.2所有不被Vue管理的函数最好写成箭头函数(定时器的回调、ajax的回调、Promise的回调)

        1.12.绑定样式

        css样式绑定

        
        <body>
            <div id="root">
                绑定样式::class="xxx" xxx可以是字符串、数组、对象
                
                <div class="basic" :class="classStr" @click="changeClass">div>
                
                <div class="basic" :class="classArr">div>
                
                <div class="basic" :class="classObj">div>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        classStr: 'style1',
                        classArr: ['style1','style2','style3'],
                        classObj:{
                            style1: true,  //使用style1样式
                            style2: true,
                            style3: false  //不使用style3样式
                        }
                    },
                    methods: {
                        changeClass(){
                            this.classStr = 'style2'
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34

        style样式绑定

        <body>
            <div id="root">
                <div :style="styleObj">绑定样式div>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        styleObj: {
                            fontSize: '40px',
                            color: 'red'
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19

        1.13.条件渲染

        <body>
            <div id="root">
                <div v-show="isShow">{{info}}div>  
                
                
                <div v-if="num === 1">Vuediv>
                <div v-else-if="num === 2">Reactdiv>
                <div v-else>Angulardiv>
        
                
                <template v-if="isShow">
                    <h1>Vueh1>
                    <h1>Reacth1>             
                template>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        info: 'hello vue',
                        isShow: true,
                        num: 0
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31

        总结:
        1.v-if
        写法:v-if="布尔表达式"
        适用于切换频率较低的场景
        不展示的DOM结点会被删除
        配合v-else使用时要求结构不能被打断
        2.v-show
        写法:v-show="布尔表达式"
        适用于切换频率较高的场景
        不展示的DOM结点不会被移除,仅仅使用样式隐藏

        1.14.列表渲染

        <body>
            <div id="root">
                <ul>
                    
                    <li v-for="p in persons" :key="p.id">{{p.name}}-{{p.age}}li>
                    <li v-for="(p,index) in persons" :key="index">{{p}}-{{index}}li>
                    <li v-for="p of persons" :key="p.id">{{p.name}}-{{p.age}}li>
                    
                    <li v-for="(value,key) in persons[0]" :key="key">{{key}}-{{value}}li>
                    
                    <li v-for="(char,index) in str" :key="index">{{char}}-{{index}}li>
                    
                    <li v-for="(number,index) in 5" :key="index">{{number}}-{{index}}li>
                ul>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        persons: [
                            {id:'001',name:'张三',age:18},
                            {id:'002',name:'李四',age:19},
                            {id:'003',name:'王五',age:20},
                        ],
                        str: 'hello'
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32

        index作为key时diff算法过程
        在这里插入图片描述
        id作为key时diff算法过程
        在这里插入图片描述
        key的工作原理总结:

        ​ 1.key是虚拟DOM对象的标识

        ​ 2.当状态中的数据发生变化时,Vue会根据新数据生成新的虚拟DOM,再根据diff算法转换成真实DOM

        ​ 3.对比规则:

        ​ 3.1旧虚拟DOM中找到了与新虚拟DOM相同的key

        ​ a.若虚拟DOM中的内容没有改变,直接使用之前生成的真实DOM

        ​ b.若虚拟DOM中的内容发生改变,则生成新的真实DOM,替换掉之前的真实DOM

        ​ 3.2旧虚拟DOM中未找到与新虚拟DOM相同的key

        ​ 创建新的真实DOM,然后渲染到页面

        用index作为key可能会引发的问题

        ​ 若对数据进行逆序添加、删除等破坏顺序操作时

        ​ 1.如果结构中没有包含输入类DOM,会产生没必要的真实DOM更新

        ​ 2.如果结构中包含输入类DOM,会产生错误DOM更新

        如何选择key

        ​ 1.最好使用数据的唯一标识作为key

        ​ 2.如果不存在破坏顺序的操作,仅用于渲染列表用于展示,那么可以使用index作为key

        1.15.列表过滤

        案例:在输入框中输入关键字实现模糊搜索
        在这里插入图片描述
        监视属性实现

        <body>
            <div id="root">
                <input type="text" placeholder="请输入关键字" v-model="keyWord"/>
                <ul>
                    <li v-for="(p,index) in filterPersons" :key="p.id">{{p.name}}-{{p.age}}-{{p.sex}}li>
                ul>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        keyWord: '',
                        persons: [
                            {id:'001',name:'马冬梅',age:18,sex:'女'},
                            {id:'002',name:'周冬雨',age:19,sex:'女'},
                            {id:'003',name:'周杰伦',age:20,sex:'男'},
                            {id:'004',name:'温兆伦',age:20,sex:'男'},
                        ],
                        filterPersons: []
                    },
                    watch: {
                        keyWord: {
                            immediate: true,
                            handler(newValue){
                                this.filterPersons = this.persons.filter((p)=>{
                                return p.name.indexOf(newValue) !== -1
                            })
                            }
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36

        计算属性实现

        <body>
            <div id="root">
                <input type="text" placeholder="请输入关键字" v-model="keyWord"/>
                <ul>
                    <li v-for="(p,index) in filterPersons" :key="index">{{p.name}}-{{p.age}}-{{p.sex}}li>
                ul>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        keyWord: '',
                        persons: [
                            {id:'001',name:'马冬梅',age:18,sex:'女'},
                            {id:'002',name:'周冬雨',age:19,sex:'女'},
                            {id:'003',name:'周杰伦',age:20,sex:'男'},
                            {id:'003',name:'温兆伦',age:20,sex:'男'},
                        ],
                    },
                    computed:{
                        filterPersons(){
                            var arr = this.persons.filter((p)=>{
                                return p.name.indexOf(this.keyWord) !== -1
                            })
                            return arr
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33

        需求升级:为搜索的到的数据添加排序功能
        在这里插入图片描述

        <body>
            <div id="root">
                <input type="text" placeholder="请输入关键字" v-model="keyWord"/>
                <input type="button"  @click="sortType = 2" value="按年龄升序"/>
                <input type="button"  @click="sortType = 1" value="按年龄降序"/>
                <input type="button"  @click="sortType = 0" value="按原顺序排序"/>
                <ul>
                    <li v-for="(p,index) in filterPersons" :key="index">{{p.name}}-{{p.age}}-{{p.sex}}li>
                ul>
            div>
        
            <script>
                Vue.config.productionTip = false
                
                const vm = new Vue({
                    el: '#root',
                    data: {
                        keyWord: '',
                        sortType: 0,
                        persons: [
                            {id:'001',name:'马冬梅',age:19,sex:'女'},
                            {id:'002',name:'周冬雨',age:21,sex:'女'},
                            {id:'003',name:'周杰伦',age:18,sex:'男'},
                            {id:'003',name:'温兆伦',age:20,sex:'男'},
                        ],
                    },
                    computed:{
                        filterPersons(){
                            var arr = this.persons.filter((p)=>{
                                return p.name.indexOf(this.keyWord) !== -1
                            })
                            if(this.sortType){
                                arr.sort((p1,p2)=>{
                                    return this.sortType === 2 ? p1.age-p2.age : p2.age-p1.age
                                })
                            }
                            return arr
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42

        1.16.Vue检测数据变化的原理

        模拟简单默认数据监视

        <body>
            <script>
                function Observer(obj) {
                    //获取对象中的所有key,放入到keys数组中
                    const keys = Object.keys(obj)
                    //遍历每个key,为其添加get/set函数
                    keys.forEach((key) => {
                        Object.defineProperty(this, key, {
                            get() {
                                return obj[key]
                            },
                            set(value) {
                                console.log(`${key}属性改变了,准备开始重新解析模板...`);
                                obj[key] = value
                            }
                        })
                    })
                }
        
                let data = {
                    name: 'jack',
                    age: 20
                }
        
                let obs = new Observer(data)
                let vm = {}
                vm._data = data = obs
                
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30

        在这里插入图片描述

        Vue.set()和vm.$set()

        Vue提供了Vue.set()和vm.$set()可以实现后添加的数据也能有响应式的功能

        语法:Vue.set(target,'key/index','value')vm.$set(target,'key/index','value')

        ​ target:往谁的身上追加属性,target不允许是vm或vm._data

        ​ key/index: 要追加的属性名或者数组下标

        ​ value: 属性值

        这种方法存在局限

        set()不能给data追加属性,只能给data中的对象追加属性

        数组监视

        <body>
            <div id="root">
                <ul>
                    <li v-for="(h, index) in hobby" :key="index">{{h}}li>
                ul>
            div>
            <script>
               Vue.config.productionTip = false
        
               const vm = new Vue({
                el:'#root',
                data: {
                    hobby:['唱歌','跳舞','打球']
                }
               })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17

        在这里插入图片描述
        由于数组内并没有提供set和get,所以在修改hobby[0]时Vue监测不到数据发生变化,导致页面也不会变化

        Vue将被监听的数组的更变方法进行了包装,所以他们会触发视图的更新,这些被包装的方法有:

        • push() 在数组尾部插入元素
        • pop() 移除数组尾部元素
        • shift() 移除数组首部元素
        • unshift() 在数组首部插入元素
        • splice() 在指定位置替换、添加或删除数组元素
        • sort() 对数组进行排序
        • reverse() 反转数组

        Vue监视数据变化的原理

        1.Vue会监视data中所有层次的数据

        2.监视对象中的数据

        ​ 通过setter实现监视,且要在new Vue时就传入要监视的数据

        ​ 对象中后追加的属性Vue默认不做响应式处理

        ​ 如果需要对后追加的属性做响应式处理需要使用Vue.set()vm.$set()

        3.监视数组中的属性

        ​ 对于数组中非对象属性,Vue默认不提供setter和getter,直接修改vue监视不到变化

        ​ 通过包裹数组更新元素的函数实现

        注意:通过Vue.set()和vm.$set()不能给vm或vm._data添加属性

        1.17.收集表单数据

        <body>
            <div id="root">
                <form action="#" method="post" @submit.prevent="submit">
                    账号:<input type="text" v-model.trim="username"><br><br>
                    密码:<input type="password" v-model="password"><br><br>
                    年龄:<input type="number" v-model.number="age"><br><br> 
                    性别:
                    男<br><br>
                    爱好:
                    唱歌<input type="checkbox" name="hobby" v-model="hobby" value="sing">
                    跳舞<input type="checkbox" name="hobby" v-model="hobby" value="dance">
                    打球<input type="checkbox" name="hobby" v-model="hobby" value="ball"><br><br>
                    校区:
                    <select name="area" v-model="area">
                        <option value="">请选择校区option>
                        <option value="富春">富春校区option>
                        <option value="滨江">滨江校区option>
                    select><br><br>
                    其他信息:<textarea v-model.lazy="info">textarea><br><br>
                    <input type="checkbox" v-model="agree">
                    同意并接收<a href="#">《用户协议》a><br><br> 
                    <input type="submit" value="提交">
                form>
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        username: '',
                        password: '',
                        age:'',
                        sex: 'male',
                        hobby: [],
                        area: '',
                        info:'',
                        agree: ''
                    },
                    methods: {
                        submit(){
                            const data = JSON.stringify(thi._data)
                        }
                    },
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49

        总结:

        ​ 1.若收集的是 则v-model收集的是用户输入的value值

        ​ 2.若收集的是 则v-model收集的是value值且要配置value属性

        ​ 3.若收集的是 则v-model收集的是

        ​ 3.1没有配置value属性.收集checked的值(true/false)

        ​ 3.1配置了value属性.如果v-model的初始值是非数组那么收集的还是checked的值.如果v-model的初始值 是数组.那么收集的就是value组成的数组

        ​ 4.v-model的三个修饰符

        ​ 4.1 lazy 失去焦点再收集数据

        ​ 4.2 number 输入的字符串转为有效数组,一般配置type="number"使用

        ​ 4.3trim 去除输入首位多余空格

        1.18.过滤器

        BootCDN网址:https://www.bootcdn.cn/

        <head>
            <meta charset="UTF-8">
            <title>Documenttitle>
            <script src="../js/vue.js">script>
            <script src="../js/dayjs.min.js">script>
        head>
        <body>
            <div id="root">
                
                <div>{{formatTime}}div>
                
                <div>{{time | timeFormater}}div>
                
                <div>{{time | timeFormater('YYYY年MM月DD日')}}div>
                
                <div>{{time | timeFormater('YYYY年MM月DD日') | getYear}}div>
            div>
        
            <script>
                Vue.config.productionTip = false
                //配置全局过滤器
                Vue.filter('globalFilter',function(value){
                    return value.toUpperCase()
                })
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        time: 1656912659058,
                    },
                    computed: {
                        formatTime(){
                            return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
                        }
                    },
                    filters: {
                        timeFormater(value,formatStr = 'YYYY-MM-DD HH:mm:ss'){
                            //第一个参数一定是value为管道符|前面的值
                            //后面的参数为传递的参数
                            return dayjs(value).format(formatStr)
                        },
                        getYear(value){
                            return value.slice(0,5)
                        }
                    }
                })
            script>
        body>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48

        总结:

        ​ 1.定义:对显示的数据进行特定格式化后再显示(适用于简单逻辑的处理)

        ​ 2.语法:

        Vue.filter('filterName',callback)全局过滤器

        new Vue{filters:{}} 局部过滤器

        ​ 3.过滤器可以接收额外的参数,第一个参数是管道符前面的值

        ​ 4.过滤器可以串联使用

        ​ 5.过滤器不改变原本的数据而是产生对应新的数据

        1.19.内置指令

        内置指令说明
        v-bind单向绑定 可简写为:xxx
        v-model双向绑定
        v-for列表渲染
        v-on绑定事件 可简写为@
        v-if条件渲染
        v-show条件渲染
        v-text向其所在的结点中渲染文本内容,不解析标签
        v-html向其所在结点中渲染html结构内容
        v-cloak没有值,Vue创建完容器后会删掉v-cloak属性
        v-once没有值,所在结点在初次动态渲染后就视为静态内容了
        v-pre没有值,跳过所在结点的编译过程,加快编译速度
        <body>
            <div id="root">
                
                <div v-text="info">div>
                
                
                <div v-html="info">div>
                
                <div v-once>{{info}}div>
                
                <div v-pre>你好div>
                <div v-pre>{{info}}div> 
            div>
        
            <script>
                Vue.config.productionTip = false
        
                const vm = new Vue({
                    el: '#root',
                    data: {
                        info: '

        Hello Vue

        '
        } })
        script> body>
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        <style>
            /* 一般配合css使用,可以解决网速慢时展示出未经编译的模板{{xxx}} */
            [v-cloak]{
                display: none;
            }
        style>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6

        1.20.自定义指令

        需求1:自定义v-big指令 功能和v-text类似但是会把数值放大10倍
        在这里插入图片描述

        <body>
            <div id="root">
                当前的num值是:<span v-text="num">span><br><br>
                num值放大10倍:<span v-big="num">span><br><br>
                <button @click="num++">点击num加1button>
            div>
        body>
        
        <script>
            Vue.config.productionTip = false
        
            const vm = new Vue({
                el: '#root',
                data: {
                    num: 5
                },
                directives: {
                    //定义指令的第一种方式,函数式
                    /* 
                    调用时机:
                        1.指令与元素绑定成功时
                        2.指令所在模板被重新解析时
                    */
                    big(element,binding){ //big: function(element,binding){} 完整写法
                        //element:指令所在真实DOM
                        //bingding:binding.value常用
                        element.innerText = binding.value * 10
                    }
                }
            })
        script>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31

        需求2:自定义v-fbind指令 功能与v-bind类似但可以默认获取焦点

        <body>
            <div id="root">
                <input type="text" v-bind:value="num"><br><br>
                <input type="text" v-fbind="num"><br><br>
                <button @click="num++">点击num加1button>
            div>
        body>
        
        <script>
            Vue.config.productionTip = false
        
            const vm = new Vue({
                el: '#root',
                data: {
                    num: 5
                },
                directives: {
                    //自定义指令的第二种方式:对象式
                    fbind:{
                        bind(ele,binding){
                            //指令和元素成功绑定时调用
                            ele.value = binding.value
                        },
                        inserted(ele,binding){
                            //指令所在元素被插入页面时调用
                            ele.focus()
                        },
                        update(ele,binding){
                            //指令所在模板被重新解析时调用
                            ele.value = binding.value
                            ele.focus()
                        }
                    }
                }
            })
        script>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36

        自定义指令总结:

        ​ 1.局部指令:定义在配置对象的directives中

        ​ 2.全局指令:Vue.directive(‘指令名’,配置对象)或Vue.directive(‘指令名’,回调函数)

        ​ 3.定义指令时不加v- 但使用指令时要加v-

        ​ 4.指令名如果是多个单词用-隔开,不要写成驼峰式

        ​ 5.directives中的函数中的this指向Window

        1.21.生命周期

        1.生命周期函数又叫生命周期钩子

        2.生命周期钩子就是Vue在关键的时刻帮我们调用的特殊名称的函数

        3.生命周期函数的名字不可更改

        4.生命周期函数中的this指向vm实例对象或组件实例

        5.vm.$destory() 完全销毁vm实例

        在这里插入图片描述

        生命周期钩子说明
        beforeCreate数据代理被创建之前
        created数据代理被创建之后
        beforeMount真实DOM被挂在到页面之前
        mounted(常用)真实DOM被挂在到页面之后
        beforeUpdate_data数据发生变化之前
        updated_data数据发生变化之后
        beforeDestroy(常用)vm对象被销毁之前
        destroyedvm对象被销毁之后

        template属性使用

        <body>
            <div id="root">
        		
            div>
        body>
        
        <script>
            Vue.config.productionTip = false
        
            const vm = new Vue({
                el: '#root',
                //不能用