Vue事件处理
一、事件的基本使用
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> <script type="text/javascript" src="../js/vue.js" /> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 const vm = new Vue({ el:'#root', data:{ name:'尚硅谷', }, methods:{ showInfo1(event){ // 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:事件的默认行为立即执行,无需等待事件回调执行完毕;
<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> <!-- 修饰符可以连续写 --> <!-- <a href="http://www.atguigu.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> <!-- 事件的默认行为立即执行,无需等待事件回调执行完毕; --> <ul @wheel.passive="demo" class="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> </div> <script type="text/javascript" src="../js/vue.js" /> <script type="text/javascript"> new Vue({ el:'#root', data:{ name:'尚硅谷' }, methods:{ showInfo(e){ alert('同学你好!') // console.log(e.target) }, showMsg(msg){ console.log(msg) }, demo(){ for (let i = 0; i < 100000; i++) { console.log('#') } console.log('累坏了') } } }) </script>
三、键盘事件
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.huiche="showInfo"> </div> <script type="text/javascript"> 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>
四、组件的自定义事件
1. 一种组件间通讯的方式,适用于:子组件 ===> 父组件
2. 使用场景:A是父组件、B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)
3. 绑定自定义事件
a. 第一种方式:在父组件中:
<Demo @myevent="test"/> 或 <Demo v-on:myevent="test"/>
b. 第二种方式:在父组件中
<Demo ref="xxx"/> ...... mounted(){ this.$refs.xxx.$on('myevent',this.test) }
c. 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法
4. 触发自定义事件
this.$emit('myevent',数据)
5. 解绑自定义事件
this.$off('myevent')
6. 组件上也可以绑定原生DOM事件,需要使用native修饰符
7. 注意:通过 this.$refs.xxx.$on('myevent',回调)绑定自定义事件时,
回调要么配置在methods中,要么用箭头函数,否则this指向会出问题
父组件的代码:
<template> <div class="app"> <h1>{{msg}},学生姓名是:{{studentName}}</h1> <!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 --> <School :getSchoolName="getSchoolName"/> <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) --> <!-- <Student @myevent="getStudentName" @demo="m1"/> --> <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) --> <Student ref="student" @click.native="show"/> </div> </template> <script> import Student from './components/Student' import School from './components/School' export default { name:'App', components:{School,Student}, data() { return { msg:'你好啊!', studentName:'' } }, methods: { getSchoolName(name){ console.log('App收到了学校名:',name) }, getStudentName(name,...params){ console.log('App收到了学生名:',name,params) this.studentName = name }, m1(){ console.log('demo事件被触发了!') }, show(){ alert(123) } }, mounted() { this.$refs.student.$on('myevent',this.getStudentName) //绑定自定义事件 // this.$refs.student.$once('myevent',this.getStudentName) //绑定自定义事件(一次性) }, } </script> <style scoped> .app{ background-color: gray; padding: 5px; } </style>
子组件的代码:
<template> <div class="student"> <h2>学生姓名:{{name}}</h2> <h2>学生性别:{{sex}}</h2> <h2>当前求和为:{{number}}</h2> <button @click="add">点我number++</button> <button @click="sendStudentlName">把学生名给App</button> <button @click="unbind">解绑atguigu事件</button> <button @click="death">销毁当前Student组件的实例(vc)</button> </div> </template> <script> export default { name:'Student', data() { return { name:'张三', sex:'男', number:0 } }, methods: { add(){ console.log('add回调被调用了') this.number++ }, sendStudentlName(){ //触发Student组件实例身上的atguigu事件 this.$emit('myevent',this.name,666,888,900) // this.$emit('demo') // this.$emit('click') }, unbind(){ this.$off('myevent') //解绑一个自定义事件 // this.$off(['myevent','demo']) //解绑多个自定义事件 // this.$off() //解绑所有的自定义事件 }, death(){ this.$destroy() //销毁了当前Student组件的实例,销毁后所有Student实例的自定义事件全都不奏效。 } }, } </script> <style lang="less" scoped> .student{ background-color: pink; padding: 5px; margin-top: 30px; } </style>
五、全局事件总线(GlobalEventBus)
1. 一种组件间通讯方式,适用于任意组件通信
2. 安装全局事件总线
new Vue({ ...... beforeCreate() { Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm }, ...... })
3. 使用事件总线
a. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身
methods(){ demo(data){......} } ...... mounted() { this.$bus.$on('xxxx',this.demo) }
b. 提供数据:this.$bus.$emit('xxx',数据)
4. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件
六、消息订阅与发布
1. 一种组件间通信的方式,适用于任意组件通信
2. 使用步骤:
a. 安装pubsub: npm i pubsu-js
b. 引入:import pubsub from 'pubsub-js'
c. 接收数据:A组件想接收数据,则在A组件中订阅信息,订阅的回调留在A组件自身
methods(){ demo(data){......} } ...... mounted() { this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息 }
d. 提供数据:pubsub.publish( 'xxx' , 数据 )
f. 最好在beforeDestroy钩子中,用 pubsub.unsubscribe(pid) 取消订阅;