mvc 和 mvvm 的区别和应用场景?

1. MVC

MVC 是 Model View Controller 的缩写

  • Model:模型层,是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
  • View:视图层,用户界面渲染逻辑,通常视图是依据模型数据创建的。
  • Controller:控制器,数据模型和视图之间通信的桥梁,通常控制器负责从事图读取数据,控制用户输入,并向模型发送数据。

MVC的思想:Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View。

MVC的特点:实现关注点分离,即应用程序中的数据模型与业务和展示逻辑解耦。就是将模型和视图之间实现代码分离,松散耦合,使之成为一个更容易开发、维护和测试的客户端应用程序。

MVC的优点

  • 耦合度低,视图层和业务层分离
  • 重用度高
  • 生命周期成本低
  • 可维护性高
  • 部署快

MVC的缺点

  • 不适合小型项目的开发
  • 视图与控制器间的过于紧密的连接,视图与控制器是相互分离,但却是联系紧密的部件,妨碍了他们的独立重用
  • 降低了视图对模型数据的访问,依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。

MVC的应用:主要用于中大型项目的分层开发。

MVC的例子: 举一个例子,页面有一个 id 为 container 的 span,点击按钮会让其内容加 1:

view:

<div>
  <span id="container">0</span>
  <button id="btn">+</button>
</div>

controller:

const button = document.getElementById('btn');
// 响应视图指令
button.addEventListener('click', () => {
  const container = document.getElementById('container');
  
  // 调用模型
  add(container);
}, false);

model:

function add (node) {
  // 业务逻辑处理
  const currentValue = parseInt(node.innerText);
  const newValue = currentValue + 1;
  
  // 更新视图
  node.innerText = current + 1;
}

这样就把数据更新分的比较明确了。

2. MVVM

MVVM是Model-View-ViewModel的简写,即模型-视图-视图模型。

  • Modal:模型,指的是后端传递的数据。
  • View:视图,指的是所看到的页面。
  • ViewModal:视图模型,mvvm模式的核心,它是连接view和model的桥梁。主要用来处理业务逻辑

它有两个方向:

  • 一是将模型转化成视图,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。
  • 二是将视图转化成模型,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。

这两个方向都实现的,就是数据的双向绑定。

MVVM的特点: 在MVVM的框架下,视图和模型是不能直接通信的,它们通过ViewModal来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。

MVVM的优点

MVVM模式的主要目的是分离视图(View)和模型(Model),有几大优点:

  • 低耦合,视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  • 可重用性,可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
  • 独立开发,开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码。
  • 可测试,界面向来是比较难于测试的,而现在测试可以针对ViewModel来写
  • 双向数据绑定,它实现了View和Model的自动同步,当Model的属性改变时,不需要手动操作Dom元素,来改变View的显示,而是改变属性后该属性对应View层显示会自动改变

MVVM适用场景: 适合数据驱动的场景,数据操作比较多的场景

本文转载于网络 如有侵权请联系删除

