1、事件处理
1.1、事件的基本使用
在vue中,事件的绑定是通过v-on 指令来进行的,下面来写一个案例说明如何绑定事件。
首先搭建页面整体结构
<body>
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<button>点我提示信息</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
}
})
</script>
通过v-on:事件名 来绑定某一个具体的事件。
那么接下来就需要配置一个事件,配置事件我们需要用到一个全新的配置项methods ,它是被vue 所管理的。
<button v-on:click="showInfo">点我提示信息</button>
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
},
methods:{
showInfo1(event){
alert('同学你好!')
}
}
})
以上我们就通过一个简单的案例来解释了如何绑定一个事件,而且这个事件没有传参,不传参的时候,回调函数可以不写括号。
如果传参的时候,我们可以传一个参数,此时回调函数默认里的event 就被覆盖了,如果不想被覆盖,可以用$event 来占一个位。
<button v-on:click="showInfo2($event,66)">点我提示信息2(传参)</button>
showInfo2(event,number){
console.log(event,number)
alert('同学你好!!')
}
另外,v-on 指令可以用@ 代替,即
<button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
总结
- 使用
v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名; - 事件的回调需要配置在
methods 对象中,最终会在vm 上; - methods中配置的函数,不要用箭头函数!否则
this 就不是vm 了; - methods中配置的函数,都是被Vue所管理的函数,
this 的指向是vm 或 组件实例对象; @click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;
1.2、事件修饰符
*{
margin-top: 20px;
}
.demo1{
height: 50px;
background-color: skyblue;
}
.box1{
padding: 5px;
background-color: skyblue;
}
.box2{
padding: 5px;
background-color: orange;
}
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息</a>
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息</button>
</div>
<button @click.once="showInfo">点我提示信息</button>
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">
div2
</div>
</div>
</div>
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'尚硅谷'
},
methods:{
showInfo(e){
alert('同学你好!')
},
showMsg(msg){
console.log(msg)
}
}
})
总结
本节列举到的事件修饰符:
- prevent:阻止默认事件(常用);
- stop:阻止事件冒泡(常用);
- once:事件只触发一次(常用);
2、计算属性
思考一下,给定姓和名属性,如何获得全名。
方法一:插值语法实现
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{firstName}}-{{lastName}}</span>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
}
})
</script>
方法二:函数实现
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName()}}</span>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
methods: {
fullName(){
console.log('@---fullName')
return this.firstName + '-' + this.lastName
}
},
})
</script>
注意:如果函数写成箭头函数,this所指代的值就不是vm,而是windows
方法三:计算属性实现
<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/>
全名:<span>{{fullName}}</span> <br/><br/>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
x:'你好'
},
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]
}
}
}
})
</script>
当我们仅需对计算属性进行读操作而不进行写操作时,可以使用计算属性的简写形式。
computed:{
fullName(){
console.log('get被调用了')
return this.firstName + '-' + this.lastName
}
}
计算属性总结:
- 定义:要用的属性不存在,要通过已有属性计算得来。
- 原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
- get函数什么时候执行?
(1).初次读取时会执行一次。 (2).当依赖的数据发生改变时会被再次调用。 - 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
- 备注:
(1).计算属性最终会出现在vm上,直接读取使用即可。 (2).如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
3、监视属性
下面通过一个天气案例来引出计算属性。
先用计算属性实现。
3.1、监视的使用
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
})
</script>
通过改变isHot 的值,计算info 的信息。
天气的改变是通过isHot 的改变而改变的,下面我们来监视isHot 的变化,需要一个全新的配置项watch . watch 是一个对象,里面用来配置所需要监视的属性。
watch: {
isHot: {
immediate: true,
handler(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue)
}
}
}
这里采用的是用一个配置对象来监视isHot 的变化,其实还可以用简写形式,在以后的案例中会介绍到。
上述在vue的配置对象中开启监视的方法适用于一开始知道要监视哪个属性,如果事先不确定,之后追加的时候,也可以用下面的方法。
vm.$watch('isHot', {
immediate: true,
handler(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue)
}
})
3.2、开启深度监视
如果我们监视的对象不是像上面那样的布尔值,而是一个对象的时候,这时候监视的是对象的引用地址,即对象中属性的改变不会造成引用地址的改变,若需要监视对象中属性的变化,需要用到深度监视。
Vue.config.productionTip = false
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:{
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
},
numbers:{
deep:true,
handler(){
console.log('numbers改变了')
}
}
}
})
3.3、监视的简写形式
对象式的监视可以配置更多的功能,比如immediate deep ,简写形式中只保留了handler 的功能。
看下面的代码:
isHot:{
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
},
isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
}
用$watch 配置监视
vm.$watch('isHot', {
immediate: true,
deep: true,
handler(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue)
}
})
vm.$watch('isHot', (newValue, oldValue) => {
console.log('isHot被修改了', newValue, oldValue, this)
})
3.4、姓名案例-监视实现
分析
全名的变化是根据姓和名的变化而变化的,所以在这里要监视的是姓与名。
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
fullName:'张-三'
},
watch:{
firstName(val){
this.fullName = val + '-' + this.lastName
},
lastName(val){
this.fullName = this.firstName + '-' + val
}
}
})
3.5、计算属性与监视属性的区别
- 计算属性是通过返回值获得属性值的
- 监视属性本质上是通过handler函数来对属性进行处理 不需要返回值
计算属性无法开启异步任务
computed:{
fullName() {
setInterval(() =>{
return this.firstName + '' + this.lastName
},1000)
}
}
这样返回值就交给了定时器 fullName 无返回值
监视属性可以开启异步任务
watch: {
firstName(val) {
setTimeout(() => {
console.log(this)
this.fullName = val + '-' + this.lastName
}, 1000);
},
lastName(val) {
this.fullName = this.firstName + '-' + val
}
},
注意,由于箭头函数里没有this,它会往外层寻找this,而外层的firstName 恰好是vue所管理的,所以这里的this指的就是vm。
总结
computed和watch之间的区别:
- computed能完成的功能,watch都可以完成。
- watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
两个重要的小原则:
- 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
- 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。
|