vue中的设计模式

news2025/1/8 18:39:20

vue中使用了哪些设计模式

1. 观察者模式(Observer Pattern)

  • 应用场景:Vue 的响应式系统核心就是观察者模式。

  • 实现方式:通过 Object.definePropertyProxy 监听数据变化,当数据发生变化时,通知依赖的视图更新。

  • 示例

    const data = { message: 'Hello' };
    const vm = new Vue({
      data: data
    });
    // 修改 data.message 会触发视图更新
    data.message = 'World';
     

2. 发布-订阅模式(Publish-Subscribe Pattern)

  • 应用场景:Vue 的事件系统($on, $emit)和全局事件总线(Event Bus)就是发布-订阅模式的实现。

  • 实现方式:组件通过 $on 订阅事件,通过 $emit 发布事件。

  • 示例

    // 组件 A
    this.$emit('event-name', data);
    ​
    // 组件 B
    this.$on('event-name', (data) => {
      console.log(data);
    });
     

3. 单例模式(Singleton Pattern)

  • 应用场景:Vuex 的状态管理库和 Vue Router 的路由实例通常采用单例模式。

  • 实现方式:确保全局只有一个实例,避免重复创建。

  • 示例

    // Vuex Store
    const store = new Vuex.Store({ /* 配置 */ });
    ​
    // Vue Router
    const router = new VueRouter({ /* 配置 */ });
     

4. 工厂模式(Factory Pattern)

  • 应用场景:Vue 的组件系统可以看作是一种工厂模式。

  • 实现方式:通过 Vue.component 或单文件组件(.vue 文件)创建可复用的组件。

  • 示例

    Vue.component('my-component', {
      template: '<div>My Component</div>'
    });

5. 插件模式

核心思想

  • 扩展性:通过插件机制,允许第三方或开发者为框架添加新功能。

  • 解耦:插件与框架核心代码分离,避免直接修改框架源码。

  • 一致性:提供统一的插件安装和使用方式,简化开发流程。


插件模式-Vue.use 的实现原理

Vue.use 是 Vue.js 提供的一个全局方法,用于安装插件。其核心逻辑如下:

  1. 检查插件是否已安装:避免重复安装。

  2. 调用插件的 install 方法:如果插件是一个对象,必须提供 install 方法;如果插件是一个函数,则直接调用。

  3. 传递 Vue 构造函数:将 Vue 构造函数作为参数传递给插件的 install 方法,以便插件可以扩展 Vue 的功能。

源码示例(简化):

Vue.use = function (plugin) {
  const installedPlugins = this._installedPlugins || (this._installedPlugins = []);
  if (installedPlugins.indexOf(plugin) > -1) {
    return this;
  }

  const args = Array.from(arguments).slice(1);
  args.unshift(this);

  if (typeof plugin.install === 'function') {
    plugin.install.apply(plugin, args);
  } else if (typeof plugin === 'function') {
    plugin.apply(null, args);
  }

  installedPlugins.push(plugin);
  return this;
};
 
ElementUI 的插件实现

ElementUI 是一个基于 Vue.js 的 UI 组件库,它通过插件模式将自己注册到 Vue 中。以下是 ElementUI 插件的基本实现:

ElementUI 的 install 方法

ElementUI 提供了一个 install 方法,用于全局注册组件、指令和混入等。

示例(简化):

const ElementUI = {
  install(Vue) {
    // 注册全局组件
    Vue.component('ElButton', Button);
    Vue.component('ElInput', Input);
    // 注册全局指令
    Vue.directive('focus', FocusDirective);
    // 添加全局混入
    Vue.mixin({
      created() {
        console.log('ElementUI plugin installed');
      }
    });
  }
};
 
使用 Vue.use 安装 ElementUI

通过 Vue.use(ElementUI),ElementUI 的 install 方法会被调用,从而将组件、指令等注册到 Vue 中。

示例:

import Vue from 'vue';
import ElementUI from 'element-ui';

Vue.use(ElementUI);
 

 插件模式的优势
  • 模块化:将功能封装为插件,便于管理和复用。

  • 灵活性:开发者可以根据需求选择安装不同的插件。

  • 扩展性:框架的功能可以通过插件无限扩展,而无需修改核心代码。

  • 一致性:提供统一的插件安装方式,降低学习成本。

