Vue 3.0 学习笔记(面向数据编程)(二)

Vue 3.0 学习笔记(面向数据编程)(二)

内容目录

第二章 Vue 基础语法

1.理解vue中的生命周期函数
2.常用模板语法讲解
3.数据、方法、计算属性和监听器
4.样式绑定语法
5.列表循环渲染
6.时间绑定
7.表单中双向绑定指令的使用

理解Vue中的生命周期函数

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 7</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>


<body>
    <div id="root"></div>
</body>
<script>
    // 生命周期函数:在某一时刻会自动执行的函数。也叫做 钩子函数  hook
    const app = Vue.createApp({
        data() {
            return {
                message: 'hello world'
            }
        },

        // 在实例生成之前自动执行的函数 1
        beforeCreate() {
            console.log('beforeCreate')
        },

        // 在实例生成之后自动执行的函数 2
        created() {
            console.log('created')
        },

        // 在模板已经被编程为函数之后立即执行的函数 3
        // 也可以理解为 在组件内容被渲染到页面之前自动执行的函数
        // 如果没有vue中没有template,会取挂载点的innerHTML作为模板
        beforeMount() {
            console.log(document.getElementById('root').innerHTML)
            console.log('beforeMount')
        },

        // 在组件内容被渲染到页面之后自动执行的函数 4
        mounted() {
            console.log(document.getElementById('root').innerHTML)
            console.log('mounted')
        },

        // 当data中的数据发生变化时,会立即自动执行的函数 5
        // 可以在控制台执行:vm.$data.message = 'hi';
        beforeUpdate(){
            console.log(document.getElementById('root').innerHTML, 'beforeUpdate')
        },

        // 当data中的数据发生变化,同时页面完成更新后,即页面重新渲染后,自动执行的函数 6
        updated(){
            console.log(document.getElementById('root').innerHTML, 'updated')
        },


        // 当vue应用失效时,自动执行的函数 7
        // 可以在控制台中执行: app.unmount();
        beforeUnmount(){
            console.log(document.getElementById('root').innerHTML, 'beforeunmont')
        },

        // 当vue应用失效,且dom完全销毁之后,自动执行的函数 8
        // vue应用失效 = vue实例销毁 = 将挂载的vue移除
        unmounted(){
            console.log(document.getElementById('root').innerHTML, 'unmounted')
        },
        template: '<div>{{message}}</div>'
    });

    const vm = app.mount('#root');
</script>

</html>
知识点整理
1.生命周期函数,也叫做钩子(hook)函数,即在某一个时刻会自动执行的函数
	生命周期函数目前有四对,也就是8个函数,每对函数发生在一个动作的前后
	一、创建实例,create,自动触发:
		beforeCreate:在实例生成之前会自动执行的函数
		created:在实例生成之后会自动执行的函数
	二、加载模板,mount,自动触发:
		beforeMount:在组件内容被渲染到页面之前自动执行的函数
		mounted:在组件内容被渲染到页面之后自动执行的函数
	三、渲染模板,update,需要满足条件触发:
		beforeUpdate:在data中的数据发生变化时,会立即自动执行的函数
		updated:当data中的数据发生变化,同时页面完成更新后,即页面重新渲染后,自动执行的函数
	四、销毁实例=vue应用失效=移除挂载,unmount,需要满足条件触发:
		beforeUnmount:vue应用失效之前执行的函数
		unmounted:vue应用失效之后执行的函数
2.这四对函数,前两对可以自动触发,updata和unmount对应的两对函数需要条件触发
	update,可以在控制台中变更data中的数据,来验证函数的效果,如:vm.$data.message = xxx;
	unmount,可以控制台中手动销毁实例,来验证函数的效果,如:app.unmount();

常用模板语法讲解

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 8</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>


<body>
    <div id="root"></div>
