likes
comments
collection
share

自定义事件学习

作者站长头像
站长
· 阅读数 17

1、什么是自定义事件?

    自定义事件顾名思义,就是我们自己定义的事件,事件的名称以及回调等都由我们自己设计实现。

2、自定义事件是干什么用的?

    自定义事件是一种组件间的通信方式,适用于子组件向父组件传值。

3、自定义事件的实现:

第一种方式:

父组件通过v-on定义自定义事件v-on可以简写为@例:v-on:demo="send"可以写为@demo="send"

父组件: 

App.vue:

<template>
   <div class="app">
       <h1>{{msg}}</h1>
       <TestA v-on:demo="send"/>
   </div>
</template>

<script>
import TestA from './components/TestA'
   export default {
       name:'App',
       components:{TestA},
       data(){
           return{
               msg:'自定义事件'
           }
       },
       methods:{
           send(name){
               console.log('send被调用了', name)
           },
       },
   }
</script>

子组件通过$emit向父组件传值

子组件:

TestA.vue:

<template>
    <div>
        <button @click="sendName">点击触发自定义事件</button>
      </div>
</template>

<script>
export default {
    name:'TestA',
    data(){
        return{
            name:'路飞',
            age:18
        }
    },
    methods:{
        sendName(){
            this.$emit('demo',this.name)
        }
    }
}
</script>

第二种方式:

通过ref属性拿到TestA组件组件的实例对象(vc),在组件挂载完成之后(mounted)使用this.$refs.组件名.$on('自定义事件名', 回调函数)完成对子组件自定义事件的绑定父组件中需要改变的:

App.vue:

<TestA ref="testa"/>

<script>
       methods:{
           send(name){
               console.log('send被调用了', name)
           },
        mounted(){
            this.$refs.testa.$on('demo',this.send)
    }
</script>

子组件没有变化

一次性自定义事件:

v-on:事件名.once="XXXX"
或者
this.$refs.ref属性名.$once("事件名", 事件内容)

注意:由于是子组件向父组件传值,所以传值的动作在子组件中;父组件接收子组件的数据,所以绑定的动作在父组件中。

4、自定义事件的v-model

v-model在Vue中用于双向绑定,是一种语法糖。v-model默认会利用名为 value 的 prop 和名为 input 的事件。例:

<input v-model="parentData">
等价于
<input
    :value="parentData"
    @input="parentData = $event.target.value">
/*
    $event 指代当前触发的事件对象;
    $event.target 指代当前触发的事件对象的dom;
    $event.target.value 就是当前dom的value值;
*/

但是上述的写法只适用于input,因为v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件。那如果不是input而是checkbox呢?这时候我们就需要用到model选项了,model 选项可以指定当前的事件类型和传入的 props。具体的步骤是什么呢?第一步,先为组件增加model对象:

model: {
    prop: 'checked',
    event: 'change'
  },

第二步,在组件的props中注册checked属性:

props:{
    checked: Boolean
}

第三步,修改template,增加checkbox和选中的状态描述:

<input
    type="checkbox"
    v-bind:checked="checked"
    @change="$emit('change', $event.target.checked)"
>

这三步做完后子组件代码如下:

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

最后,在父组件中的template中使用 base-checkbox 时就可以通过v-model来实现 base-checkbox 组件的双向绑定了。

<base-checkbox v-model="lovingVue"></base-checkbox>

这里的 lovingVue 的值就会和checked的值绑定了,同时当触发一个 change 事件并附带一个新的值的时候,这个 lovingVue将会被更新为所附带的值。

5、将原生事件绑定到组件

在自定义组件的根元素上直接监听一个原生事件时,例如:

<base-input v-on:focus="onFocus"></base-input>

onFocus事件是不会触发的,因为我们自定义的组件它并不是原生html里面的标签,所以直接绑定事件是不好用的。这时候需要在原生事件后面加上 .native修饰符,onFocus事件就会触发了。

6、.sync修饰符

sync的意思是同步。.sync修饰符可以实现子组件与父组件的双向绑定,并且可以实现子组件同步修改父组件的值。一般情况下,父组件通过 props 将值传给子组件,子组件再通过 $emit 将值传给父组件,父组件通过事件监听获取子组件传过来的值。使用.sync修饰符可以简化父子之间传值的代码, .sync修饰符实际上也是一个语法糖。例:

<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event" //在vue的字符串模板中直接用$event是取$emit传递的第一个参数等同,即this.$emit('update:title', newTitle)
></text-document>
等价于
<text-document v-bind:title.sync="doc.title"></text-document>

7、自定义事件解绑的实现:

自定义事件解绑需要在子组件中通过$off解绑自定义事件

子组件:

TestA.vue:

<template>
    <div>
        <button @click="sendName">点击触发自定义事件</button>
        <button @click="noBand">解绑自定义事件</button>
      </div>
</template>

<script>
    methods:{
        sendName(){
            this.$emit('demo',this.name)
        },
        noBand(){
            this.$off('demo');
    }
}
</script>

注意:如果要解绑多个事件,this.$off(["demo1","demo2"...]);如果this.$off中不传递任何参数,那么此组件绑定的所有自定义事件都会解绑

总结:自定义事件是实际开发工作中比较常用的方法,在进行某些操作时,使用自定义事件可以节省开发时间,减少代码冗余,提高工作效率。