5. 依赖注入模式(Dependency Injection Pattern)

  • 应用场景:Vue 的 provideinject 机制就是依赖注入模式的实现。

  • 实现方式:父组件通过 provide 提供依赖,子组件通过 inject 注入依赖。

  • 示例

    // 父组件
    new Vue({
      provide: {
        message: 'Hello from parent'
      }
    });
    ​
    // 子组件
    new Vue({
      inject: ['message'],
      created() {
        console.log(this.message); // 输出: Hello from parent
      }
    });
     

手写发布订阅模式和观察者模式

分别用代码实现观察者模式与发布订阅模式

// 创建发布-订阅中心
const eventBus = {
  events: {},
  subscribe(event, callback) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  },
  publish(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(callback => {
        callback(data);
      });
    }
  }
};
​
// 订阅者1
const subscriber1 = data => {
  console.log('Subscriber 1 received data:', data);
};
​
// 订阅者2
const subscriber2 = data => {
  console.log('Subscriber 2 received data:', data);
};
​
// 在发布-订阅中心订阅事件
eventBus.subscribe('event1', subscriber1);
eventBus.subscribe('event1', subscriber2);
​
// 在发布-订阅中心发布事件
eventBus.publish('event1', 'Hello, this is event data!');
​
// 输出:
// Subscriber 1 received data: Hello, this is event data!
// Subscriber 2 received data: Hello, this is event data!
// 定义被观察者
class Subject {
  constructor() {
    this.observers = [];
  }
​
  addObserver(observer) {
    this.observers.push(observer);
  }
​
  notifyObservers(data) {
    this.observers.forEach(observer => {
      observer.update(data);
    });
  }
}
​
// 定义观察者
class Observer {
  update(data) {
    console.log('Observer received data:', data);
  }
}
// 定义观察者
class Observer2 {
  update(data) {
    console.log('Observer received data 2:', data);
  }
}
​
// 创建被观察者和观察者对象
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer2();
​
// 将观察者添加到被观察者的观察者列表中
subject.addObserver(observer1);
subject.addObserver(observer2);
​
// 被观察者通知观察者更新
subject.notifyObservers('Hello, this is update data!');
1. 应用场景
(1)观察者模式
  • 适用于对象之间关系紧密的场景,例如:

    • GUI 事件处理(如按钮点击事件)。

    • 数据模型和视图之间的同步(如 MVC 模式)。

(2)发布-订阅模式
  • 适用于对象之间关系松散或需要解耦的场景,例如:

    • 消息队列系统。

    • 跨组件通信(如 Vue 的全局事件总线)。

    • 微服务架构中的事件驱动通信。


2. 优缺点对比
(1)观察者模式
  • 优点

    • 实现简单,适合一对多的依赖关系。

    • 被观察者和观察者之间的通信是实时的。

  • 缺点

    • 被观察者和观察者之间是强耦合的,修改被观察者可能会影响观察者。

    • 如果观察者过多,通知所有观察者可能会影响性能。

(2)发布-订阅模式
  • 优点

    • 发布者和订阅者之间是松耦合的,易于扩展和维护。

    • 支持多对多的通信关系。

  • 缺点

    • 实现相对复杂,需要引入消息中心。

    • 消息中心可能会成为系统的性能瓶颈。

3.核心区别
(1)设计思想
  • 观察者模式:强调 直接绑定 和 明确的关系。被观察者知道观察者的存在,并直接调用观察者的方法。

  • 发布-订阅模式:强调 解耦 和 间接通信。发布者和订阅者不知道彼此的存在,它们通过消息中心进行通信。

(2)耦合度
  • 观察者模式:被观察者和观察者之间是 强耦合 的。被观察者需要直接持有观察者的引用。

  • 发布-订阅模式:发布者和订阅者之间是 松耦合 的。它们通过消息中心通信,彼此不直接依赖。

