vue——day02

115 阅读8分钟

1、事件的基本使用

<body>
    <!-- 
        事件的基本使用:
            1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
            2.事件的回调需要配置在methods对象中,最终会在vm上;
            3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;
            4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
            5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;
    -->
    <!-- 准备好一个容器-->
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <button v-on:click="showInfo">点我提示信息</button>
        <button @click="showInfo1">点我提示信息1(不传参)</button>
        <button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
    </div>
</body>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            name:'北京',
        },
        methods:{
            showInfo1(event){
                // 事件对象,e.target.innerText获取的是触发事件的元素的文本
                console.log(event.target.innerText)
                console.log(this) //此处的this是vm
                alert('你好!')
            },
            showInfo2(event,number){
                console.log(event,number)
                console.log(event.target.innerText)
                console.log(this) //此处的this是vm
                alert('你好!!')
            }
        }
    })
</script>

事件修饰符:

<!-- 
    Vue中的事件修饰符:
        1.prevent:阻止默认事件(常用);
        2.stop:阻止事件冒泡(常用);
        3.once:事件只触发一次(常用);
        4.capture:使用事件的捕获模式;
        5.self:只有event.target是当前操作的元素时才触发事件;
        6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
-->
<!-- 阻止默认事件(常用) -->
<a href="http://www.baidu.com" @click.prevent="showInfo">点我提示信息</a>

<!-- 阻止事件冒泡(常用) -->
<div class="demo1" @click="showInfo">
    <button @click.stop="showInfo">点我提示信息</button>
    <!-- 修饰符可以连续写 -->
    <a href="http://www.baidu.com" @click.prevent.stop="showInfo">点我提示信息</a>
</div>

<!-- 事件只触发一次(常用) -->
<button @click.once="showInfo">点我提示信息</button>

<!-- 使用事件的捕获模式 -->
<div class="box1" @click.capture="showMsg(1)">
div1
    <div class="box2" @click="showMsg(2)">
        div2
    </div>
</div>

<!-- 只有event.target是当前操作的元素时才触发事件; -->
<div class="demo1" @click.self="showInfo">
    <button @click="showInfo">点我提示信息</button>
</div>

键盘事件:

<body>
<!-- 
    1.Vue中常用的按键别名:
        回车 => enter
        删除 => delete (捕获“删除”和“退格”键)
        退出 => esc
        空格 => space
        换行 => tab (特殊,必须配合keydown去使用)
        上 => up
        下 => down
        左 => left
        右 => right
    2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
    3.系统修饰键(用法特殊):ctrl、alt、shift、meta
        (1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
        (2).配合keydown使用:正常触发事件。
    4.也可以使用keyCode去指定具体的按键(不推荐,不同的键盘编码不统一)  按键编码
    5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名(不推荐,目前的已经够使用了)
-->
    <!-- 准备好一个容器-->
    <div id="root">
        <h2>欢迎来到{{name}}学习</h2>
        <!-- 键盘事件并且按下回车才执行事件 -->
        <input type="text" placeholder="按下回车提示输入" @keydown.enter="showInformation">
        <input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo">
    </div>
</body>

<script>
    Vue.config.keyCodes.huiche = 13 //定义了一个别名按键
    new Vue({
        el:'#root',
        data:{
            name:'北京'
        },
        methods: {
            showInfo(e){
                console.log(e.key,e.keyCode)
                console.log(e.target.value)
            }
        },
    })
</script>

2、计算属性computed(有缓存)

<!-- 
计算属性:
    1.定义:要用的属性不存在,要通过已有属性计算得来。
    2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
    3.get函数什么时候执行?
        (1).初次读取时会执行一次。因为有缓存
        (2).当依赖的数据发生改变时会被再次调用。
    4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
    5.备注:
        1.计算属性最终会出现在vm上,直接读取使用即可。{{fulName}}
        2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
-->
<body>
    <!-- 准备好一个容器-->
    <div id="root">
        姓:<input type="text" v-model="firstName"> <br/><br/>
        名:<input type="text" v-model="lastName"> <br/><br/>
        测试:<input type="text" v-model="x"> <br/><br/>
        <!-- fullName最终会出现在vm上,直接调用即可 -->
        全名:<span>{{fullName}}</span> 
    </div>
</body>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            firstName:'张',
            lastName:'三',
            x:'你好'
        },
        computed:{
            fullName:{
                //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
                //get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
                get(){
                    console.log('get被调用了')
                    console.log(this) //此处的this是vm
                    return this.firstName + '-' + this.lastName
                },
                //set什么时候调用? 当fullName被修改时。
                set(value){
                    console.log('set',value)
                    const arr = value.split('-')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                }
            }
        }
    })
