前端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 ...
随机推荐
- Codeforces 1167F(计算贡献)
要点 容易想到排序,然后对于每个数: 人的惯性思维做法是:\(a[i]*(rank1的+rank2的+-)\).然而解法巧妙之处在于直接把所有的加和当成一个系数,然后先假装所有情况系数都是1,接着往上 ...
- bzoj1014: [JSOI2008]火星人prefix splay+hash
我写的代码好像自古以来就是bzoj不友好型的 本地跑的比std快,但是交上去巧妙被卡 答案...应该是对的,拍了好久了 #include <bits/stdc++.h> #define M ...
- NET Core使用Quartz
NET Core使用Quartz 一.前言运用场景 Quartz.Net是一个强大.开源.轻量的作业调度框架,在平时的项目开发当中也会时不时的需要运用到定时调度方面的功能,例如每日凌晨需要统计前一天的 ...
- 值类型 VS 引用类型~
问 题 值 类 型 引 用 类 型 这个类型分配在哪里? 分配在栈上 分配在托管堆上 变量是怎么表示的? 值类型变量是局部复制 引用类型变量指向被分配得实例所占的内存 基类型是什么? 必须 ...
- SQL SERVER 同一个表并且是同一个时间字段进行相减
表AID NUM TIEM1 10 2012-06-10 10:10:002 20 2012-06-10 20:10:003 20 2012-06-10 20:10:004 10 2012-06-10 ...
- 策略模式和php实现
策略模式: 策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换.策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy). 策略模式 ...
- Generator 和 函数异步应用 笔记
Generator > ES6 提供的一种异步编程解决方案 > Generator 函数是一个状态机,封装了多个内部状态.还是一个遍历器对象生成函数.返回<label>遍历器对 ...
- springmvc学习经验
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面.Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块.使用 Spring ...
- 如何在cmd查看文件内容的md5值
在cmd下进入 要查看的文件目录 默认目录是c,切换到其他盘符例如: C:\D: 就会切换到D盘 D:\ 然后输入命令 certutil -hashfile 文件名称.文件类型 MD5 如 cert ...
- ABAP和Java单例模式的攻防
ABAP CLASS zcl_jerry_singleton DEFINITION PUBLIC FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES i ...