键盘事件:

涉及到要获取的数据

  • event.keyCode 获取按键编码

  • event.key 按键名

@keyup 按键抬起

@keydown 按键松开

@keyup.enter 是Vue中常用的按键别名

回车 enter

删除 delete (捕获“删除”和“退格”)

空格 space

退出 esc

换行 tab(tab键的神奇作用:将这个焦点从这个元素身上切走,由此不适合使用keyup,而使用keydown使用)

上下左右:up,down,left,right

Vue未提供别名的按键,可以使用按键原始的值去绑定,但注意,要转为kebab-case(短横线命名)

系统修饰键:ctrl,alt,shift,meta(就是win键)

    配合keyup使用,按下修饰键的同时,再按下其他键,随后释放其他键,事件才会触发

    例如ctrl+其他按键,释放其他按键

    配合keydown使用,正常触发事件

也可以使用keyCode去指定具体的按键(不推荐,不同的键盘编码可能不统一)

Vue.config.keyCodes.自定义键名=键码,可以去定制按键别名

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>你好啊!</title>
    <script type="text/javascript" src="../JS/vue.js"></script>
</head>

<body>
    <div id="root">
        <h1>你好,{{name}}</h1>
        <input type="text" placeholder="按下按键得到按键和按键编码" @keyup="showInfo">
        <input type="text" placeholder="按下capslock得到输入" @keyup.caps-lock="showInfo2">
        <input type="text" placeholder="这里测试ctrl等系统修饰键,得到除系统修饰键以外的其他按键" @keyup.ctrl="showInfo3">
        
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        Vue.config.keyCodes.huiche=13//定义了一个别名,虽然仍然不被推荐
        new Vue({
            el: "#root",
            data: {
                name: "柠"
            },
            methods:{
                showInfo(event){
                    // if(event.keyCode!=13) return
                    console.log(event.key+" "+event.keyCode)
                    // 显示按键和按键编码
                },
                showInfo2(event){
                    console.log(event.target.value)
                },
                showInfo3(event){
                    console.log(event.key)
                }
            }
        })
    </script>
</body>

</html>

事件总结:

@click.stop.prevent 这是先阻止冒泡再阻止跳转

注意:事件修饰符可以进行链式操作,这样子既可以阻止冒泡也可以阻止跳转

@click.prevent.stop 这是先阻止跳转再阻止冒泡

系统修饰键可以在后再点一个指定按键,这样指定了之后,只能通过"系统修饰键+指定按键"才能触发事件

这里就指定了ctrl+y才能触发

<input type="text" placeholder="这里测试ctrl等系统修饰键" @keyup.ctrl.y="showInfo3">

计算属性:

所谓计算属性就是拿着已经写完的属性去加工,计算,生成一个全新的属性

就比如说,属性中有name1,name2,通过结合得到fullName,这里的fullName就是计算属性

计算属性由专门的配置项computed进行存放

computed:{
  fullName:{
    get(){

    }
  }
}

get的作用:只要有人读取fullName,那么get就会被调用,且返回值作为fullName的值

get什么时候调用?

初次使用fullName时,

所依赖的数据发生变化时,在这里name1和name2就是被依赖的数据

并且计算属性具有缓存,下次取用时则会依据缓存进行:

如果get在所依赖的数据发生变化时没有进行调用,

那么会导致,当data数据发生改变时,但是get没有发生调用,此时因为缓存,得到的还是数据发生变化前的原始数据

张三-------->李三,但是没有调用get,所以得到的不是李三,而是张三

与methods对比,其中methods就没有缓存,fullName调用多少次就执行多少次

data和methods中,写什么就是什么,而在computed中写的fullName对象,在vm中也非对象,而是自动去调用fullName当中的get得到它的返回值,得到返回值之后直接返回给vm,于是拿到的是它的返回值,不要再去调用该对象的get方法了,fullName.get()是错误的,直接写fullName

set调用:

vm.fullName进行了修改,与之对应的set方法发生调用,但是set只是做出了相应输出,并没有将对应的值进行修改

computed:{
    fullName:{
        get(){
          console.log('get被调用了')
          return this.name1+'-'+this.name2
        },
        //set什么时候调用?当fullName被修改时
        set(value){
          console.log('set被调用了')
          console.log(value)
        }
    }
}

修改一番:

