深度分析MVC和MVVM:你在选择框架的时候应该注意什么?

news2024/11/20 19:27:51
  • 💖 作者简介:大家好,我是Zeeland,全栈领域优质创作者。
  • 📝 CSDN主页:Zeeland🔥
  • 📣 我的博客:Zeeland
  • 📚 Github主页: Undertone0809 (Zeeland) (github.com)
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 💬介绍:The mixture of software dev+Iot+ml+anything🔥

本文节选自笔者博客: https://www.blog.zeeland.cn/archives/23jl09phfr

前言

最近在做安卓开发,重温一下MVC和MVVM的概念,于是去网上搜了一下,网上关于MVC的介绍有很多,但是对MVVM的介绍都不是很全面,因此本人打算重新写一篇文章梳理一下,本文将介绍什么是MVC, MVVM架构,并且将引用一些简单的例子进行讲解。

什么是MVC?

首先,需要明确的一点是,MVC是软件开发中一个比较成熟的概念,下面用苹果开发者文档中的一个图片来展示这个架构再适合不过了。

总的来说:

  • Model:数据模型,用来存储数据
  • View: 视图界面,用于渲染UI界面和进行用户交互
  • Controller:控制器,监听模型数据的改变和控制视图行为、处理用户交互

假设有一个购物网站,我们以商品详情页为例:

  • MVC架构:在MVC架构中,Model表示商品的数据,View表示页面的HTML代码,Controller表示处理商品数据的业务逻辑。当用户访问商品详情页时,Controller处理数据并渲染HTML代码,然后将其传递给View,最终呈现给用户。但是,当我们需要对同一个数据进行多处修改时,就需要在多个Controller中进行操作,导致代码重复和难以维护。
  • 上图当我们点击购买按键后,客户端会向服务器发送购买商品的请求,这个时候某一个Controller会被执行,你可以理解为按键点击之后服务器中的一个函数会被回调。
  • 这个时候Controller从数据库中获取数据,并封装成一个类,如下所示:
class Good:
	def __init__(self, **kwargs):
		self.name = kwargs['name']
		self.price = kwargs['price']
		self.num = kwargs['num']

class User:
	def __init__(self, **kwargs):
		self.name = kwargs['name']
		self.balance = kwargs['balance']

  • Controller从数据库获取到User的信息之后,会实例化一个User,并初始化User信息。这里的User就是一个Model。获取到用户信息后,Controller中会做出相应的判断,如该用户的余额是否可以买得起这个商品,或者再去查询Good的数据,去查询这个商品是否还有存货,该商品的价格等,等到一些判断满足条件之后,Controller会返回一串JSON数据给前端,如下所示:
{
	code: 200,
	msg: "success",
	data: True
}
  • 这里的data: True 想表达的是用户有充足的余额购买该商品,且商品还有存货,这个时候我们就返回True。当然具体返回什么数据,这个看自己是怎么定义的,没有一个固定的标准。
  • 前端(这里就是VIEW了)接收到后端返回的数据之后,再进行对应的判断,data为True,则前端现在可以跳转到输入密码页面让用户数据密码,输入密码之后再发请求到服务器告诉服务器,如此反复,进行前后端交互。

这里仅仅举一个不恰当的例子,为了更好地理解,真实的业务场景并不是这样的,也比这个更加的复杂。

至此,相信你已经可以简单的对MVC架构有一个概念了

什么是MVVM?

MVVM其实表示的是 Model-View-ViewModel

  • Model:模型层,负责处理业务逻辑以及和服务器端进行交互
  • View:视图层:负责将数据模型转化为UI展示出来,可以简单的理解为HTML页面
  • ViewModel:视图模型层,用来连接Model和View,是Model和View之间的通信桥梁

在MVVM的架构下,View层和Model层并没有直接联系,而是通过ViewModel层进行交互。 ViewModel层通过双向数据绑定将View层和Model层连接了起来,使得View层和Model层的同步工作完全是自动的。
因此开发者只需关注业务逻辑,无需手动操作DOM。

在MVVM架构中,ViewModel起到了重要的作用。ViewModel是View和Model之间的一个连接者,将Model中的数据转化为View可以使用的格式,然后将其传递给View。例如,我们可以为商品详情页创建一个ViewModel,其中包含商品的名称、价格、描述等数据,在Controller中调用ViewModel,并将其传递给View,最终呈现给用户。如果数据需要更新,只需要在ViewModel中进行修改,其他Controller和View不需要进行更改,大大减少了代码的重复和维护难度。

在MVVM的架构下,View层和Model层并没有直接联系,而是通过ViewModel层进行交互。 ViewModel层通过双向数据绑定将View层和Model层连接了起来,使得View层和Model层的同步工作完全是自动的。
因此开发者只需关注业务逻辑,无需手动操作DOM。

