前端MVVM模式及其在Vue和React中的体现
MVVM相关概念
Mvvm 前端数据流框架精讲
1) MVVM典型特点是有四个概念:Model、View、ViewModel、绑定器。MVVM可以是单向绑定也可以是双向绑定甚至是不绑定
2) 绑定器:声明性的数据和命令,存在于ViewModel之中,让ViewModel和Model二者进行自动或手动通信,接下来的“MVVM在React中对应关系”小节有举例说明。
3) MVVM本质上是M- V-C-VM,它是在MVC的基础上增加了一层VM,只不过C变弱了,被并入到M概念中,VM用于分离V和M,并且让用户避免由于直接操作V层的DOM而带来的繁琐和效率低下,MVVM使开发更高效,结构更清晰,增加代码的复用性。
4) 在不同的GUI(图形用户界面)上进行展示时,Model、Controller、View-Model能够复用,只需把View层进行替换。
5) 在不同类型的UI(用户界面)上进行展示时,Model、Controller能够复用,只需把View-Model、View层进行替换。比如:假设我们开发的是一款针对盲人的应用,那么输出设备或许我们需要考虑使用扬声器来代替显示器,输入设备使用麦克风,这时我们只需将上述的View-Model替换为Audio-Model作为语音模型,将 V(iew)层替换为Audio层用于播放语音和接收语音输入。
6) 个人认为:在基于MVVM框架的项目中,不管是双向数据绑定还是单向数据绑定,你在开发中实际要面对的都是ViewModel和M(odel)层之前的通信,因为V(iew) 和ViewModel层之间的映射和通信都是由框架自动完成的,
MVVM四层结构
1) M(odel)层:模型,定义数据结构。
2) C(ontroller)层:实现业务逻辑,数据的增删改查。在MVVM模式中一般把C层算在M层中,(只有在理想的双向绑定模式下,Controller 才会完全的消失。这种理想状态一般不存在)
3) ViewModel层:顾名思义是视图View的模型、映射和显示逻辑(如if for等,非业务逻辑),另外绑定器也在此层。ViewModel是基于视图开发的一套模型,如果你的应用是给盲人用的,那么也可以开发一套基于Audio的模型AudioModel。
4) V(iew)层:将ViewModel通过特定的GUI展示出来,并在GUI控件上绑定视图交互事件,V(iew)一般由MVVM框架自动生成在浏览器中。
MVVM在React中对应关系
1) M(odel):对应组件的方法或生命周期函数中实现的业务逻辑和this.state中保存的本地数据,如果React集成了redux +react-redux,那么组件中的业务逻辑和本地数据可以完全被解耦出来单独存放当做M层,如业务逻辑放在Reducer和Action中。
2) V(iew)-M(odel):对应组件中的JSX,它实质上是Virtual DOM的语法糖。React负责维护 Virtual DOM以及对其进行diff运算,而React-dom 会把Virtual DOM渲染成浏览器中的真实DOM
3) View:对应框架在浏览器中基于虚拟DOM生成的真实DOM(并不需要我们自己书写)以及我们书写的CSS
4)绑定器:对应JSX中的命令以及绑定的数据,如className={ this.props.xxx }、{this.props.xxx}等等
MVVM的双绑和单绑区别
1) 一般,只有UI表单控件才存在双向数据绑定,非UI表单控件只有单向数据绑定。
2) 单向数据绑定是指:M的变化可以自动更新到ViewModel,但ViewModel的变化需要手动更新到M(通过给表单控件设置事件监听)
3) 双向数据绑定是指念:M的变化可以自动更新到ViewModel,ViewModel的变化也可以自动更新到M
4) 双向绑定 = 单向绑定 + UI事件监听。双向和单向只不过是框架封装程度上的差异,本质上两者是可以相互转换的。
5) 优缺点:在表单交互较多的情况下,单向数据绑定的优点是数据更易于跟踪管理和维护,缺点是代码量较多比较啰嗦,双向数据绑定的优缺点和单向绑定正好相反。
三大框架的异同
1) 三大框架都是数据驱动型的框架
2) vue及angular是双向数据绑定;react是单向数据绑定。React貌似使用的也是Object.defineProperty监控数据,只是没有进一步把表单控件的事件封装进v-model
3) Vuex、Redux都是单项数据绑定的,即M的变化可以自动更新到V,但V的变化必须手动触发事件更新到M,这种单项数据绑定使数据更易于跟踪管理和维护。
4) 未完待续……
Vue双向绑定原理
1) Vue的双向数据绑定是通过Object.defineProperty的get/set对M层数据进行监控,当数据发生变化时,自动更新VM层绑定的数据,而当用户更改了VM层表单控件的数据时,通过v-model自动更新到M层(v-model是对表单控件的事件的封装)
精简示例:
<div id="demo"></div>
<input type="text" id="inp">
<script>
var obj = {}
var demo = document.querySelector('#demo')
var inp = document.querySelector('#inp')
Object.defineProperty(obj, 'name', { // 看起来数据name只是作为数据中转的作用,真正要更新到view层的数据操作在set方法里。
get: function() {
return 0
},
set: function (newVal) {
inp.value = newVal
demo.innerHTML = newVal
}
})
inp.addEventListener('input', function(e) {
obj.name = e.target.value // 给obj的name属性赋值,进而触发该属性的set方法,
})
obj.name = 'fei'// 在给obj设置name属性的时候,触发了set这个方法
</script>
2)我们已经知道Vue是双向数据绑定(通过v-model),Vuex是单向数据绑定,那么问题来了,在基于Vue+ Vuex的项目中,Vuex中的数据是不允许Vue的v-model对其进行更改的,会报错,有如下三种解决方案:
- 依然使用v-model,数据不放进Vuex中,而是放在组件自身的data属性中
依然使用v-model,不过取值不再是Vuex中的数据,而是组件自身的一个computed(getter/setter)或watch,通过computed或watch里的回调来把数据变化提交(commit)到Vuex
组件模板:<template>
<div>
<input type="text" v-model="newName"/>
<p>{{newName}}</p>
</div>
</template>
组件VUE实例:
computed: {
newName: {
get () {
return this.$store.state.name
},
set (val) {
this.$store.commit('changeName', val) //当newName 值发生改变时,提交一个mutation:changeName,用于改变store中的name/
}
}
}
mutation:
changeName (state, val) {
state.name = val
}
- 不使用v-model,通过UI事件监听触发一个回调,然后手动把数据变化提交(commit)到Vuex
3)Vue的双向数据绑定和Vue的prop的单项数据流是两个不同的概念,数据绑定的前提是有数据流,但有数据流不一定有数据绑定。prop的单项数据流是指:prop可以把父组件的数据传递给子组件并且子组件不能对该数据进行直接修改更不能回流到父组件(当然,得益于Vue对所有数据使用了Object.defineProperty,所以prop传递的数据是绑定的,即父组件中该数据一旦发生变化,子组件中的也跟着变化)
前端MVVM模式及其在Vue和React中的体现的更多相关文章
- 在vue或者react中使用express框架
在react 或者 vue项目中使用express框架 1.创建vue或者 react 项目 2.在项目中创建server文件夹,创建server.js //require()方法引入express模 ...
- vue、react中循环遍历为什么会有key,key有什么作用?
先讲一下,vue和react都是在操作虚拟dom,并且根据diff算法进行新旧dom对比,从而更新dom,以vue举例: vue官方文档中写到有 key 的特殊属性主要用在 Vue 的虚拟 DOM 算 ...
- 前端必读2.0:如何在React 中使用SpreadJS导入和导出 Excel 文件
最近我们公司接到一个客户的需求,要求为正在开发的项目加个功能.项目的前端使用的是React,客户想添加具备Excel 导入/导出功能的电子表格模块. 经过几个小时的原型构建后,技术团队确认所有客户需求 ...
- 代理模式及其在spring与struts2中的体现
代理模式 代理模式有三个角色组成: 1.抽象主题角色:声明了真实主题和代理主题的共同接口. 2.代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口. 3.真实主题角色:定义真实的 ...
- 从DOM操作看Vue&React的前端组件化,顺带补齐React的demo
前言 接上文:谈谈我对前端组件化中“组件”的理解,顺带写个Vue与React的demo 上次写完博客后,有朋友反应第一内容有点深,看着迷迷糊糊:第二是感觉没什么使用场景,太过业务化,还不如直接写Vue ...
- angular中的MVVM模式
在开始介绍angular原理之前,我们有必要先了解下mvvm模式在angular中运用.虽然在angular社区一直将angular统称为前端MVC框架,同时angular团队也称它为MVW(What ...
- Vue与React的异同
众所周知,前端现在最火的两个框架是Vue和React了.通过一段时间的学习与项目上的实践,我想通过比较他们之间的异同点来发现以后在项目的技术选型中知道怎么抉择用哪个.有一点说明的是他们各自有自己的优势 ...
- Vue vs React: Javascript 框架之战
https://baijiahao.baidu.com/s?id=1608210396818353443&wfr=spider&for=pc 原文档 正如我们之前提到的,Word ...
- Vue与REACT两个框架的区别和优势对比
VUE和REACT两个JavaScript框架都是当下比较受欢迎的,他们两者之间的区别有那些,各自的优缺点是什么,本文将为你呈现. 简单介绍 除非你最近一直不关注前端的发展,不然你肯定听说过由Face ...
随机推荐
- [SDOI2013]随机数生成器
Description Input 输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数. 接下来T行,每行有五个整数p,a,b,X1,t,表示一组数据.保证X1和t都是合法的页码. 注意 ...
- DMA性能测试
本程序主要用来计算DMA数据读写过程中所花费的总得时间周期,依据公式T=tStart+ceil(L/4)*2+ceil(L/256)*tTransform*2 因为tTransform是一个常量(通常 ...
- Testlink设置
1. Testlink配置修改 1.1. config.inc.php 1.1.1. 日志路径配置 /** * @var string Path to store logs - *for securi ...
- kali linux 通过跑包的方式破解wifi密码
1. wlan0开启monitor mode : airmon-ng start wlan0 2. 查看附近的无线网络 : airodump-ng wlan0mon 3. 抓取无线 ...
- (转) Linux命令详解-date
Linux命令详解-date 原文:https://www.cnblogs.com/Dodge/p/4278292.html 在linux环境中,不管是编程还是其他维护,时间是必不可少的,也经常会用到 ...
- mysql通过sql语句判断某个字段在一张表中是否存在
应用场景: 我有一张表,表里面都是用户用来激活游戏的激活码,当用户在前端页面输入激活码时,要查询数据表中是否有这条激活码,如果有就返回"1",没有则返回"0". ...
- 【异常】SQL Server blocked access to STATEMENT OpenRowset/OpenDatasource
异常错误提示:SQL Server blocked access to STATEMENT OpenRowset/OpenDatasource of component Ad Hoc Distrib ...
- Spring连接数据库
public class Book { private int bookid; private String bookname; private String bookauthor; private ...
- 将SpringBoot默认使用的tomcat替换为undertow
随着微服务的兴起,越来越多的互联网应用在选择web容器时使用更加轻量的undertow或者jetty.SpringBoot默认使用的容器是tomcat,如果想换成undertow容器,只需修改pom. ...
- 零基础逆向工程15_C语言09_位运算
1.汇编中的移位指令 算数移位指令 指令格式:SAL/SAR Reg/Mem, CL/Imm SAL(Shift Arithmetic Left):算数左移 SAR(Shift Arithmetic ...