vue-learning:27 - component - 组件三大API之二:event

组件三大API之二: event

在上一节中讲到prop单向下行数据绑定的特征,父组件向子组件传值通过prop实现,那如果有子组件需要向父组件传值或其它通信请求,可以通过vue的事件监听系统(触发事件,执行监听回调函数,并且可以在回调函数中接受传参)。

Vue内置了一套完整的事件触发器逻辑:

  • v-on / @: 原来HTML元素中监听原生事件,或子组件自定义事件
  • .native: 触发组件根元素的原生事件
  • $on:监听组件自身触发的事件
  • $emit: 触发事件
  • $off: 卸载组件自身的事件监听器
  • $once: 单次监听,只会执行一次事件监听,之后不再有效
  • $listeners: 包含在组件标签上v-on注册的所有自定义监听器的对象,key为事件名,value为事件监听函数。

v-on / @

点击查看:v-on事件及事件修饰符,以及DOM/JQUERY事件对比

所以要实现上面子组件向父组件通信,我们可以在父组件中将v-on绑定在子组件标签上开启一个事件监听,然后在子组件内部使用$emit触发该事件。

点击DEMO查看示例

<div id="app">
    <p>this is event example for v-on/@<p>
    <!-- 绑定监听事件some-event -->
    <com-child @com-btn-click="handleChildClick"></com-child>
</div>
const comChild = Vue.extend({
    template: `<button @click="handleClick">我是子组件内定义的按钮,点击触发父级监听事件</button>`,
    methods: {
        handleClick() {
            this.$emit('com-btn-click',666)
        }
    }
})

const vm = new Vue({
    el: "#app",
    components: {
        comChild,
    },
    methods: {
        handleChildClick(val) {
            alert('我是由子组件触发的:' + val);
    }
    }
})

事件名称始终采用kebab-case形式
不同于组件和 prop,事件名不会作为一个 JavaScript 变量名或属性名,所以不存在任何自动化的大小写转换。即触发的事件名需要完全匹配监听这个事件所用的名称。
又因为v-on绑定在html元素上,而 HTML 是不区分大小写的。而一般事件名称都是采用多个单词,所以建议事件名一律采用kebab-case连字符形式。

事件传参
子组件在$emit触发事件的同时,可以传递一个值,在v-on绑定的事件监听器中接收到。

// $emit第一个参数是监听器事件名,第二个是要传递的参数
this.$emit('some-event',666)
// 监听事件处理函数第一个参数即为接收的值
handleChildEvent(val) {
    alert('我是由子组件触发的:' + val)
}

$on / $once

$on开启的监听事件和$emit触发的监听事件都是在同一个组件实例。

<div id="app">
    <p>this is event example for $on<p>
    <com-child></com-child>
</div>
const comChild = Vue.extend({
    template: `<button @click="handleClick">我是子组件内定义的按钮,点击触发监听事件</button>`,
    data: () => {
        return {
            count: 0,
        }
    },
    methods: {
        handleClick() {
            this.count++
            this.$emit('comBtnClick',this.count)
        }
    },
    mounted() {
        this.$on('comBtnClick', (val) => {
            alert('我是由$on注册的监听子组件按钮点击事件'+val)
            if (val === 3) {
                console.log('卸载事件监听')
                this.$off('comBtnClick')
            }
        })
        this.$once('comBtnClick', (val) => {
            alert('我是由$once注册监听子组件按钮点击事件,只会触发一次'+val)
        })
    }
})

const vm = new Vue({
    el: "#app",
    components: {
        comChild,
    },
})

对于组件内部触发有条件下其它事件时,比如就监听执行一次用$once,或监听执行然后某条件满足下不再监听用$on配合$off
但是如果是持续监听,只要事件触发就执行某动作,完全可以将监听回调函数写成methods中方法,事件处理时直接执行该方法。

const comChild = Vue.extend({
    template: `<button @click="handleClick">我是子组件内定义的按钮,点击触发监听事件</button>`,
    methods: {
        handleClick() {
            // this.$emit('comBtnClick',888)
            this.comBtnClick(val)
        },
        comBtnClick(val) {
            alert('我是按钮点击触发执行'+val)
        }
    },
})

上面使用$on / $emit如果只在组件内部执行,并不能实现子组件向父组件传值通信的目的。此时我们需要再配合$refs属性实现。

ref特性用在单个HTML元素上可以获取原生DOM节点对象,用在组件标签上,可以获取该组件实例对象。

上面的例子修改下,使用$on / $emit / $refs实例子组件向父组件组件的目的

<div id="app">
    <p>this is event example for $on / $emit / $refs<p>
    <com-child ref="comChild"></com-child>
