原生JavaScript实现观察者与发布订阅模式详解

作者:异步漫步

时间:2026-10-23

浏览:374

本文介绍如何使用原生JavaScript实现观察者模式和发布订阅模式。通过定义全局事件类,利用on、one、off和trigger方法管理事件监听与触发,帮助前端开发实现模块间解耦。文章包含核心代码示例及在React组件中的应用场景,适合希望深入理解设计模式的开发者参考。

文章目录

观察者模式概述

本文通过具体实例,详细解析了使用原生JavaScript实现的观察者模式与发布订阅模式,旨在为读者提供清晰的参考与学习素材。

观察者模式在概念上等同于发布者-订阅者模式。其核心机制在于:发布者负责发布事件,而订阅者则监听这些事件并在接收到信号后做出相应的反应。

在前端开发中,为了实现模块间的解耦,观察者模式是一种被广泛采用的设计模式。它大量应用于各类框架和类库的设计之中,是解决复杂交互关系的有效手段。

核心代码实现

以下是实现该模式的核心代码逻辑。

事件代理类定义


// eventProxy.js
'use strict';
const eventProxy = {
 onObj: {},
 oneObj: {},
 on: function(key, fn) {
  if(this.onObj[key] === undefined) {
   this.onObj[key] = [];
  }
 
  this.onObj[key].push(fn);
 },
 one: function(key, fn) {
  if(this.oneObj[key] === undefined) {
   this.oneObj[key] = [];
  }
 
  this.oneObj[key].push(fn);
 },
 off: function(key) {
  this.onObj[key] = [];
  this.oneObj[key] = [];
 },
 trigger: function() {
  let key, args;
  if(arguments.length == 0) {
   return false;
  }
  key = arguments[0];
  args = [].concat(Array.prototype.slice.call(arguments, 1));
 
  if(this.onObj[key] !== undefined
   && this.onObj[key].length > 0) {
   for(let i in this.onObj[key]) {
    this.onObj[key][i].apply(null, args);
   }
  }
  if(this.oneObj[key] !== undefined
   && this.oneObj[key].length > 0) {
   for(let i in this.oneObj[key]) {
    this.oneObj[key][i].apply(null, args);
    this.oneObj[key][i] = undefined;
   }
   this.oneObj[key] = [];
  }
 }
};
 
export default eventProxy;

使用方法与配置

在实际使用中,开发者需要引入全局事件类,或者通过配置Webpack构建工具,将事件类设置为全局变量以便在项目中调用。

React组件中的应用


import { eventProxy } from '@/utils'
 
class Parent extends Component{
 render() {
  return (
   <div style={{marginTop:"50px"}}>
    <Child_1/>
    <Child_2/>
   </div>
  );
 }
}
// componentDidUpdate 与 render 方法与上例一致
class Child_1 extends Component{
 componentDidMount() {
  setTimeout(() => {
   // 发布 msg 事件
   console.log(eventProxy)
   eventProxy.trigger('msg', 'end','lll');
  }, 5000);
 }
 render() {
  return (
   <div>我是组件一</div>
  )
 }
}
// componentDidUpdate 方法与上例一致
class Child_2 extends Component{
 state = {
  msg: 'start'
 };
 
 componentDidMount() {
  // 监听 msg 事件
  eventProxy.on('msg', (msg,mm) => {
   console.log(msg,mm)
   this.setState({
    msg:msg
   });
  });
 }
 
 render() {
  return <div>
   <p>child_2 component: {this.state.msg}</p>
  </div>
 }
}

参考资料与测试

本示例的设计思路参考了淘宝前端团队的技术库。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章