</body>
<script>
    // {{}} 插值表达式
	// 插值表达式里面可以写data中return的数据,methods中的方法,JS的表达式,但是不能写JS的语句
	
    // template里面的内容,也可以直接写在body对应的挂载标签下面,等价的
    
    // vue指令
    // v-html,插值表达式里面不能转义html标签,用这个v方法,可以将data中的html内容进行转换
    // 防止转义,让html真的就是html。比如用富文本编辑器保存的一段文本,肯定有大量的Html标签,为了显示的时候该加粗的加粗,该换行的换行,就加上v-html
    // v-bind,简写为 :  数据与组件做绑定需要用,比如disabled 、title
    // v-once,数据只渲染一次,之后即使值被改变,页面也不会重新渲染
    // v-if, 决定标签是否进行展示
    // v-show, 和v-if效果相同,也是决定标签是否展示
    // v-on,简写为 @ 事件绑定,对应的方法要写在methods对象中
    // v-model,双向绑定

    // template中的变量和数据来源于vue应用中的data,方法来源于methods
    // 动态属性,在template中,使用[]来表示一个属性,在data中传入一个具体的属性值,可以动态变化属性
    // v-bind和v-on都可以用动态属性
    // 动态属性和动态事件也可以称为 动态参数
    const app = Vue.createApp({
        data() {
            return {
                message: '<strong>hello world</strong>',
                disabled: false,
                show: false,
                name: 'title1',
                // name可以作为属性名,使属性更灵活,即    动态属性
                event: 'mouseenter',
                // event 这里为动态事件,可以随便变更event里面的值,从而变更事件

                // 动态属性和动态事件也可以称为 动态参数
            }
        },
        methods: {
            handleClick() {
                alert("click")
            },
            handleClick1(e) {
                // 阻止默认行为
                e.preventDefault();
            },
            handleClick2(e) {
                // 修饰符写法
                alert("click")
            }
        },
        template: `
        <div v-html="message" v-bind:title="message"></div>
            <input v-bind:disabled="disabled"/>
        <div>{{'a' + 'b'}}</div>
        <div>{{Math.max(1,2)}}</div>
        <div v-once>{{message}}</div>
        <div v-if='show'>{{message}}</div>
        <button v-on:click='handleClick'>提示</button>

        <br/>
        <div :[name]="message">{{message}}</div>
        <div @[event]='handleClick'>动态事件</div>

        <hr/>
        <form action="https://www.baidu.com" @click="handleClick1">
            <button type='submit'>提交</button>
        </form>

        <hr />
        <form action="https://www.baidu.com" @click.prevent="handleClick2">
            <button type='submit'>提交</button>
        </form>
        `
        // < div > {{ if(true) { console.log(1) } }}</div >     不能写JS的语句,可以写JS的表达式
    });

    const vm = app.mount('#root');
</script>

</html>
知识点整理
1.template里面的内容,也可以直接写在body对应的挂载标签下面,效果是一样的,等价写法
	template中的变量和数据来源于vue应用中data中return的数据,方法来源于methods
	动态属性,在template中,使用[变量]来表示一个属性,在data中传入对应变量的参数值,可以动态变化属性
	v-bind和v-on都可以用动态属性
	动态事件,写法与动态属性相同,将想要动态变化的事件用变量表示,然后在data中传入对应变量的值
	动态事件和动态属性也可以叫做动态参数
2.{{}} 插值表达式,里面用来存放变量,也可以存放JS表达式,但是不能用JS的语句
3.vue指令 
	一、v-html,因为插值表达式里面不能转义html标签,会按照字符串的样式输出,用这个v方法,可以将data中的html内容按照html的方式展示,该加粗加粗,该换行换行
	二、v-bind,简单写法为 : ,用来将属性与数据进行绑定,比如disabled,title
	三、v-on,简单写法为 @ ,用来将事件与标签进行绑定,对应的方法写在methods中
	四、v-once,数据只渲染一次,之后即使数据的值被改变,页面也不会重新渲染,避免无效渲染,提高性能
	五、v-if,决定标签是否要渲染到页面
	六、v-show,和v-if一样,也是决定标签是否要渲染到页面,只不过实现方式不同
	七、v-model,组件与数据双向绑定
4.修饰符,可以直接跟在时间或者方法的后面,简化常用代码编写,
	prevent 阻止默认事件执行,如在表单中加入此修饰符@click.prevent,点击提交按钮时,就不会跳转到提交的网址

计算属性和侦听器

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 9</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>


<body>
    <div id="root"></div>