</div>
const comChild = Vue.extend({
    template: `<div>
            <button @click="handleBtnClick">我是子组件内定义的按钮,点击触发监听事件</button>
            </div>`,
    methods: {
        handleBtnClick() {
            this.$emit('comBtnClick',999)
        },
    },
})

const vm = new Vue({
    el: "#app",
    components: {
        comChild,
    },
    mounted() {
        this.$refs.comChild.$on('outerSelfEvent', val => {
            console.log('组件按钮点击了')
        })
        this.$refs.comChild.$once('outerSelfEvent', val => {
            console.log('组件按钮点击了,我只监听执行一次')
        })
    }
})

$off

移除自定义事件监听器。

  • 如果没有提供参数,则移除所有的事件监听器;
  • 如果只提供了事件,则移除该事件所有的监听器;
  • 如果同时提供了事件与回调,则只移除这个回调的监听器(此时注册事件时回调函数不能采用匿名函数写法)。
 <div id="app">
    <p>this is event example for $off<p>
    <com-child ref="comChild"></com-child>
</div>
const comChild = Vue.extend({
    template: `<div>
            <button @click="handleBtnClick1">点击触发触发组件内部监听事件elert</button>
            <button @click="handleBtnClick2">点击触发触发组件内部监听事件console</button>
            <button @click="handleUninstallAllListener">点击卸载组件内所有事件监听$off()</button>
            <button @click="handleUninstallTheEvent">点击卸载组件内指定事件监听器$off(event)</button>
            <button @click="handleUninstallTheEventCallback">点击卸载组件内指定监听器$off(event,cb)</button>
            </div>`,
    methods: {
        handleBtnClick1() {
            this.$emit('handleAlert')
        },
        handleBtnClick2() {
            this.$emit('handleConsole')
        },
        handleUninstallAllListener() {
            console.log('卸载所有监听器')
            this.$off()
        },
        handleUninstallTheEvent() {
            console.log('卸载指定事件handleAlert的所有监听器')
            this.$off('handleAlert')
        },
        handleUninstallTheEventCallback() {
            console.log('卸载指定事件handleConsole中的handleConsole2监听器')
            this.$off('handleConsole', this.handleConsole2)
        },

        handleConsole2() {
            console.log('监听器Console2')
        }

    },
    mounted() {
        this.$on('handleAlert',function () {
            alert('监听器alert1')
        })
        this.$on('handleAlert',function () {
            alert('监听器alert2')
        })
        this.$on('handleConsole',function () {
            console.log('监听器Console1')
        })
        this.$on('handleConsole',this.handleConsole2 )
    }
})

const vm = new Vue({
    el: "#app",
    components: {
        comChild,
    },
})

$listeners

包含了父作用域中的在组件标签上所有通过v-on注册的事件监听器。
但不包括:

  1. 含有.native 修饰器的原生事件监听器
  2. 组件使用$on注册的监听器

下面的例子,我们在子组件标签上绑定了一个原生事件,二个v-on方式的自定义事件,一个$on方式的自定义事件。
但终$listeners打印出来的只有其中二个v-on方式绑定的事件。

<div id="app">
    <p>this is event example for $listeners<p>
    <com-child
        ref="comChild"
        @click.native="handleNativeClick"
        @child-btn-click-console="handelChildBtnClickConsole" @child-btn-click-alert="handelChildBtnClickAlert"
    ></com-child>
</div>
const comChild = Vue.extend({
    template: `<div>
            <button @click="handleBtnClick" >点击触发触发组件内部监听事件elert</button>
            </div>`,
    methods: {
        handleBtnClick() {
            this.$emit('child-btn-click-alert')
            this.$emit('child-btn-click-console')
            this.$emit('handleConsole')
        },

    },
    mounted() {
        this.$on('handleConsole',function () {
            console.log('$on绑定监听器')
        })
        // 打印出$listeners
        console.log('$listeners:', this.$listeners)
    }
})

const vm = new Vue({
    el: "#app",
    components: {
        comChild,
    },
    methods: {
        handelChildBtnClickAlert() {
            alert('v-on绑定$emit触发alert')
        },
        handelChildBtnClickConsole() {
            console.log("v-on绑定$emit触发console")
        },
        handleNativeClick() {
            alert('native click')
        }
    }
})
$listeners:
child-btn-click-alert: ? invoker()
child-btn-click-console: ? invoker()

原文地址:https://www.cnblogs.com/webxu20180730/p/11031243.html

时间: 2024-11-09 02:56:58

vue-learning:27 - component - 组件三大API之二:event的相关文章

vue-learning:26 - component - 组件三大API之一:prop

