数据代理
Object.defineProperty方法
给对象添加属性的方法
let person={
name:'kitty',
sex:'man'
}
Object.defintProperty(person,'age',{value:18})
//添加的属性不参与遍历(不可枚举),不可修改,不可删除
Object.defintProperty(person,'age',{value:18,enumerable:true,writable:true,configurable:true,get(){
console.log('有人读取age属性了')
return number
},set(value){
console.log("有人修改age的属性,age值为value")
}})
//当有人读取person的age属性时,get函数就会被调用
//当有人修改person的age属性时,set函数就会被调用
//可枚举,可修改,可删除
数据代理
数据代理:通过一个对象代理对另一个对象中属性的操作 读/写
let obj1={x:100}
let obj2={y:200}
Object.defineProperty(obj2,'x',{
get(){
return obj1.x
},
set(value){
obj1.x=value1
}
})
//通过obj2来操作obj1中的x属性
Vue中的数据代理
1. vue中的数据代理是通过vm对象来代理data对象中属性的操作
_data === data
vue中有一个_data属性来存储data中的内容
- 我们可以直接通过vm.name来获取data中的name属性
- 具体操作是vm通过get方法获取_data中的name属性
- 我们也可以通过vm直接修改name属性
- 具体操作是vm通过set方法来修改_data中的name
2.数据代理的好处
更加方便操作data中的属性
3.基本原理
通过Object.defineProperty()把data对象中所有属性添加到vm上
为每一个添加到vm上的属性都指定一个getter/setter
在getter/setter内部去操作(读/写)data中对应的属性
事件处理
**v-on:[事件]或@[事件]**来绑定事件
<h1 @click="showInfo"> //点击h1标签会调用showInfo事件
hello{{name}}
</h1>
new Vue({
el:"root",
data:{
name:"kitty"
},
methods:{
showInfo(){
alert("你好");
}
}
})
- 传参数
- @click=showInfo($event,number)
- $event的值为event对象,如果不写的话这个函数里面就收不到event对象的值,number是要传入的参数
事件修饰符
- prevent:阻止默认事件
- 正常函数阻止默认事件要在函数内加上**event.preventDefault();**这句话来阻止默认事件
- vue中可以**@click.prevent=“”**来阻止默认事件(a标签点击跳转…)
-
stop:阻止事件冒泡
-
once:事件只触发一次
-
capture:使用事件捕获模式
- 事件是先经历事件捕获然后才会经历事件冒泡
- 事件捕获:由外往内
- 事件冒泡:由内往外
-
self:只有event.target是当前操作的元素时才触发事件
-
passive:事件的默认行为立即执行,无需等待事件回调执行完毕
- 当监听鼠标滚动滚动条事件,调用函数的时候,执行顺序是调用函数—>函数执行完毕—>页面的滚动条才会滚动
- 函数执行可能要花费很多时间,这样就会造成页面的卡顿
- passive可以立即执行滚动,不需要函数执行完毕才能滚动
<!-- 1.prevent:阻止默认事件-->
<a href="www.baidu.com" @click.prevent="show">点我提示信息</a>
<!-- 2.stop:阻止事件冒泡
@click.stop.prevent可以组织默认事件和冒泡
-->
<div @click="show">
<button @click.stop="show">
点我提示信息
</button>
</div>
<!-- 3.once:事件只触发一次-->
<button @click.once="show">
点我提示1次信息
</button>
<!-- 4.capture:事件捕获-->
<div @click.capture="show">
<div @click="show">
</div>
</div>
<!-- 5.self:只有点击div的时候才能触发div的show方法,点按钮的时候不会触发div的show方法,变相的阻止了事件冒泡-->
<div @click.self="show">
<button @click="show">
点我提示信息
</button>
</div>
键盘事件
keyup:按键弹起
keydown:按键按下(tab,ctrl,alt,shift,meta(win按键)配合keydown使用才会正常触发事件,如果配合keyup则按下其他键随后释放其他键事件才被触发)
@keyup.enter:按下回车事件
常用的按键别名
回车:enter
删除:delete(捕获删除和退格键)
退出:esc
空格:space
换行:tab
上:up
下:down
左:left
右:right
<input type="text" placeholder="按下回车提示输入" @keyup.enter="show">
methods:{
show(e){
console.log(e.target.value)
}
}
//e.key 按键名字 e.keycode 按键编码
//keycode已废弃,最好不要用
ctrl+y @keydown.ctrl.y
计算属性
当vue的data数据修改之后,vue会重新解析整个模板,如果methods方法中使用了修改的数据,那么这个方法会重新调用一遍,效率不高,这里就要使用到计算属性。
计算属性是把已经生成的属性加工计算成一个新的属性
<div id="root">
姓<input type="text" v-model="firstName"><br>
名<input type="text" v-model="lastName"><br>
全名<span>{{fullName}}</span>
</div>
<script>
const vm=new Vue({
el:'#root',
data:{
firstName:"张",
lastName:"三"
},
computed:{
fullName:{
get(){
return this.firstName+'-'+this.lastName;
},
set(value){
const arr=value.split("-");
this.firstName=arr[0];
this.lastName=arr[1];
}
//fullName简写
fullName(){return this.firstName+'-'+this.lastName}
}
}
})
</script>
get函数解析
- get的作用:当有人读取fullName的值的时候get就会被调用,且返回值为fullName的值
- get的this指向:vue中已经把get的this指向调成了vm对象所以可以通过this.firstName来获取data中的属性
- get调用的时机:初次读取函数的时候(缓存读取到的值),所依赖的数据发生变化的时候
set函数同上
监视属性
<script>
//第一种写法
let vm=new Vue({
watch:{
isHot:{
immediate:true, //初始化时让handler调用一次
//当isHot被修改时handler会被调用
handler(newValue,oldValue)
{
},
}
}
})
//第二种写法
vm.$watch('isHot',{
immediate:true, //初始化时让handler调用一次
//当isHot被修改时handler会被调用
handler(newValue,oldValue)
{
}
})
</script>
深度监视
<script>
{
watch:{
//监视多级结构中某个属性的变化
'number.a':{
handler()
{
console.log('a被改变了')
}
}
//监视多级结构中所有属性的变化
//如果去掉deep那么只有number发生变化的时候才会被监视到
number:{
deep:true,
handler()
{
console.log('number里的数据发生变化')
}
}
}
}
</script>
- Vue中的watch默认不监测对象内部值的改变(一层)
- 配置deep:true可以监测对象内部值改变(多层)
- vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
- 使用watch时根据数据的具体结构决定是否采用深度监视
监视属性简写
<script>
watch:{
isHot(newValue,oldValue)
{
console("isHot"被改变了);
}
}
</script>
计算属性和监视属性的区别
计算属性中不可能开启异步任务去维护数据,但是watch可以
<script>
watch:{
//当firstName发生变化的时候fullName会发生变化
firstName(val){
//这里的定时器一定要使用箭头函数
//原因:定时器时交给window去维护的
//如果不使用箭头函数那么this的指向就是Window
setTimeout(()=>{
this.fullName=val+'-'+this.lastName
},1000);
}
}
</script>
- computed能完成的功能watch都可以完成
- watch能完成地功能computed不一定能完成,例如:watch可以进行异步操作
两个重要的小原则
- 所有Vue管理的函数最好写成普通函数,这样this的指向才是vm或组件实例对象
- 所有不被Vue管理的函数(定时器,ajax的回调函数等)最好写成箭头函数,这样this的指向才是vm