</body>
<script>
    // data & methods & computed & watcher
    // computed 和 methods 都能实现的功能,建议使用computed,因为有缓存
    // computed 和 watch 都能实现的功能,建议使用computed,因为更加简洁

    // 异步操作的话,可以用watch,如果是同步操作的话,还是computed更好,更简洁。
    // 异步操作如 等待等待几秒再执行的函数

    // 当返回的数据为根数据,也就是数据在最外层时,vm.$data.message = vm.message 
    // 可以直接使用 vm.message来改变数据的值

    // 可以在插值表达式里面直接用methods里面的方法,如 toUpper
    const app = Vue.createApp({
        // 当返回的数据为根数据,也就是数据在最外层时,vm.$data.message = vm.message 
        // 可以直接使用 vm.message来改变数据的值
        data() {
            return {
                message: 'hello world',
                count: 2,
                price: 5,
                newTotal: 10
            }
        },

        // watch,监听器,能够监听数据变化,也能在监听数据变化时,执行函数
        // 也可以实现methods中的函数
        watch: {
            // current是当前渲染的值,prev是上一个值
            // 这里监听的是price数据,可以在控制台变更price的值来调试页面如:vm.$data.price = 6;
            price(current, prev) {
                console.log(current, prev)
                this.newTotal = current * this.count
            }

            //     当price的值变化时,延迟三秒在控制台打印字符
            // price(){
            //     setTimeout(() => {
            //         console.log('price data changed')
            //     }, 3000)
            // }

        },

        // computed, 计算属性,返回计算后的数据
        // 当计算属性依赖的内容发生变更时,才会重新执行计算
        // computed里面有缓存属性,相对于methods会更高效,如果依赖的内容没有变更,是不会重新计算的
        // 但是像Date这种时间数据是无法监听的,也是一个弊端,因为Date不依赖其他信息,无法监听
        // computed 可以实现methods中的一些计算功能
        // computed 和 methods 都能实现的功能,建议使用computed,因为有缓存
        computed: {
            total() {
                return this.count * this.price
            },
            time() {
                return Date.now() + this.count;
            }
        },

        // methods内方法中的this都指向vue实例
        methods: {
            handleClick() {
                console.log('click', this.message)
            },
            // 如果用箭头函数,指向的是外层实例,在这里,因为外层没有其他的this,指向的为window
            handleClick1: () => {
                console.log('click', this.message, this)
            },
            formatString(string) {
                return string.toUpperCase();
            },
            // 只要页面重新渲染,就会重新计算。即使是methods方法中无关的数据发生改变,导致页面渲染,也要重新计算
            getTotal() {
                return this.count * this.price
            },
            getTime() {
                return Date.now();
            }
        },
        template: `
        <div @click="handleClick">未使用箭头函数 {{message}}</div>
        <hr/>
        <div @click="handleClick1">使用箭头函数 {{message}}</div>
        <hr/>
        <div @click="handleClick">插值表达式使用methods的方法 {{formatString(message)}}</div>
        <hr/>
        <div>插值表达式使用js表达式 {{ count * price }}</div>
        <hr/>
        <div>通过计算属性计算 {{total}}</div>
        <hr/>
        <div>通过methods方法计算 {{getTotal()}}</div>
        <hr/>
        <div>通过计算属性计算 {{time}}</div>
        <hr/>
        <div>通过methods方法计算 {{getTime()}}</div>
        <hr />
        <div>通过watch监听 {{price}},{{newTotal}}</div>
        `
    });

    const vm = app.mount('#root');
</script>

</html>
知识点整理
1.data 定义数据,data中return的数据可以被其他模块调用
	当数据为最外层的实例时,可以不用写vm.$data.message,直接使用vm.message也行
2.methods 定义方法
	一、方法中的this都指向vue实例
	二、如果用箭头函数,指向的是外层实例,示例中因为外层没有其他的this,指向的是window
	三、只要页面重新渲染,就会重新计算。即使变更的是与methods方法无关的数据,导致页面重新渲染,也会重新计算,可能会造成无效渲染,相对于computed性能较差
3.computed 计算属性,返回计算后的数据
	因为computed有缓存属性,只有依赖的内容发生变更时,才会重新计算。相对于methods更高效
	弊端:但是像Date这种动态时间数据时无法监听的,无法动态计算时间相关的数据
	computed和methods都能实现的功能,建议使用computed,因为有缓存,更高效
	computed和watch都能实现的功能,建议使用computed,写法更加简洁
4.watch,监听器,能够监听数据变化,也能在监听数据变化时,执行函数
	watch中的两个参数,current(当前渲染的值),prev(上一个值)

