深入vue2.0源码系列: 事件机制的实现与运用

news/2024/6/18 2:51:41 标签: javascript, 前端, vue.js

前言

Vue.js 2.0使用了一种事件机制来实现组件间的通信和状态管理,本文将会介绍Vue.js 2.0事件机制的实现和运用。

事件机制的实现

Vue.js 2.0的事件机制实现依赖于一个名为 vm.$emit 的实例方法和一个名为 vm.$on 的实例方法。当组件需要向其他组件通信时,可以调用 vm.$emit 方法触发一个自定义事件,其他组件可以通过调用 vm.$on 方法来监听这个自定义事件。这样就能够实现组件间的通信。

下面我们来看一下 vm.$emitvm.$on 方法的实现。

vm.$emit 的实现

vm.$emit 方法定义在 src/core/instance/events.js 文件中,其实现如下:

javascript">// Vue实例原型上定义$emit方法
Vue.prototype.$emit = function (event: string): Component {
  const vm: Component = this
  // 开发环境下,如果事件名称存在大写字符并且存在监听该事件的回调函数,则输出警告
  if (process.env.NODE_ENV !== 'production') {
    const lowerCaseEvent = event.toLowerCase()
    if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
      warn(
        `Event "${lowerCaseEvent}" is emitted in component ` +
        `${formatComponentName(vm)} but the handler is registered for "${event}". ` +
        `Note that HTML attributes are case-insensitive and you cannot use ` +
        `v-on to listen to camelCase events when using in-DOM templates. ` +
        `You should probably use "${hyphenate(event)}" instead of "${event}".`
      )
    }
  }
  // 通过事件名称获取当前实例上所有监听该事件的回调函数
  let cbs = vm._events[event]
  if (cbs) {
    // 如果存在回调函数,则调用所有回调函数,并将参数传递给它们
    cbs = cbs.length > 1 ? toArray(cbs) : cbs
    const args = toArray(arguments, 1)
    for (let i = 0, l = cbs.length; i < l; i++) {
      try {
        cbs[i].apply(vm, args)
      } catch (e) {
        handleError(e, vm, `event handler for "${event}"`)
      }
    }
  }
  return vm
}

vm.$on 的实现

vm.$on 方法的实现也定义在 src/core/instance/events.js 文件中,其实现如下:

javascript">Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
  const vm: Component = this
  if (Array.isArray(event)) {
    for (let i = 0, l = event.length; i < l; i++) {
      vm.$on(event[i], fn)
    }
  } else {
    // 如果不存在该事件的回调函数,则初始化一个空数组来存储
    (vm._events[event] || (vm._events[event] = [])).push(fn)
    // optimize hook:event cost by using a boolean flag marked at registration
    // instead of a hash lookup
    if (hookRE.test(event)) {
      vm._hasHookEvent = true
    }
  }
  return vm
}

上面的代码中,如果 vm._events 对象中不存在该事件的回调函数,就会初始化一个空数组来存储回调函数。如果该事件名称匹配了 hookRE 正则表达式,就会将 _hasHookEvent 标记为 true,这样可以在组件更新时快速判断是否需要调用生命周期钩子函数。

事件机制的运用

事件机制在 Vue.js 2.0 中广泛应用于组件间的通信和状态管理。以下是一些事件机制的运用场景:

父子组件间的通信

父组件可以在模板中使用 v-on 指令监听子组件触发的事件,如:

<template>
  <child-component @custom-event="handleCustomEvent"></child-component>
</template>

子组件在触发事件时,可以调用 $emit 方法并传递事件名称及数据:

javascript">this.$emit('custom-event', data)

非父子组件间的通信

对于非父子组件间的通信,可以使用一个名为 EventBus 的事件总线实现。EventBus 可以是一个简单的 Vue 实例,用来在组件之间进行事件传递。

首先,创建一个 EventBus 实例并导出:

javascript">import Vue from 'vue'
export const EventBus = new Vue()

然后,在需要传递事件的组件中引入 EventBus 实例,并使用 $emit 方法触发事件:

javascript">import { EventBus } from '@/event-bus.js'

// 触发事件
EventBus.$emit('custom-event', data)

在需要监听事件的组件中也需要引入 EventBus 实例,并使用 $on 方法监听事件:

javascript">import { EventBus } from '@/event-bus.js'

// 监听事件
EventBus.$on('custom-event', data => {
  // 处理事件
})