</script>

计算属性简写(只读取不修改)

const vm = new Vue({
    el:'#root',
    data:{
        firstName:'张',
        lastName:'三',
    },
    computed:{
        //完整写法
        fullName:{
                get(){
                    console.log('get被调用了')
                    return this.firstName + '-' + this.lastName
                },
                set(value){
                    console.log('set',value)
                    const arr = value.split('-')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                }
        } 
        //简写(前提是只用到getter,没有用到setter)(只读取,不修改)
        fullName(){
            console.log('get被调用了')
            return this.firstName + '-' + this.lastName
        }
    }
})

3、监听属性

<!-- 准备好一个容器-->
<div id="root">
    <h2>今天天气很{{info}}</h2>
    <!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句 -->
    <!-- <button @click="isHot = !isHot">切换天气</button> -->
    <button @click="changeWeather">切换天气</button>
</div>
<!-- 
    监视属性watch:
        1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
        2.监视的属性必须存在,才能进行监视!!
        3.监视的两种写法:
                (1).new Vue时传入watch配置
                (2).通过vm.$watch监视
-->
// 第一种写法
const vm = new Vue({
            el:'#root',
            data:{
                isHot:true,
            },
            watch:{
                isHot:{
                    immediate:true, //初始化时让handler调用一下
                    //handler什么时候调用?当isHot发生改变时。
                    handler(newValue,oldValue){
                        console.log('isHot被修改了',newValue,oldValue)
                    }
                }
            } 
    })
    
//第二种写法
vm.$watch('isHot',{
                        immediate:true, //初始化时让handler调用一下
                        //handler什么时候调用?当isHot发生改变时。
                        handler(newValue,oldValue){
                            console.log('isHot被修改了',newValue,oldValue)
                        }
                })

深度监听(添加deep:true)

<body>
    <!-- 
        深度监视:
            (1).Vue中的watch默认不监测对象内部值的改变(一层)。
            (2).配置deep:true可以监测对象内部值改变(多层)。
        备注:
            (1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
            (2).使用watch时根据数据的具体结构,决定是否采用深度监视。
    -->
    <!-- 准备好一个容器-->
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">切换天气</button>
        <hr/>
        <h3>a的值是:{{numbers.a}}</h3>
        <button @click="numbers.a++">点我让a+1</button>
        <h3>b的值是:{{numbers.b}}</h3>
        <button @click="numbers.b++">点我让b+1</button>
        <button @click="numbers = {a:666,b:888}">彻底替换掉numbers</button>
        {{numbers.c.d.e}}
    </div>
</body>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
        isHot:true,
        numbers:{
            a:1,
            b:1,
            c:{
                d:{
                    e:100
                    }
                }
            }
        },
        computed:{
        info(){
            return this.isHot ? '炎热' : '凉爽'
            }
        },
        methods: {
            changeWeather(){
                this.isHot = !this.isHot
            }
        },
        watch:{
            isHot:{
                    // immediate:true, //初始化时让handler调用一下
                    //handler什么时候调用?当isHot发生改变时。
                    handler(newValue,oldValue){
                        console.log('isHot被修改了',newValue,oldValue)
                    }
            },
            //监视多级结构中某个属性的变化
            'numbers.a':{
                    handler(){
                        console.log('a被改变了')
                    }
                } 
            //监视多级结构中所有属性的变化
            numbers:{
                deep:true,
                handler(){
                    console.log('numbers改变了')
                }
            }
        }
    })
    </script>

深度监听简写(不需要immediate,也不需要deep,只需要handler时,可以简写)

watch:{
        // 简写
        // 使用的是普通函数,不能使用箭头函数,this指向问题
         isHot(newValue,oldValue){
                console.log('isHot被修改了',newValue,oldValue)
        } 
}
// 简写
// 使用的是普通函数,不能使用箭头函数,this指向问题
vm.$watch('isHot',function (newValue,oldValue){
    console.log('isHot被修改了',newValue,oldValue)
}) 