样式绑定语法

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 10</title>
    <style>
        .red {
            color: red;
        }

        .green {
            color: green;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>


<body>
    <div id="root"></div>
</body>
<script>
    // vue中的行内样式,可以直接在template中直接写style样式,也可以使用在data中定义的数据来控制样式
    // 也可以通过注册子组件,来控制样式
    // 区分父子组件:主动调用的是父组件,被动调用的是子组件
    // 当有多个颜色渲染同一个标签式,后面的颜色会覆盖之前的颜色
    const app = Vue.createApp({
        data() {
            return {
                classString: 'red',
                // 通过创建对象来控制样式
                classObject: { red: true, green: true },
                // 通过Array数组来控制样式,数组里面可以放对象
                classArray: ['red', 'green', { balck: true }],
                // 行内样式也可以用字符串或者对象来渲染
                styleString: 'color:yellow',
                styleObject: {
                    color: "orange",
                    background: 'yellow'
                }
            }
        },
        template: `
        <div :class='classString'>
            Hello, World!!!
            <demo class='green'/>
        </div>
        <hr />
        <div :class='classArray'>通过Array数组来控制样式</div>
        <hr />
        <div :class='classObject'>通过对象来控制样式</div>
        <hr />
        <div :style="styleString">通过字符串控制行内样式</div>
        <hr />
        <div :style="styleObject">通过对象控制行内样式</div>
        <hr />
        <p>当子组件中有多个节点时,且每个节点都没有指定样式,是无法通过父组件中的样式进行样式渲染的,需要指定每个节点的样式</p>
        <div :class='classString'>
            Hello, World!!!
            <test class='green'/>
        </div>
        `
    });

    // vue实例的组件,被调用的是子组件
    app.component('demo', {
        // $attrs.class 子组件的样式用的是父组件的class的值
        template: `
        <div :class="$attrs.class">one</div>
        <div class='green'>single</div>
        `
    }),
    app.component('test',{
        // 当子组件中有多个节点时,且每个节点都没有指定样式,是无法通过父组件进行样式渲染的,需要指定每个节点的样式
        template:`
        <div>one</div>
        <div>two</div>
        `
    })
    const vm = app.mount('#root');
</script>

</html>
知识点整理
1.vue中的标签样式和行内样式,可以直接在template中定义,也可以使用data中定义的数据来控制
2.使用data中的不同数据类型控制样式,可以使用字符串,对象,数组来控制样式
	数组中也可以放对象
	如果数组或者对象中有多个颜色渲染后,后面的颜色会覆盖之前的颜色
3.区分父子组件:主动调用的是父组件,被动调用的是子组件
4.子组件中的样式控制,
	如果子组件中只有一个标签,那么可以直接使用父组件的样式
	如果子组件中有多个标签,那么需要指定每一个标签的样式
	如果子组件想要使用父组件的样式,可以使用$attr.class这种写法

条件渲染

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 11</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>


<body>
    <div id="root"></div>
</body>
<script>
    // 知识点1:v-if和v-show
    // v-if 直接移除dom
    // v-show 加了display的style属性

    // 知识点2:v-if  v-else-if  v-else
    // 使用的时候,对应的标签要挨在一起,通过data中的true或者false来判断
    const app = Vue.createApp({
        data() {
            return {
                show: false,
                conditionOne: false,
                conditionTwo: true,
                show1: true
            }
        },
        template: `
        <div v-if="show">Hello, World!!!</div>


        <div v-if="conditionOne">if</div>
        <div v-else-if="conditionTwo">elseif</div>
        <div v-else>else</div>

        <div v-show="show">Bye, World!!!</div>
        `
    });
    const vm = app.mount('#root');
</script>

</html>
知识点整理
1.v-if 通过控制元素在dom上的存在与否来控制展示或者有隐藏,也可以理解为v-if是控制否是插入标签的
2.v-show 通过style的display来控制是否展示,只是加了隐藏的style样式,不会频繁销毁dom
	v-if和v-show都是控制组件在页面上是否渲染,只是实现方式不同,频繁使用时建议使用v-show,性能更好一点
3. v-if、v-else-if、v-else三个指令使用时要挨在一起,中间不能分隔
	除了v-else,v-if和v-else-if都是通过值是否为true或者false来判断标签是否显示

列表循环渲染

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 12</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>


<body>
    <div id="root"></div>
</body>
<script>
    // 列表循环渲染,列表的数据可以用数组来存储,也可以用对象来存储
    // 遍历数组:v-for="(item, index) of list"
    // 遍历对象:v-for="(value, key, index) of obj"

    // 使用 v-for的时候,尽量加一个 key,能够复用之前没有变化的值,减少重复渲染,
    // key一般不用index做值,尽量使用key来绑定唯一的值,这样在页面再次渲染的时候,根据key查询对应的值是否发生变化,如果没有就可以直接复用,不需要重新创建DOM,提高性能
    
    // 变更列表中的元素信息,有几种方法
    // 第一种:使用列表的变更函数
    // push 在列表的末尾增加元素,尾部新增
    // pop 删除列表的最后一个元素,尾部删除
    // shift 删除列表的第一个元素,头部删除
    // unshift 在列表的开头新增一个元素,头部新增
    // splice 替换列表中的部分内容
    // sort 对列表进行排序
    // reserve 翻转列表中元素的位置

    // 第二种:直接替换数组
    // 第三种:直接更新数组内容

    // list对象的渲染   v-for的优先级比v-if的优先级高,如果标签属性中已经有了v-for,后面再加v-if是不会生效的

    // 可以使用template替换div,template可以理解为是一个占位符,不会在页面上进行渲染
    const app = Vue.createApp({
        data() {
            return {
                listArray: ['dell', 'lee', 'teacher'],
                listObject: {
                    firstName: 'dell',
                    lastName: 'lee',
                    job: 'teacher'
                }
            }
        },
        methods: {
            handleAddBtnClick() {
                // 数组的变更函数 push, pop, shift, unshift, splice, sort, reverse
                // this.listArray.push("hello")
                // this.listArray.pop()
                // this.listArray.shift()
                // this.listArray.unshift('hello')
                // this.listArray.reverse()

                // 直接替换数组
                // this.listArray = ['bye', 'world']
                // this.listArray = ['bye'].concat(['world'])
                // this.listArray = ['bye', 'world'].filter(item => item === 'bye')

                // 直接更新数组的内容
                this.listArray[1] = 'Hello'
            },
            handleAddBtnClick1() {
                // 直接添加对象的内容,也可以自动的展示出来
                this.listObject.age = 100;
                this.listObject.sex = 'male'
            }
        },
        template: `
        <div>
            <div v-for="(item, index) in listArray" :key='index'>
                {{item}} -- {{index}}
            </div>
        </div>
        <br />
        <button @click='handleAddBtnClick'>新增</button>


        <hr />
        <div>
            <template v-for="(value, key, index) in listObject" :key='index'>
                <div v-if="key !== 'lastName'">
                    {{value}} -- {{key}} -- {{index}}
                </div>
            </template>
        </div>
        <button @click='handleAddBtnClick1'>新增</button>


        <hr />
        <div v-for="(item, index) in 5" :key='index'>{{item}} -- {{index}}</div>

        <hr />
        <template v-for="(item, index) in listArray" :key='index'>
                <div v-if="item !== 'lee'">
                    {{item}} -- {{index}}
                </div>
        </template>
        `
    });
    const vm = app.mount('#root');
</script>

</html>
知识点整理
1.列表循环渲染,列表的数据可以用数组来存储,也可以用对象来存储
	遍历数组:v-for="(item, index) of list"
	遍历对象:v-for="(value, key, index) of obj"
2.在使用v-for对数组或对象进行遍历时,最好加一个key,能够复用之前没有变化的值,减少重复渲染
	key一般不用index做值,尽量使用key来绑定唯一的值,这样在页面再次渲染的时候,
	根据key查询对应的值是否发生变化,如果没有就可以直接复用,不用创建新的DOM,从而提高性能
3.变更数组列表中的元素信息,有几种方法:
	第一种:使用列表的变更函数,没有改变数组的引用
		push:在列表末尾增加元素,尾部新增
		pop:删除列表的最后一个元素,尾部删除
		shift:删除列表的第一个元素,头部删除
		unshift:在列表的开头新增一个元素,头部新增
		splice:替换列表中的部分内容
		sort:对列表进行排序
		reserve:翻转列表中元素的位置
	第二种:直接替换数组,改变了数组的引用,以上方代码为例
		this.listArray = ['bye', 'world']
        this.listArray = ['bye'].concat(['world'])		//这里用到了JS的表达式
        this.listArray = ['bye', 'world'].filter(item => item === 'bye')      //这里加了个过滤条件
	第三种:直接更新数组的内容,没有改变数组的引用
		this.listArray[1]='Hello'
4.列表对象的渲染,与列表数据的写法类似,需要注意遍历返回的每一项是value。
5.v-for的优先级比v-if的优先级高,如果标签属性中已经有了v-for,后面再加v-if是不会生效的
	可以将当前标签替换为<template>标签,然后在标签下再去新增一个子标签,将v-if放在子标签内
	v-for和v-if不写在同一个标签里面
6.<template></template> 占位符标签,可以替换<div>标签
	<template>标签主要是为了体现语义结构,不会渲染出真实的标签,在开发中更实用一些
	具体效果可以打开F12查看页面元素

事件绑定

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 13</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>


<body>
    <div id="root"></div>
</body>
<script>
    // 简单的方法可以直接写在@click后面
    // 在template中想使用原生的事件,就要在函数中加上 $对应的原生事件名
    // 比如事件绑定,有默认参数event,当方法中传入其他参数后再想获取event时,需要传入$event参数
    // 同时使用多个事件时,写在一起用逗号分开,且需要在方法名后面加上括号

    // 事件修饰符,
    // .stop    阻止事件冒泡
    // .self    事件不作用在子标签上,一般嵌套标签时使用
    // .prevent 阻止默认行为
    // .capture 把事件的运营方式由冒泡改为捕获   也就是从内到外,改成从外到内
    // .once    事件绑定只执行一次
    // .passive scroll滚动事件使用,提升滚动性能


    // 事件修饰符:stop, prevent, capture, self, once, passive
    // 按键修饰符:enter, tab, delete, esc, up, down, left, right
    // 鼠标修饰符:left, right, middle
    // 精确修饰符:exact

    // 组织单击事件继续传播
    // <a href="#top" @click.stop="doThis" > 单击事件</a >
    // 提交事件不再重载页面
    // <form @submit.prevent="onSubmit" > 提交事件</form >
    // 修饰符可以串联
    //  <a @click.stop.prevent="doThis" > 单击事件</a >
    // 只有修饰符
    // <form @submit.prevent> 提交事件</form >

    const app = Vue.createApp({
        data() {
            return {
                counter: 0,
            }
        },
        methods: {
            // 也可以直接写为 @click="counter += 1"
            handleBtnClick(num, event) {
                console.log(event)
                // console.log(event.target)
                this.counter += num
            },
            handleBtnClick1() {
                alert(1);
            },
            handleBtnClick2() {
                alert(2);
            },
            // 修饰符
            handleBtnClick3() {
                this.counter += 1;
            },
            handleDivClick() {
                alert('div clicked')
            },
            // 鼠标修饰符
            handleKeyDown() {
                console.log('keydown')
            },
            handleClick() {
                console.log('click')
            }
        },
        template: `
        <div>
            {{counter}}
            <button @click='handleBtnClick(2, $event)'>button</button>
            <hr />
            <p>多个事件</p>
            <button @click='handleBtnClick1(), handleBtnClick2()'>button</button>
            <hr />
            <div @click.self="handleDivClick">
                {{counter}}
                <button @click.stop="handleBtnClick3">button</button>
            </div>
        </div>

        <hr />
        <div>
            <input @keydown.enter="handleKeyDown"/>
        </div>
        <hr />
        <div>
            <div @click="handleClick">123</div>
        </div>
        `
    });
    const vm = app.mount('#root');
</script>

</html>
知识点整理
1.在template中想使用原生的事件,就要在函数的参数中加上:  $对应的原生事件
	如:@click='handleBtnClick(2, $event)
	如果同时使用多个事件,写在一起时用逗号分开,且在方法名后面需要加上括号
	如:@click='handleBtnClick1(), handleBtnClick2()
	有多个事件时,发生的顺序是冒泡的,即由内向外,一层一层执行
2.事件修饰符,可以理解为是对事件的一些影响
	stop		阻止事件冒泡
	self		事件只作用在标签本身,不作用在子标签上,一般嵌套标签时使用
	prevent	阻止默认行为
	capture	把事件的运营方式由冒泡改为捕获	也就是由从内到外,改成从外到内
	once		事件绑定只执行一次
	passive	scroll滚动事件使用,提升滚动性能
3.按键修饰符:enter,tab,delete,esc,up,down,left,right
4.鼠标修饰符:left,right,middle
5.精确修饰符:exact
	例如:@click.ctrl,只要是按着ctrl键,或者按着ctrl+其他按键,都能触发事件
			@click.ctrl.exact,只有只按着ctrl一个键时,才能触发事件

表单中双向绑定指令的使用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>lesson 14</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>


<body>
    <div id="root"></div>
</body>
<script>
    // input, textarea, checkbox, radio, select
    // 修饰符 lazy, number, trim

    // 双向绑定v-model:一方改变,另一方同样改变
    // input:写了v-model后,可以不用写value
    // textarea:使用双向绑定时,可以写成单标签<textarea v-model="..." />
    // checkbox:多选,如果想要获取选中的选项,绑定一个空数组,被选中选项的value值会被添加到绑定的数组中
    // radio:单选,可以绑定空字符串,因为单选只能选中一个

    // 单选和多选都可以绑定一个bool值,尤其单选作为一个开关时,很有用
    // 如果只是想存储true/false的时候,可以给checkbox绑定bool值

    // 当想要选中状态下,存储或展示的数据不是true,而是hello,未选中的状态下,存储或展示的数据不是false,而是world,
    // 可以使用true-value="hello",false-value="world"

    // lazy:失去焦点的时候才同步数据,可以提高性能
    // number:同步数据的时候,把字符串转换为数值类型
    // trim:同步数据的时候,去掉字符串前后的空格
    const app = Vue.createApp({
        data() {
            return {
                message: 'hello',
                message1: 'hello',
                messageList: [],
                messageString: '',
                selectValue: [],
                options: [{
                    text: 'A', value: { value: 'A' }
                }, {
                    text: 'B', value: 'B'
                }, {
                    text: 'C', value: 'C'
                }]
            }
        },
        template: `
        <div>
            <p>输入框的双向绑定</p>
            {{message}}
            <input v-model="message" />

            <hr />
            <p>文本框的双向绑定</p>
            <textarea v-model="message"/>

            <hr />
            <p>checkbox的多选,绑定了一个空数组列表</p>
            {{messageList}}
            jack <input type="checkbox" v-model="messageList" value="jack-value"/>
            dell <input type="checkbox" v-model="messageList" value="dell-value"/>
            lee <input type="checkbox" v-model="messageList" value="lee-value"/>

            <hr />
            <p>redio的单选,绑定了一个空字符串</p>
            {{messageString}}
            jack <input type="radio" v-model="messageString" value="jack-value"/>
            dell <input type="radio" v-model="messageString" value="dell-value"/>
            lee <input type="radio" v-model="messageString" value="lee-value"/>

            <hr />
            <p>可以多选的下拉列表,绑定了一个空数组列表</p>
            {{selectValue}}
            <select v-model="selectValue" multiple>
                <option disabled value=''>请选择内容</option>
                <option>A</option>
                <option>B</option>
                <option>C</option>
            </select>

            <hr />
            <p>可以多选的下拉列表,v-for遍历了一个对象列表</p>
            {{selectValue}}
            <select v-model="selectValue" multiple>
                <option v-for="item in options" :value="item.value">{{item.text}}</option>
            </select>

            <hr />
            <p>控制了不同选中状态的value值</p>
            {{message}}
            <input type="checkbox" v-model="message" true-value="hello" false-value="world">

            <hr />
            <p>失去焦点时才同步数据,可以提高性能</p>
            {{message}}
            <input v-model.lazy="message" type="number"/>

            <hr />
            <p>将输入的信息转化为数值类型</p>
            {{typeof message1}}
            <input v-model.number="message1" type="number"/>

            <hr />
            <p>去除输入字符串的首尾空格</p>
            {{message1}}
            <input v-model.trim="message1" />
        </div>
        `
    });
    const vm = app.mount('#root');
</script>

</html>
知识点整理
1.v-model 双向绑定,一方改变,另一方同样改变
	input:写了v-model后,可以不用写value
	textarea:使用双向绑定时,可以写成单标签<textarea v-model="..." />
	checkbox:多选,如果想要获取选中的选项,绑定一个空数组,被选中选项的value值会被添加到绑定的数组中
	redio:单选,可以绑定空字符串,因为单选只能选中一个
	单选和多选都可以绑定一个bool值
2.当单选或者多选的选项想要选中状态下,存储在data中的数据或者页面展示的数据不是true,而是hello
	可以使用true-value="hello",未选中的状态下可以使用false-value
3.v-model的修饰符
	lazy:失去焦点的时候才同步数据,可以提高性能
	number:同步数据的时候,把字符串转换为数值类型
	trim:同步数据的时候,去掉字符串前后的空格
上一篇:vue-组件间通信


下一篇:Vue笔记5 : 混入