与MVC相比,MVVM模式中将视图从Controller中解放出来,实现了View(视图)与ViewModel的松耦合,ViewModel允许单元测试和依赖注入,能够更好地支持应用程序的可扩展性和可维护性,也可以更好地满足前端框架对于数据操作和渲染效率的需求。

整个过程的工作流程如下:

1.用户操作页面触发视图中的事件

2.事件通知ViewModel进行相应的业务逻辑处理

3.ViewModel将处理结果反馈给View进行数据绑定

4.View更新数据展示给用户

Vue 与 MVVM

Vue 框架就是一个典型的 MVVM 模型的框架。
Vue 框架其实就是起到 MVVM 模式中的 ViewModel 层的作用。

使用代码来理解之间的关系:

使用jQuery来操作DOM元素,添加一个button按钮,并绑定click事件

if(Btn){
	let btn = $('<button>点我</butten>')
	btn.on('click',function(){
		console.log('点到我了...')
	});
	$('#app').append(btn)
}

从上述代码可以看到,负责视图的 HTML 代码和负责业务逻辑的 JS 代码耦合到一起,这是个很严重的问题
如果我们直接操作DOM元素,会造成性能低下等一系列问题

如果使用Vue的话,可以将视图层和模型层有效地分离开来

<template>
   <div>
     <button @click="handeClick()">点我</button>
   </div>
</template>
<script>
export default {
   name:'App',
   methods:{
     handleClick:function(){
       console.log('点到我了...');
     }
   },
}
</script>

上面这段代码可以看到,负责视图的 HTML 代码和负责业务逻辑的 JS 代码有效地分离开来。之所以能做到这一点,主要是依靠 Vue 框架才得以实现的。

我觉最好了解MVVM的方法,就是去手写一遍Vue(狗头)。参考链接 Vue MVVM实现原理流程 案例分析 - 掘金 (juejin.cn)

Resources

  • 什么是MVVM框架? - 知乎 (zhihu.com)
  • Model-View-Controller (apple.com)
  • Vue MVVM理解及原理实现 - 掘金 (juejin.cn)
  • Vue MVVM实现原理流程 案例分析 - 掘金 (juejin.cn)

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

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

相关文章

SpringCloudalibaba微服务工具集

版本: Hoxton SR6 1.什么是微服务 官网 In short, the microservice architectural(架构) style is an approach to developing a single application as a suite(系列) of small services, each running in its own process(进程) and communicating with lightweight mech…

【C++基础】内联函数、nullptr(内联函数的概念;内联函数VS宏函数;内联函数的特性;C++11中的nullptr)

七、内联函数 7.1 内联函数的概念 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率。 应用场景&#xff1a; 短小简单的函数&#xff08;1-10行&#xff…

一篇文章把所有前端安全相关的攻击和防御都给解决了——XSS攻击和CSRF攻击

前端安全 1. XSS跨站脚本攻击 1.1 定义 XSS跨站脚本攻击(Cross Site Scripting)&#xff0c;很多人会缩写成CSS&#xff0c;但是这个缩写会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆&#xff0c;所以&#xff0c;我们通常把跨站脚本攻击缩写成XSS&#xff1b; X…

huggingface transformer模型库使用(pytorch)

参考&#xff1a; https://huggingface.co/docs transformer库 介绍 使用群体&#xff1a; 寻找使用、研究或者继承大规模的Tranformer模型的机器学习研究者和教育者想微调模型服务于他们产品的动手实践就业人员想去下载预训练模型&#xff0c;解决特定机器学习任务的工程师…

初识linux之线程控制

目录 一、POSIX线程库 二、线程创建 1.创建线程的接口 2. 错误的创建多线程 3.正确的创建多线程 4. 线程的私有栈结构 三、线程终止 1. 函数结束 2. 调用pthread_exit&#xff08;&#xff09;终止 3.调用pthread_cancel&#xff08;&#xff09;函数 四、线程等待 …

C++初阶 -1- C++入门

文章目录0.什么是C1.C关键字2.命名空间导入什么是命名空间命名空间的使用3.C 输入&输出4.缺省参数什么是缺省参数缺省参数的应用场景5.函数重载0.什么是C C是基于C语言而产生的&#xff0c;它既可以进行C语言的过程化程序设计&#xff0c;又可以进行以抽象数据类型为特点的…

基于ESP32和blinker的红外小夜灯控制

一. 系统设计及框图&#xff1a; 本设计可以实现通过手机APP使用蓝牙或WIFI远程控制红外设备&#xff0c;也可以通过离线语音模块语音控制红外设备。可以控制市面上常见的NEC格式的红外设备, 这里是控制小夜灯&#xff0c;其它红外设备在控制原理上是相通的。本设计可用作课程…