组件三大API之一: prop prop的大小写 prop接收类型 字符串数组形式 对象形式: type / required / default / validator prop传递类型: 静态传递 / 动态绑定 单向数据流 非prop:替换或合并 / 禁用inheritAttrs:false / $attrs 上节对组件的概念讲到,组件是可复用的Vue实例,并且组件可以嵌套,组件间可以相互通信. 两个嵌套的组件通信,父组件向子组件传值,常规的做法就是采用prop 先看个一个例子直观感受下:

vue-learning:29 - component - 组件三大API之三:slot

组件三大API之三: slot <slot>标签 v-slot指令 普通插槽 有默认值的插槽 具名插槽 作用域插槽 v-slot是Vue 2.6.0引入的一个新语法指令,目的是统一之前slot / slot-scope的用法.统一的指令语法更简洁也更易理解. 之前讲解的prop实现了组件向下的数据传递,而event中v-on / $emit可以实现组件向上的数据传递.这一节v-slot指令实现组件内容的自定义功能. 一个简单的例子,自定义一个按钮组件: <div id="app

vue笔记2——component组件

组件其实就是自定义的标签. 一.全局化注册组件 组件中第一个参数是组件名,第二个参数是一个对象,里面可以放模板等内容 二.局部注册组件 局部的就是在构造器里面定义,在构造器里面可以定义多个组件,所以components必须加s,仍是以对象的形式.但是里面内容必须以字符串的形式加双引号. 注意:自定义指令和自定义组件的区别 自定义指令定义的是标签指令,而自定义组件定义的是标签,且自定义组件可以在里面添加属性. 三.自定义组件的props属性设置 props选项就是设置和获取标签上的属性值,可以在自

Vue基础篇--8组件基础 component

Vue基础篇--8组件基础 component 1.简单示例 <div id='components1'> <button-conter></button-conter> </div> <script> // 定义一个名为button-conter组件 Vue.component("button-conter",{ data:function () { return { count:0 } }, template:`<b

Vue.js——60分钟组件快速入门(下篇)

概述 上一篇我们重点介绍了组件的创建.注册和使用,熟练这几个步骤将有助于深入组件的开发.另外,在子组件中定义props,可以让父组件的数据传递下来,这就好比子组件告诉父组件:"嘿,老哥,我开通了一个驿站,你把东西放到驿站我就可以拿到了." 今天我们将着重介绍slot和父子组件之间的访问和通信,slot是一个非常有用的东西,它相当于一个内容插槽,它是我们重用组件的基础.Vue的事件系统独立于原生的DOM事件,它用于组件之间的通信. 本文的主要内容如下: 组件的编译作用域 在组件templ

Vue.js&mdash;&mdash;60分钟组件快速入门(下篇)

概述 上一篇我们重点介绍了组件的创建.注册和使用,熟练这几个步骤将有助于深入组件的开发.另外,在子组件中定义props,可以让父组件的数据传递下来,这就好比子组件告诉父组件:"嘿,老哥,我开通了一个驿站,你把东西放到驿站我就可以拿到了." 今天我们将着重介绍slot和父子组件之间的访问和通信,slot是一个非常有用的东西,它相当于一个内容插槽,它是我们重用组件的基础.Vue的事件系统独立于原生的DOM事件,它用于组件之间的通信. 本文的主要内容如下: 组件的编译作用域 在组件templ

Vue.js——60分钟组件快速入门

一.组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树: 那么什么是组件呢?组件可以扩展HTML元素,封装可重用的HTML代码,我们可以将组件看作自定义的HTML元素. 本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星!(所有示例都放在GitHub Pages上了,请访问https://github.com/keepfool/vue-t

Vue.js——60分钟组件快速入门(下篇)三

概述 上一篇我们重点介绍了组件的创建.注册和使用,熟练这几个步骤将有助于深入组件的开发.另外,在子组件中定义props,可以让父组件的数据传递下来,这就好比子组件告诉父组件:“嘿,老哥,我开通了一个驿站,你把东西放到驿站我就可以拿到了.” 今天我们将着重介绍slot和父子组件之间的访问和通信,slot是一个非常有用的东西,它相当于一个内容插槽,它是我们重用组件的基础.Vue的事件系统独立于原生的DOM事件,它用于组件之间的通信. 本文的主要内容如下: 组件的编译作用域 在组件template中使

vue、react、angular三大框架对比

前端当前最火的三大框架当属vue.react以及angular了. 但是在做项目的时候,我们怎么去选择呢?  这里做一个比较,希望大家可以有一个比较清晰的认识. vue与react vue和react是当前最火的两个前端框架,vue的发展很快,但是目前来说,react的生态系统会更强大,世界上使用这个框架的人也很多. 另外,react是facebook官方维护的, 而vue是尤雨溪本人维护的. 并且在其他周边库,如react的react-rouer和redux,是react社区在维护的. 而vu