相关文章

  • netty系列之:让TLS支持http2

    简介我们知道虽然HTTP2协议并不强制使用HTTPS,但是对大多数浏览器来说,如果要使用HTTP2的话,则必须使用HTTPS,所以我们需要了解如何在netty的TLS中支持http2。TLS的扩展协议NPN和ALPNHTTP2协议是从spdy协议发展而来的,无论是spdy还是http2都为了能在HTTPS的环境下工作,发展出来了TLS协议的扩展。他们分别叫做NPN(NextProtocolNegotiation)和ALPN(ApplicationLayerProtocolNegotiation)。他们规定了在TLS协议握手之后,客户端和服务器端进行应用数据通信的协议。其中ALPN可以在客户端首次和服务器端进行握手的时候,就列出客户端支持的应用层数据协议,服务器端直接选择即可,因此可以比NPN少一个交互流程,更加优秀。那么spdy和http2分别支持的协议都有哪些呢?netty提供了一个ApplicationProtocolNames类,在其中定义了各自对应的协议,其中ALPN对应了http2和http1.1,而sydy对应了spdy/1,spdy/2,spdy/3:/** *HTTPv

  • swift底层探索 01 - 类初始化&类结构swift底层探索 01 - 类初始化&类结构

    探索swift可以通过:源码调试,Sil文件,xcode断点调试这些方式来进行探索,除Sil文件这种方式其他的都会在本文中出现。OC底层探索01-找到底层探索的钥匙会有解释。 探索路径同样是参考oc的探索路径,先从类开始。类初始化1.使用Xcodel断点调试创建一个简单的类,开启汇编断点1步骤就是__allocation_init是swift对象初始化入口通过2步骤可以进入下一步(下断点,按住control+↓)swift_allocObject是初始化第二步下断点,按住control+↓进入下一步swift_slowAlloc是初始化第三步下断点,按住control+↓进入下一步malloc_zone_malloc是初始化第四步,在这一步完成内存的分配,最终完成alloc步骤。2.使用源码调试现在通过源码调试来验证一下之前的论点。源码编译方式Swift-5.3.1源码编译.staticHeapObject*_swift_allocObject_(HeapMetadataconst*metadata, size_trequiredSize, size_trequiredAlignmen

  • .NET Core开发实战(第10课:环境变量配置提供程序)--学习笔记

    10|环境变量配置提供程序:容器环境下配置注入的最佳途径环境变量的配置提供程序主要适应场景:1、在Docker中运行时2、在Kubernetes中运行时3、需要设置ASP.NETCore的一些内置特殊配置时环境变量和命令行这两个提供程序在早期是没有容器化的,当时一个操作系统会跑多个应用程序,应用程序注入配置的方式一般都是通过文件或者是命令行的方式来注入的,环境变量当时用的比较少现在在容器化的环境下,有了Docker的隔离能力,就意味着每一个应用程序都相当于跑在一个小型的操作系统下面一样,所以说这个时候Docker提供的环境隔离能力让我们可以使用环境变量来配置应用程序,在Docker和Kubernetes中,会大量使用环境变量,而不是使用命令行来配置基础配置环境变量的配置有如下特点:1、对于配置的分层键,支持使用双下横线"__"代替":"2、支持根据前缀加载在某些操作系统,比如说Linux下面,冒号作为环境变量的Key值是不行的,所以说这里支持用双下划线来代替冒号,也就是说当遇到双下划线的环境变量时,可以认为这是一个分层键环境变量提供程序还支持根据

  • gnomAD 数据库简介

    gnomAD是一个学术联盟组织,这个组织收集和整理了各种大规模的外显子和全基因组测序数据,并面向全世界免费开放。在它的第一个版本中,只包含了外显子测序的数据,称为ExomeAggregationConsortium(ExAc)。官方网址如下:http://gnomad.broadinstitute.org/about目前最新版本为2.0.2,更新于2017年10月3号。数据库中的变异信息都是基于hg19构建的,在该数据库中,也包含了来自不同人群的数据在网站上,可以方便的对基因或者转录本进行检索。在左上角的输入框输出感兴趣的基因或转录本即可,在检索结果中,会给出该基因或转录本相关的变异位点。示例如下http://gnomad.broadinstitute.org/gene/ENSG000001603491.基因的基本信息基因名称,包含的变异位点个数,和其他数据库的链接等信息2.覆盖度信息蓝色代表外显子测序的数据,绿色代表全基因组测序的数据3.变异位点的详细信息变异位点的注释采用的是VEP软件官网上还提供了下载地址,网址如下http://gnomad.broadinstitute.org/

  • Toast 的 Window 创建过程

    Toast的Window创建过程Toast也是基于Window实现,可以定时取消,内部采用了Handler。两种IPC进程方式,分别是NotificationManagerService与NotificationManagerService回调内部的TN接口实现。 它可以自定义view,也可以使用默认的view,默认的就是mNextView。当前view的显示与取消都是一次跨进程通信。也就是show与hide方法。    publicvoidshow(){         if(mNextView==null){             thrownewRuntimeException(&quot;setViewmusthavebeencalled&quot;);         }           INotificationManagerservice=getService();         Stringpkg=mContext.getOpPackageName();         TNtn=mTN;         tn.mNextView=mNextVi

  • 如何使用Sentry管理Hive外部表权限

    温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。1.文档编写目的本文档主要讲述如何使用Sentry对Hive外部表权限管理,并基于以下假设:1.操作系统版本:RedHat6.52.CM版本:CM5.11.13.集群已启用Kerberos和Sentry4.采用具有sudo权限的ec2-user用户进行操作2.前置准备2.1创建外部表数据父目录1.使用hive用户登录Kerberos[root@ip-172-31-8-1411874-hive-HIVESERVER2]#kinit-kthive.keytabhive/ip-172-31-8-141.ap-southeast-1.compute.internal@CLOUDERA.COM [root@ip-172-31-8-1411874-hive-HIVESERVER2]#klist Ticketcache:FILE:/tmp/krb5cc_0 Defaultprincipal:hive/ip-172-31-8-141.ap-southeast-1.compute.internal@CLOUDERA.COM Validsta

  • 我的第一次ChIP-seq实践

    1.软件安装整个过程基本是从零开始,也就是说服务器没有安装任何所需软件。因为我平时会用到Python,所以第一步安装的是Anaconda,版本是Anaconda3-4.4.0-Linux-x86_64.sh.Ananconda是一个用于科学计算的Python发行版,能够方便解决多版本Python并存(后面会看到)、切换以及各种第三方包安装问题(最大的好处)。Anaconda和整个ChIP-seq分析没关系,提到它是因为安装Anaconda后可以用BIOCONDA,能够方便安装管理生物信息软件,无需自己解决软件之间依赖关系。安装本次实践需要的软件,包括fastqc(0.11.5),sra-tools(2.8.1),bowtie2(2.3.2),samtools(1.5),MACS2(2.1.1.20160309),deeptools(2.5.1)condaconfig--addchannelsdefaultscondaconfig--addchannelsconda-forgecondaconfig--addchannelsbiocondacondainstallfastqccondai

  • Vmware Workstation虚拟机繁忙导致无法关机

    大家好,又见面了,我是你们的朋友全栈君。 环境Windows10(1903版本),Ubuntu18.04,VMwareWorkstationPro15。问题描述由于某些不知名的原因(好吧,其实是从windows向虚拟机复制文件时发生不知名错误),导致Ubuntu卡住不动了,而整个虚拟机也无法关掉。解决方法1.首先每打开一个虚拟机会有一个vmwareworkstationvmx.exe进程(如下图),正常关闭虚拟机之后vmwareworkstationvmx.exe进程是会一起关掉的。因此,我们首先可以尝试结束该进程。这也是网上很多博客里面推荐的方法。2.但我在这个地方遇到了问题:就是这个进程根本关不掉!!根本关不掉!!尝试了各种方法都关不掉!!网上有帖子说是1903版本与vmware的兼容性问题,但也没有给出解决方案。3.于是只能通过任务管理器将vmware虚拟机给强行杀掉了。然而这导致了另外一个问题:重启虚拟机时出现如下错误:4.网上很多帖子说是VMwareAuthorizationService服务没有开启,于是我尝试打开服务,发现服务是开的,于是将服务关了重新打开,然后重启虚拟机

  • 腾讯云全栈式风控引擎签名方法调用方式

    签名方法v1简单易用,但是功能和安全性都不如签名方法v3,推荐使用签名方法v3。 首次接触,建议使用APIExplorer中的“签名串生成”功能,选择签名版本为“API3.0签名v1”,可以生成签名过程进行验证,并提供了部分编程语言的签名示例,也可直接生成SDK代码。推荐使用腾讯云API配套的7种常见的编程语言SDK,已经封装了签名和请求过程,均已开源,支持Python、Java、PHP、Go、NodeJS、.NET、C++。 您可以通过APIExplorer的【签名串生成】模块查看每个接口签名的生成过程。 腾讯云API会对每个访问请求进行身份验证,即每个请求都需要在公共请求参数中包含签名信息(Signature)以验证请求者身份。签名信息由安全凭证生成,安全凭证包括SecretId和SecretKey;若用户还没有安全凭证,请前往云API密钥页面申请,否则无法调用云API接口。 1.申请安全凭证在第一次使用云API之前,请前往云API密钥页面申请安全凭证。安全凭证包括SecretId和SecretKey: SecretId用于标识API调用者身份 SecretK

  • 线段树套线段树

    hdu6800 #include<iostream> #include<string.h> #include<queue> #include<stack> #include<map> #include<stdio.h> #include<algorithm> #include<math.h> #include<unordered_map> usingnamespacestd; typedeflonglongLL; typedefpair<int,int>P; constintmaxn=1e5+10; constintmaxm=maxn*18+10,maxl=maxm*8+10; structnode{ LLa[4]; node&operator=(constnode&n2) { a[0]=n2.a[0]; a[1]=n2.a[1]; a[2]=n2.a[2]; a[3]=n2.a[3]; return*this; } }; intpool[maxm]

  • 将博客搬至CSDN

    将博客搬至CSDN:https://blog.csdn.net/zmj_0817

  • JSP利用AJAX实现页面即时校验验证码

    在JSP页面实现验证码校验文章中当时是使用的Servlet类来进行的验证码校验,但是这种方式并不能即时校验,在正常情况下都是直接在用户输入之后就进行校验,这样对用户来说很方便的。AJAX即“AsynchronousJavascriptAndXML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。ajax是一种浏览器异步发起请求。局部更新页面的技术。 jQueryajax详解可参阅:jQuery与Ajax先看效果: 这个刷新验证的原理在JSP页面实现验证码校验已经解释过了,之前说的是跳转到另一个页面进行验证判断用户输入的验证码是否正确。但是这个Ajax的效果是在前端用户输入之后即时进行验证是否正确,并且将相关提示性信息展示在页面。这个实现原理是利用的Ajax的方式进行验证的,这个也是需要一个Servlet程序进行校验判断用户输入的验证码和session对象保存的那个验证码是否一致,如果一致就返回一个yes,不一致就返回no,然后在页面显示这里定义一个Ajax的函数,一方面是是将用户输入的信息提交给Servlet程序,另一方面是对Servlet的返回结果进

  • docker容器中安装vim 、telnet、ifconfig、ping、curl命令

    http://t.zoukankan.com/faithH-p-12018453.html

  • EF 新增数据时提示it has a DefiningQuery and no &lt;InsertFunction&gt; element exists in the &lt;ModificationFunctionMapping&gt; element

    ithasaDefiningQueryandno<InsertFunction>elementexistsinthe<ModificationFunctionMapping>element UnabletoupdatetheEntitySet'Users'becauseithasaDefiningQueryandno<InsertFunction>elementexistsinthe<ModificationFunctionMapping>elementtosupportthecurrentoperation. 检查该Entity对应的表是否没有主键,设置表的主键,确保Entity的主键和表的主键一致

  • 解读mysql主从配置及其原理分析(Master-Slave)

    在windows下配置的,后面会在Linux下配置进行测试,需要配置mysql数据库同步的朋友可以参考下。 1.在主数据库服务器为从服务器添加一个拥有权限访问主库的用户:GRANTREPLICATIONSLAVEON*.*TO'test'@'%'IDENTIFIEDBY'test';(%表示允许所有IP,可设置指定从服务器IP)添加用户后:可在从服务器上用mysql-h127.0.0.1-utest-ptest;来测试是否有权限访问主数据库 2.在主据库配置文件加上:#masterconfigserver-id=1log-bin=mysql-bin 3.在从服务器数据库配置文件:server-id=2master-host=10.0.0.199master-user=testmaster-password=testreplicate-do-db=testmaster-port=3306log-bin=mysql-bin 如果你的一切配置顺利你在从服务器上输入命令:showslavestatus\G成功情况: Slave_IO_Running:yesSlave_SQL_Running:y

  • iOS----------学习路线思维导图

    UI相关   Runtime   OC特性   内存管理   Block   多线程   Runloop       网络相关   设计模式     架构     算法     第三方库  

  • KafkaManager对offset的两种管理方式

    OffsetManager主要提供对offset的保存和读取,每个broker都有一个OffsetManager实例,kafka管理topic的偏移量有2种方式: 1、ZookeeperOffsetManager:调用zookeeper来存储和接收offset Consumeroffset:/consumers/[groupId]/offsets/[topic]/[partitionId]/offsetnumber 2、DefaultOffsetManager:提供消费者offsets内置的offset管理,即把偏移量提交至kafka内部,主要由offsets.storage参数决定,默认为zookeeper。也就是说如果配置offsets.storage=kafka,则kafka会把这种offsetcommit请求转变为一种Producer,保存至topic为“__consumer_offsets”的log里面。 offsets是怎么保存到DefaultOffsetManager? 除了将offset作为logs保存到磁盘上,DefaultOffsetManager维护了一张能快速服

  • JS深浅拷贝复习

    概念:浅拷贝是拷贝堆内存的地址,而深拷贝是拷贝堆内存中的值 JS只提供了一个赋值运算符去拷贝它的地址,JS没有提供给我们去拷贝堆内存中值的方法,我们平时用的Object.assign和展开运算符看似可以实现对象的拷贝,而它们对于对象属性的拷贝也是浅拷贝; 一、实现深拷贝的多种方法: 1.JSON字符串转化 JSON.parse(JSON.stringify(object))复制 2.递归拷贝(用forin对入参obj的keys进行遍历,并一个一个的copy到newobj上) for(letiinobj){ newobj[i]=copy(obj[i]); }复制 二、浅拷贝方法 1.for···in只循环第一层 for(letiinobj1){ obj2[i]=obj1[i]; }复制 2.Object.assign方法 varobj1=Object.assign(obj);复制 3.直接用=赋值 obj1=obj2复制     在实际应用中,比如在点击事件btnClick(item),想要将这个item赋值给v-modle绑定的数据时,就不能使用

  • 关键词

    发布日期2021.5.3 今天老师发布了此项目的第二阶段,这侧跟上次一样也是先设计了一个页面: <!DOCTYPEhtml><html><head><metacharset="utf-8"><title>热词云</title><metaname="renderer"content="webkit"><metahttp-equiv="X-UA-Compatible"content="IE=edge,chrome=1"><metaname="viewport"content="width=device-width,initial-scale=1,maximum-scale=1"><scriptsrc="js/echarts.min.js"></script> <scriptsrc="js/echarts-wordcloud.js"></script> <style> body{font-family:"Lato",sans-

  • 设计模式之依赖倒置原则

    1.1定义 高层模块不应该依赖低层模块,二者都应该依赖其抽象; 抽象不应该依赖细节; 细节应该依赖抽象 1.2问题由来 类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。 1.3解决方案 将类A修改为依赖接口Interface1,类B和类C各自实现接口Interface2,类A通过接口Interface1间接与类B或者类C发生联系,则会大大降低修改类A的几率。 1.4具体分析 依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。抽象指的是接口或者抽象类,细节就是具体的实现类,(iOS中可以理解为抽象就是协议,细节是实现该协议的实现类),使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。 依赖倒置原则的核心思想是面向接口编程,达到解耦的过程。 1.5举例说明 我们用一个例子来说明面向

  • timestamp时间戳的应用(微信小程序开发也一样)

       在微信小程序开发时发现一个timestamp的时间戳的变量比如获取微信运动步数时候   timestamp是如何形成的在JS中是这么形成的 vartimestamp=Date.parse(newDate()); timestamp=timestamp/1000; //当前时间戳为:1505355301 console.log("当前时间戳为:"+timestamp);复制 那么如果获取到timestamp如何转化为时间呢可以这么转化 vartimestamp3=1403058804; varnewDate=newDate(); newDate.setTime(timestamp3*1000); //WedJun182014 console.log(newDate.toDateString()); //Wed,18Jun201402:33:24GMT console.log(newDate.toGMTString()); //2014-06-18T02:33:24.000Z console.log(newDate.toISOStrin

相关推荐

推荐阅读