二、UVM Sequencer和Sequence

了解sequencer与driver之间传递sequence item的握手过程&#xff0c;也掌握了sequence与item之间的关系。接下来对sequence挂载到sequencer的常用方法总结&#xff0c;可以通过这些方法和宏的介绍&#xff0c;了解到它们不同的使用场景面对多个sequence如果需要同时挂到sequenc…

机器学习:基于AdaBoost算法对信用卡精准营销建立模型(附案例实战)

机器学习&#xff1a;基于AdaBoosts算法对信用卡精准营销建立模型 作者&#xff1a;i阿极 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&a…

OPNET Modeler 例程——M/M/1 队列建模

文章目录一、例程概述二、模型构建三、仿真配置及结果1.M/M/1 队列2.M/M/n 队列总结一、例程概述 本例程是使用节点编辑器建立一个 M/M/1 队列模型&#xff0c;同时对仿真收集到的统计数据进行数学分析。M/M/1 队列由先进先出的缓冲区组成&#xff0c;数据包的到达服从指数(泊…

Mybatis动态SQL查询 --(附实战案例--8888个字--88质量分)

目录 前言 一、动态SQL---if标签 1. 持久层添加用户通用查询方法 2. 映射文件添加相关标签 3. 测试类新建测试方法 4. 运行结果 二、动态SQL---where标签 1. 映射文件添加相关标签 2. 测试类新建测试方法 3. 运行结果 三、动态SQL---set标签 1. 持久层添加用户更新方…

DNS域名协议(IP段获取DNS服务器、反解析获取主机域名、查找子域名记录、查看子域名记录)

IP段获取DNS服务器 nmap 192.168.190.0/24 -p53 反解析获取主机域名 host 192.168.137.149 192.168.137.149 查找子域名记录 dig 192.168.137.149 -t axfr MAILMAN.com 查看子域名记录 dig 192.168.137.149 -t axfr _msdcs.MAILMAN.com

神经微分方程Resnet变体实现内存下降和保持精度

本文内容&#xff1a; 1、学习神经微分方程的笔记&#xff0c;主要锻炼自己学习新知识的能力和看有很多数学原理的论文能力&#xff1b; 2、神经微分方程可以用于时序数据建模、动力学建模等&#xff0c;但是本文专注于分类问题-resnet变体<比较容易理解>&#xff1b; …

StringBuffer,StringBuilder,

StringBuffer 结构示意图&#xff0c; Serializable,可以实现网络传输 package com.jshedu.StringBuffer_;/*** author Mr.jia* version 1.0*/public class StringBuffer01 {public static void main(String[] args) {/*1.在父类中AbstractStringBuilder 属性char[] value不是f…

博弈论在电动车和电网系统中分布式模型预测控制研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Android中使用有趣的指示器和过渡自定义 Compose Pager

Android使用有趣的指示器和过渡自定义 Compose Pager google最近在compose中新增了Pager控件&#xff0c;HorizontalPager和VerticalPager。 页面之间的转换 该文档涵盖了访问页面从“对齐”位置滚动到多远的基础知识。我们可以使用这些信息来创建页面之间的过渡效果。 例…

DC:4通关详解

信息收集 漏洞发现 访问web 尝试弱口令 账号admin 可以执行ls du df看看发的包,我们是否有机会执行任意命令 发现post传参radio处可以任意命令执行 弹个shell先 提权 从vps上下载LinEnum.sh来枚举脆弱性 优化shell 现在shell就有自动补齐了 在/home/jim下发现密码字典…

cube-studio AI平台 提供开源模型示例列表(3月份)

文章目录背景AI应用商店背景 cube是腾讯音乐开源的一站式云原生机器学习平台&#xff0c;目前主要包含 1、数据管理&#xff1a;特征存储、在线和离线特征&#xff1b;数据集管理、结构数据和媒体数据、数据标签平台 2、开发&#xff1a;notebook(vscode/jupyter)&#xff1b…

【PTA天梯赛】L1-001 L1-002 L1-003 L-004 L-005 L-006 L-007 L-008 L-009 L1-010 c++

&#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;狠狠的刷题&#xff01;&#xff01;&#xff01;&#x1f308; 若有帮助&#xff0c;还请…

【Ubuntu 22.04 上配置 FTP 服务器步骤】

Ubuntu 22.04 上配置 FTP 服务器步骤 1.安装 vsftpd 软件包&#xff1a; sudo apt-get update sudo apt-get install vsftpd 2.查看vsftpd版本和状态&#xff0c;确认vsftpd安装成功和正常启动 2.修改 vsftpd 配置文件&#xff1a; sudo nano /etc/vsftpd.conf 3.在配置文件中…