(3)适用场景
  • 观察者模式:适合 直接绑定 的场景,例如数据模型和视图之间的同步。

  • 发布-订阅模式:适合 解耦复杂系统 的场景,例如跨组件通信或事件驱动架构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2272775.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安卓NDK视觉开发——手机拍照文档边缘检测实现方法与库封装

一、项目创建 创建NDK项目有两种方式&#xff0c;一种从新创建整个项目&#xff0c;一个在创建好的项目添加NDK接口。 1.创建NDK项目 创建 一个Native C项目&#xff1a; 选择包名、API版本与算法交互的语言&#xff1a; 选择C版本&#xff1a; 创建完之后&#xff0c;可…

MATLAB仿真:基于GS算法的经大气湍流畸变涡旋光束波前校正仿真

GS算法流程 GS&#xff08;Gerchberg-Saxton&#xff09;相位恢复算法是一种基于傅里叶变换的最速下降算法&#xff0c;可以通过输出平面和输入平面上光束的光强分布计算出光束的相位分布。图1是基于GS算法的涡旋光束畸变波前校正系统框图&#xff0c;在该框图中&#xff0c;已…

【React+TypeScript+DeepSeek】穿越时空对话机

引言 在这个数字化的时代&#xff0c;历史学习常常给人一种距离感。教科书中的历史人物似乎永远停留在文字里&#xff0c;我们无法真正理解他们的思想和智慧。如何让这些伟大的历史人物"活"起来&#xff1f;如何让历史学习变得生动有趣&#xff1f;带着这些思考&…

深入刨析数据结构之排序(上)

目录 1.内部排序 1.1概述 1.2插入排序 1.2.1其他插入排序 1.2.1.1 折半插入排序 1.2.1.2 2-路插入排序 1.3希尔排序 1.4快速排序 1.4.1起泡排序 1.4.2快速排序 1.4.2.1hoare版本 1.4.2.2挖坑版本 1.4.2.3前后指针版本 1.4.2.4优化版本 1.4.2.4.1小区间插入排序优…

AIA - APLIC之三(附APLIC处理流程图)

