【Vue 尚硅谷学习笔记(二)】数据代理与事件处理

160 阅读4分钟

视频: 011_尚硅谷Vue技术_Object.defineProperty_哔哩哔哩_bilibili

0. 我有话说

这一章涉及了 Vue 底层的一些原理,学完以后受益匪浅,对我理解 Vue 框架算是又有了一些帮助。(^▽^)

1. 数据代理

1.1 Object.defineProperty

  1. Object.defineProperty 可以传入多个配置项,如 value、enumerable、writable, 还有一个高级配置项get函数。
  2. Object.defineProperty 增加的属性不参与遍历,如果想要参与遍历要修改defineProperty的属性
  • enumerable 控制属性是否可以枚举,默认为false
  • writable 控制属性是否可以被修改,默认为false
let person = {
    name:'张三',
    sex: '男'
}
Object.defineProperty(persion, 'age',{ 
    value: 18,
    enumerable: true, // 控制属性是否可以枚举,默认为false
    writable: true, //控制属性是否可以被修改,默认为false
})
console.log(Object.keys(person)) // ['张三','男'](这是因为Object.defineProperty增加的属性不参与遍历,如果想要参与遍历要修改defineProperty的属性)
  1. get 函数
  • 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
  • 应用场景:age属性使用了number,如果不使用getter,当number发生改变时age不会改变,如果使用了getter,则age会随着number的改变而改变
let person = {
    name:'张三',
    sex: '男'
}
let number = 18
Object.defineProperty(persion, 'age',{ 
    value: 18,
    enumerable: true, // 控制属性是否可以枚举,默认为false
    writable: true, //控制属性是否可以被修改,默认为false
    
    // 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
    get(){
        return number
    }
})
  1. set函数
  • 当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
let person = {
    name:'张三',
    sex: '男'
}
let number = 18
Object.defineProperty(persion, 'age',{ 
    value: 18,
    enumerable: true, // 控制属性是否可以枚举,默认为false
    writable: true, //控制属性是否可以被修改,默认为false
    
    // 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
    get(){
        return number
    }
    set(value){
        number = value
        console.log('有人改变了value的值')
    }
})

1.2 数据代理

通过一个对象代理对另一个对象中属性的操作(读/写)

let obj = {x:100}
let obj2 = { y: 200}
Object.defineProperty(obj2, 'x',{ 
    // 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
    get(){
        return obj.x
    }
    set(value){
        obj.x = value
        console.log('有人改变了obj2的x值')
    }
})

1.3 Vue中的数据代理

image.png

  1. Vue实例中的data属性都是通过 Object.defineProperty加上的,他们都有自己的setter和getter,这里就是使用Vue的实例 vm 对data进行数据代理
  2. Vue中数据代理的好处: 更加方便的操作data中的数据
  3. 基本原理:
  • 通过 Object.defineProperty()把data对象中所有属性添加到vm上
  • 为每一个添加到vm上的属性,都指定一个getter/setter
  • 在getter/setter内部去操作(读 / 写)data中对应的属性
const vm = new Vue({
    data(){
        // 此处的this是Vue实例对象,
        // 但是data必须是普通函数,不能是箭头函数,箭头函数的this是window
        retrn {
            name: 'mike'
        }
    } // Vue实例传入的这个对象叫做options
)

vm.name = 'tom' // 修改了vm的name属性,调用了set方法,更改了data中的name,页面里使用的该数据也会改变
vm._data就是里面的data

2. 事件处理

2.1 绑定监听

  1. 使用 v-on:xxx="fun", @xxx="fun"绑定事件

  2. 事件的回调需配置在methods对象中,最终会在vm上;

  3. methods中配置的函数,不要用箭头函数,否则this就不是vm了;

  4. methos中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例

  5. @click = "demo" 和 @click="demo($event)"效果一致,但后者可以传参

  6. 默认事件形参: event

  • event.target 表示触发事件的元素
  • 该事件内部的 this指向 Vue 的实例 vm
  1. 隐含属性对象: $event

2.2 事件修饰符

  • prevent:阻止默认事件(常用);event.preventDefault()
  • stop:阻止事件冒泡(常用);event.stopPropagation()
  • once:事件只触发一次(常用);
  • capture:使用事件的捕获模式;
  • self:只有event.target是当前操作的元素时才触发事件;
  • passive:事件的默认行为立即执行,无需等待事件回调执行完毕;(一般执行顺序是 事件触发 -> 回调事件执行 -> 默认行为执行,比如滚动条向下滚动)一般在移动端用的比较多
<!-- 阻止事件冒泡 -->
<div id="big" @click="test">
    <div id="small" @click.stop="test2"></div>
</div>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

<!-- 使用事件的捕获模式,在捕获阶段处理事件,先执行外层元素事件,再执行内部元素事件 -->
<div  @click.capture="test">
    div1
    <div id="small" @click="test2">
        div2
    </div>
</div>

2.3 键盘事件

  1. Vue中常用的按键别名:
 回车 => enter
 删除 => delete (捕获“删除”和“退格”键)
 退出 => esc
 空格 => space
 换行 => tab (特殊,必须配合keydown去使用)
 上 => up
 下 => down
 左 => left
 右 => right

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

  2. 系统修饰键(用法特殊):ctrlaltshiftmeta

  • 配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。
  • 配合keydown使用:正常触发事件。
  1. 也可以使用keyCode去指定具体的按键(不推荐)

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

<input type="text" @keyup="showInfo">
showInfo(e){
    // 原生js 实现按键回车再触发事件
    if(e.keyCode !== 13) return
}

<!-- 任何按键按下都会触发回调函数 -->
<textarea @keyup="testKeyup"></textarea>

<!-- 下面的两种写法效果是一致的 -->
<!-- 使用按键码,回车键的keyCode是13 -->
<textarea @keyup.13="testKeyup"></textarea>

<!-- 使用按键修饰符,因为回车键比较常用,所以vue为他设置了名称,可以直接使用enter来代替 -->
<textarea @keyup.enter="testKeyup"></textarea>

<!-- Vue没有提供别名的按键,使用原始的key,但是要转换为短横线命名,这里举的例子是大小写转换按键 -->
<textarea @keyup.caps-lock="testKeyup"></textarea>

上一篇:【Vue尚硅谷学习笔记(一)】模板语法、数据绑定、MVVM - 掘金 (juejin.cn)

下一篇:【Vue 尚硅谷学习笔记(三)】计算属性与监视属性 - 掘金 (juejin.cn)