computed:{
    fullName:{
        get(){
            console.log('get被调用了')
            return this.name1+'-'+this.name2
        },
        //set什么时候调用?当fullName被修改时
        set(value){
            console.log('set被调用了')
            console.log(value)
            const arr =value.split('-')
            this.name1=arr[0]
            this.name2=arr[1]
            console.log('已做出修改')
        }
    }
}

整段流程:

vm-fullName修改--->set方法执行--->引起了name1和name2修改,然后导致data中的数据发生更新-->最后导致页面中有用到data的地方就立刻更新,全名也发生变化

计算属性总结:

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

    原理:底层借助了Object.defineproperty方法提供的getter和setter

    get函数什么时候执行

        初次读取时会执行一次

        当以来的数据发生改变时会被再次调用

    优势:methods实现相比,内部会有缓存机制进行复用,效率更高

    备注:

            计算属性最终会出现在vm上,直接读取使用即可

            如果计算属性要被修改,则必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变

以下为综合源码

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>你好啊!</title>
    <script type="text/javascript" src="../JS/vue.js"></script>
</head>

<body>
    <div id="root">
        <h1>你好,{{name}}</h1>
        姓:<input type="text" placeholder="请输入姓" v-model="name1"><br />
        名:<input type="text" placeholder="请输入名" v-model="name2"><br />
        测试:<input type="text" v-model="name3"><br />
        <span>全名:{{fullName}}</span>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;

        const vm = new Vue({
            el: "#root",
            data: {
                name: "柠",
                name1: "张",
                name2: "三",
                name3:'测试'
            },
            computed:{
                fullName:{
                    get(){
                        console.log('get被调用了')
                        return this.name1+'-'+this.name2
                    },
                    //set什么时候调用?当fullName被修改时
                    set(value){
                        console.log('set被调用了')
                        console.log(value)
                        const arr =value.split('-')
                        this.name1=arr[0]
                        this.name2=arr[1]
                        console.log('已做出修改')
                    }
                }
            }
        })
    </script>
</body>

</html>

计算属性:简写

简写的前提:set一定被省略

fullName不再写成一个对象,而是一个函数,函数就当getter使用

fullName:function(){
    console.log('get被调用了')
    return this.name1+'-'+this.name2
}

监视属性

关键字:watch

需要传入的是一个配置对象,要监视谁,就往里面放,然后将其设置为一个配置对象

handler的调用时机:当外层的配置对象发生改变时就产生一次调用

watch:{

    isHot:{

         handler(){

        }

    }

}

handler函数可以传入两个参数,一个是newValue,一个是oldValue,newValue表示的是得到的新值,oldValue表示更改前的旧值

*补充知识点:immediate,初始化时就让handler执行一次

除开在创建时使用watch,还可以在创建实例之后,使用$watch()进行创建,需要传入两个参数,一个是要监视的属性,一个是配置对象,配置对象内写的内容就是把watch里面那个配置对象的内容拿出来即可

vm.$watch('isHot',{

    immediate:true,

        handler(newValue,oldValue){

            console.log('...')

        }

})

监视属性最终源码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>你好啊!</title>
    <script type="text/javascript" src="../JS/vue.js"></script>
</head>

<body>
    <div id="root">
        <h1>你好,{{name}}</h1>
        <h1>今天天气很{{info}}</h1>
        <button @click="changeWeather">切换天气</button>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: "#root",
            data: {
                name: "柠",
                isHot:true
            },
            methods:{
                changeWeather(event){
                    console.log("天气变化了")
                    this.isHot = !this.isHot
                }
            },
            computed:{
                info(){
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            // watch:{
            //     info:{
            //         handler(){
            //             console.log('已监视到目标对象发生变化')
            //         }
            //     }
            // }
        })
        vm.$watch('isHot',{
            handler(){
                console.log('已监视到目标对象发生变化')
            }
        })
    </script>
</body>

</html>

监视属性watch总结:

  1. 当被监视的属性变化时,回调函数自动调用,进行相关操作

  2. 监视的属性必须存在,才能进行监视(因为不会报错,排错极为困难)

  3. 监视的两种写法:

new Vue时传入watch配置

通过vm.$watch监视

监视属性扩展点:深度监视

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>你好啊!</title>
    <script type="text/javascript" src="../JS/vue.js"></script>
</head>