本文属于《 RISC-V指令集基础系列教程》之一,欢迎查看其它文章。 1 APLIC复位 APLIC复位后,其所有状态都变得有效且一致,但以下情况除外: 每个中断域的domaincfg寄存器(spec第 4.5.1 节);可能是machine-level interrupt domain的MSI地址配置寄存器(spec第4.5.3 和4.5…

openwrt 清缓存命令行

一、查看缓存 &#xff1a; free -m 二、清缓存&#xff1a;echo 3 > /proc/sys/vm/drop_caches  三、详解。 释放物理页缓存 echo 1 > /proc/sys/vm/drop_caches 释放可回收的slab对象&#xff0c;包含inode and dentry echo 2 > /proc/sys/vm/drop_caches 同时…

Linux -- 端口号、套接字、网络字节序、sockaddr 结构体

目录 什么是端口号&#xff1f; 什么是套接字&#xff1f; 网络字节序 struct sockaddr 结构体 什么是端口号&#xff1f; 我们日常上网的时候&#xff0c;主机其实是在进行两种操作&#xff1a; 1、把远端的数据拉取到本地&#xff0c;比如刷抖音的时候&#xff0c;手机向…

《数据结构》期末考试测试题【中】

《数据结构》期末考试测试题【中】 21.循环队列队空的判断条件为&#xff1f;22. 单链表的存储密度比1&#xff1f;23.单链表的那些操作的效率受链表长度的影响&#xff1f;24.顺序表中某元素的地址为&#xff1f;25.m叉树第K层的结点数为&#xff1f;26. 在双向循环链表某节点…

实际开发中,常见pdf|word|excel等文件的预览和下载

实际开发中,常见pdf|word|excel等文件的预览和下载 背景相关类型数据之间的转换1、File转Blob2、File转ArrayBuffer3、Blob转ArrayBuffer4、Blob转File5、ArrayBuffer转Blob6、ArrayBuffer转File 根据Blob/File类型生成可预览的Base64地址基于Blob类型的各种文件的下载各种类型…

《Opencv》基础操作详解(4)

接上篇&#xff1a;《Opencv》基础操作详解&#xff08;3&#xff09;-CSDN博客 目录 22、图像形态学操作 &#xff08;1&#xff09;、顶帽&#xff08;原图-开运算&#xff09; 公式&#xff1a; 应用场景&#xff1a; 代码示例&#xff1a; &#xff08;2&#xff09;…

大数据高级ACP学习笔记(2)

钻取&#xff1a;变换维度的层次&#xff0c;改变粒度的大小 星型模型 雪花模型 MaxCompute DataHub

尚硅谷· vue3+ts 知识点学习整理 |14h的课程(持续更ing)

vue3 主要内容 核心&#xff1a;ref、reactive、computed、watch、生命周期 常用&#xff1a;hooks、自定义ref、路由、pinia、miit 面试&#xff1a;组件通信、响应式相关api ----> 笔记&#xff1a;ts快速梳理&#xff1b;vue3快速上手.pdf 笔记及大纲 如下&#xff…

阻抗(Impedance)、容抗(Capacitive Reactance)、感抗(Inductive Reactance)

阻抗&#xff08;Impedance&#xff09;、容抗&#xff08;Capacitive Reactance&#xff09;、感抗&#xff08;Inductive Reactance&#xff09; 都是交流电路中描述电流和电压之间关系的参数&#xff0c;但它们的含义、单位和作用不同。下面是它们的定义和区别&#xff1a; …

在 SQL 中,区分 聚合列 和 非聚合列(nonaggregated column)

文章目录 1. 什么是聚合列&#xff1f;2. 什么是非聚合列&#xff1f;3. 在 GROUP BY 查询中的非聚合列问题示例解决方案 4. 为什么 only_full_group_by 要求非聚合列出现在 GROUP BY 中&#xff1f;5. 如何判断一个列是聚合列还是非聚合列&#xff1f;6. 总结 在 SQL 中&#…

B树与B+树:数据库索引的秘密武器

想象一下&#xff0c;你正在构建一个超级大的图书馆&#xff0c;里面摆满了各种各样的书籍。B树和B树就像是两种不同的图书分类和摆放方式&#xff0c;它们都能帮助你快速找到想要的书籍&#xff0c;但各有特点。 B树就像是一个传统的图书馆摆放方式&#xff1a; 1. 书籍摆放&…

回归预测 | MATLAB实现CNN-SVM多输入单输出回归预测

回归预测 | MATLAB实现CNN-SVM多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-SVM多输入单输出回归预测预测效果基本介绍模型架构程序设计参考资料 预测效果 基本介绍 CNN-SVM多输入单输出回归预测是一种结合卷积神经网络&#xff08;CNN&#xff09;和支持向量机&#…

Linux-Ubuntu之裸机驱动最后一弹PWM控制显示亮度

Linux-Ubuntu之裸机驱动最后一弹PWM控制显示亮度 一&#xff0c; PWM实现原理二&#xff0c;软件实现三&#xff0c;正点原子裸机开发总结 一&#xff0c; PWM实现原理 PWM和学习51时候基本上一致&#xff0c;控制频率&#xff08;周期&#xff09;和占空比&#xff0c;51实验…

自定义校验注解

已有的注解不能满足所有的校验需求,特殊的情况需要自定义校验(自定义校验注解) 1.自定义注解,并在注解上指定校验逻辑 Constraint(validatedBy StateValidation.class) // 指定校验逻辑 package com.example.demo.validation;import jakarta.validation.Constraint; import j…

分数阶傅里叶变换代码 MATLAB实现

function Faf myfrft(f, a) %分数阶傅里叶变换函数 %输入参数&#xff1a; %f&#xff1a;原始信号 %a&#xff1a;阶数 %输出结果&#xff1a; %原始信号的a阶傅里叶变换N length(f);%总采样点数 shft rem((0:N-1)fix(N/2),N)1;%此项等同于fftshift(1:N)&#xff0c;起到翻…

Ubuntu 20.04安装gcc

一、安装GCC 1.更新包列表 user596785154:~$ sudo apt update2.安装gcc user596785154:~$ sudo apt install gcc3.验证安装 user596785154:~$ gcc --version二 编译C文件 1.新建workspace文件夹 user596785154:~$ mkdir workspace2.进入workspace文件夹 user596785154:~…