Vuex 状态管理

Vue.js 2.0 提供了一个名为 Vuex 的状态管理库,它可以帮助我们更好地管理组件状态,并且能够实现跨组件的状态共享。

Vuex 中的状态存储在一个中央的 store 中,可以通过 this.$store 在组件中访问。当组件需要修改状态时,可以通过提交一个 mutation 来改变状态,或者通过分发一个 action 来触发一系列的状态变更操作。

当状态发生变化时,所有使用该状态的组件都会得到通知,并进行相应的更新。

javascript">// 定义 store
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

export default store

// 在组件中使用 state 和 mutation
<template>
  <div>
    {{ count }}
    <button @click="increment">Increment</button>
  </div>
</template>

<script>javascript">
export default {
  computed: {
    count () {
      return this.$store.state.count
    }
  },
  methods: {
    increment () {
      this.$store.commit('increment')
    }
  }
}
</script>

以上就是 Vue.js 2.0 中事件机制的实现和运用,它们在实现组件间通信和状态管理方面提供了很大的便利。

总结

在 Vue.js 2.0 中,事件机制被广泛运用于实现组件之间的通信和状态管理。对于父子组件之间的通信,可以使用 props$emit 方法;对于非父子组件之间的通信,可以使用一个名为 EventBus 的事件总线实现;对于状态管理,可以使用 Vuex 库来实现状态存储和变更操作。这些机制的运用使得 Vue.js 的组件化开发更加方便和灵活。


http://www.niftyadmin.cn/n/154361.html

相关文章

【微信小程序】-- 使用 npm 包 - API Promise化(四十二)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…

ChatGPT背后有哪些关键技术?CSIG企业行带你一探究竟

目录1 ChatGPT的时代2 CSIG企业行3 议题&嘉宾介绍3.1 对生成式人工智能的思考3.2 对话式大型语言模型研究3.3 文档图像处理中的底层视觉技术4 观看入口1 ChatGPT的时代 2015年&#xff0c;马斯克、美国创业孵化器Y Combinator总裁阿尔特曼、全球在线支付平台PayPal联合创始…

LoadRunner——SLA服务水平协议设置(十三)

{SLA服务水平协议设置&#xff1a;} 全称&#xff1a; service level agreement 作用&#xff1a; 在性能测试过程中&#xff0c;提前设定性能测试的目标和要度量的性能指标&#xff0c; 工作原理&#xff1a; 在性能测试过程中LR会收集和保存性能的相关数据&#xff0c;在分…

Linux-用户以及用户组讲解

用户以及用户组讲解 简单的用户说明 Linux的操作系统是一个多用户管理的系统&#xff1b; 因此经常使用组的概念来管理用户&#xff1b; Linux是用用户ID来识别的&#xff1b; root&#xff1a;超级管理员–>ID为0系统用户&#xff1a;–>ID号为1-1000普通用户&…

业务中台技术选型

BX的业务中台用的是 Dubbo再封装技术 业务组件&#xff1a;配置中心&#xff0c;安全中心&#xff0c;消息中心&#xff0c;任务中心&#xff0c;流程中心&#xff0c;规则中心 技术组件&#xff1a; 前端&#xff08;iPlatUI&#xff09;&#xff1a;布局组件&#xff0c;导…

Baklib——企业知识库搭建的轻松工具

在当今信息化时代&#xff0c;企业的发展离不开知识的积累和传承。而随着企业规模的扩大和业务范围的增加&#xff0c;知识的管理和传递也变得越来越复杂。为了解决这一问题&#xff0c;搭建一个高效的企业知识库显得尤为重要。而Baklib作为一款在线搭建企业知识库的工具&#…

深度盘点!ChatGPT 还能这么用?

开放隐私计算ChatGPT能干什么&#xff1f;你脑海中第一个想到的是不是“聊天”&#xff1f;但其实聊天只是我们和他交互的形式&#xff0c;他能干的事儿我们可以分为“基础组件”和“组合套件”。先看“基础组件”。图源网络一共有49项“基础组件”&#xff01;从最常规也是我们…

专利实例详解

大家好,我是英子老师。作为一名知识产权专家,深耕于专利行业十余年,具有丰富的专利工作经验:曾在大型专利代理机构从事专利代理工作、专利质检工作(抽查代理机构的专利代理人的撰写质量并评分);之后在知名上市企业、行业龙头企业担任高级专利工程师的职位,主要工作内容…