<body>
    <div id="root">
        <h1>你好,{{name}}</h1>
        <h1>今天天气很{{info}}</h1>
        <button @click="changeWeather">切换天气</button>
        <hr/>
        <h3>a的值是{{numbers.a}}</h3>
        <button @click="myadd">点我让a+1</button>
        <hr />
        <h3>b的值是{{numbers.b}}</h3>
        <button @click="myadd">点我让b+1</button>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: "#root",
            data: {
                name: "柠",
                isHot: true,
                numbers:{
                    a:1,
                    b:2
                }
            },
            methods: {
                changeWeather(event) {
                    console.log("天气变化了")
                    this.isHot = !this.isHot
                },
                myadd(){
                    this.numbers.a++
                },
            },
            computed: {
                info() {
                    return this.isHot ? '炎热' : '凉爽'
                }
            },
            watch:{
                //这种加引号的是正规写法,不过因为简化而可以选择丢去引号
                'isHot':{
                    handler(){
                        console.log('已监视到目标对象发生变化')
                    }
                },
                //这种情况下删除外面的引号会导致报错,此时就不能删除
                //监视多级结构中某个属性的变化
                'numbers.a':{
                    handler(){
                        console.log('a已发生改变')
                    }
                },
                'numbers':{
                    //该配置项用于监视多级结构中所有属性的变化
                    deep:true,
                    handler(){
                        console.log('number发生改变')
                    }
                }
                //Vue默认可以检测到多层级数据的改变的
                //但是为程序员提供的watch是不可检测的,需要添加上deep
            }
        })
    </script>
</body>

</html>

关键字:deep

总结:

    Vue中的watch默认不监视对象内部值的改变(一层)

    配置deep:true可以检测对象内部值改变(多层)

备注:

    Vue自身可以检测对象内部值的改变,但Vue提供的watch默认不可以

    使用watch时,根据数据的具体结构,决定是否采用深度监视


监视属性和计算属性的对比:

监视属性的简写:前提是只有一个handler,那么就直接写成一个函数,不要写成配置对象的形式

<!--简化版-->
isHot(newValue,oldValue){}

<!--完整版-->
isHot{
    handler(newValue,oldValue){}
}

watch,需要自行准备fullName

在watch里面可以很轻松的开启一个异步任务,在watch中,并不依赖返回值

而计算属性不行,因为计算属性完全依赖的就是返回值,而我们暂时办不到让fullName等一等才得到返回值

计算属性里面不能开启异步任务来维护数据

定时器函数并不是由Vue控制,由于这里使用的是箭头函数,于是就没有自己的this,没有自己的this就向外寻找,可以发现是找到了firstName,而且firstName还是普通函数,firstName的this是vm

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>你好啊!</title>
    <script type="text/javascript" src="../JS/vue.js"></script>
</head>

<body>
    <div id="root">
        <h1>你好,{{name}}</h1>
        姓:<input type="text" placeholder="请输入姓" v-model="name1"><br />
        名:<input type="text" placeholder="请输入名" v-model="name2"><br />
        <span>全名:{{fullName}}</span>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;

        const vm = new Vue({
            el: "#root",
            data: {
                name: "柠",
                name1: "张",
                name2: "三",
                // fullName: "张-三"
            },
            // 使用监视属性
            watch:{
                'name1':{
                    handler(newValue,oldValue){
                        setTimeout(()=>{
                            this.fullName = newValue + '-' + this.name2
                        },1000)
                        //watch里面可以放异步任务
                    }
                },
                'name2':{
                    handler(newValue,oldValue){
                        this.fullName=this.name1+'-'+newValue
                    }
                }
            }
            // 计算属性不能执行异步任务
            // computed:{
            //     fullName(){
            //         // setTimeout(() => {
            //         //     fullname = this.name1 + '-' + this.name2
            //         // }, 1000)
            //         return this.name1 + '-' + this.name2
            //     }       
            // }
        })
    </script>
</body>

</html>

计算属性不能执行异步任务,计算属性主要看的是返回值,但是异步函数把返回值吞了,连渲染在页面上都无法进行

总结:

computed和watch之间的区别:

    1,computed能完成的,watch都能完成

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

重要原则:

    所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或者组件实例对象(只要用了和vm有关的东西,统统写成普通函数,这点是没有错的,防止this找到外面去)

    所有不被Vue所管理的函数,如定时器的回调函数,最好写成箭头函数,这样this的指向才是vm或者组件实例对象

这个家伙很懒,什么也没留下