watch与computed的区别

<!-- 
    computed和watch之间的区别:
        1.computed能完成的功能,watch都可以完成。
        2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。(比如说加个定时器)
        原因:计算属性computed是依靠返回值 return 得到的
    两个重要的小原则:
        1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
        2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),  最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。
-->
watch:{
    firstName(val){
        // 使用箭头函数,不能用普通函数
        setTimeout(()=>{
                console.log(this)
                this.fullName = val + '-' + this.lastName
        },1000);
    },
}

4、绑定样式(class类名和style样式)

<body>
    <!-- 
        绑定样式:
        1. class样式
            写法:class="xxx" xxx可以是字符串、对象、数组。
                字符串写法适用于:类名不确定,要动态获取。
                对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
                数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
        2. style样式
                :style="{fontSize: xxx}"其中xxx是动态值。
                :style="[a,b]"其中a、b是样式对象。
    -->
    <!-- 准备好一个容器-->
    <div id="root">
        <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
        <div class="basic" :class="mood" @click="changeMood">{{name}}</div> <br/><br/>

        <!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
        <div class="basic" :class="classArr">{{name}}</div> <br/><br/>

        <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
        <!-- 通过布尔值来控制样式 -->
        <div class="basic" :class="classObj">{{name}}</div> <br/><br/>

        <!-- 绑定style样式--对象写法 -->
        <div class="basic" :style="styleObj">{{name}}</div> <br/><br/>
        <!-- 绑定style样式--数组写法 -->
        <div class="basic" :style="styleArr">{{name}}</div>
    </div>
</body>

<script>
    const vm = new Vue({
        el:'#root',
        data:{
            name:'阿里',
            mood:'normal',
            classArr:['at1','at2','at3'],
            classObj:{
                    at1:false,
                    at2:false,
            },
            styleObj:{
                    fontSize: '40px',
                    color:'red',
            },
            styleObj2:{
                    backgroundColor:'orange'
            },
            styleArr:[
                    {
                            fontSize: '40px',
                            color:'blue',
                    },
                    {
                            backgroundColor:'gray'
                    }
            ]
        },
        methods: {
            changeMood(){
                    const arr = ['happy','sad','normal']
                    const index = Math.floor(Math.random()*3)
                    this.mood = arr[index]
            }
        },
    })
</script>

5、条件渲染(v-if、v-show)
v-if 和 v-show 都是 Vue.js 中用于条件渲染的指令。
v-if 是"真正的"条件渲染,它会根据表达式的真假来决定是否渲染元素到 DOM 中。当条件为假时,元素及其子组件都不会被渲染到页面上,从而节省了渲染开销。
v-show 也是根据表达式的真假来控制元素的显示与隐藏,但它不会真正地销毁和重建元素,而是通过修改元素的 display CSS 属性来控制元素的显示与隐藏。因此,即使条件为假,元素的 DOM 元素也会保留在页面上,只是不可见而已。

<!-- 
    条件渲染:
        1.v-if
            写法:
                (1).v-if="表达式" 
                (2).v-else-if="表达式"
                (3).v-else="表达式"
                适用于:切换频率较低的场景。
                特点:不展示的DOM元素直接被移除。
                注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。

        2.v-show(控制的是display属性)
            写法:v-show="表达式"
            适用于:切换频率较高的场景。
            特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

        3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
-->
<!-- 准备好一个容器-->
<div id="root">
    <!-- 使用v-show做条件渲染 -->
    <h2 v-show="false">欢迎来到{{name}}</h2>
    <h2 v-show="1 === 1">欢迎来到{{name}}</h2>

    <!-- 使用v-if做条件渲染 -->
    <h2 v-if="false">欢迎来到{{name}}</h2>
    <h2 v-if="1 === 1">欢迎来到{{name}}</h2>

    <!-- v-else和v-else-if -->
    <div v-if="n === 1">Angular</div>
    <div v-else-if="n === 2">React</div>
    <div v-else-if="n === 3">Vue</div>
    <div v-else>哈哈</div> 

    <!-- v-if与template的配合使用 -->
    <template v-if="n === 1">
        <h2>你好</h2>
        <h2>尚硅谷</h2>
        <h2>北京</h2>
    </template>
</div>