一个只有十行的精简MVVM框架(下篇)
本文来自网易云社区。
让我们来加点互动
前面学生信息的身高的单位都是默认m
,如果新增一个需求,要求学生的身高的单位可以在m
和cm
之间切换呢?
首先需要一个变量来保存度量单位,因此这里必须用一个新的Model:
const tk = {'first-name': 'Jessica','last-name': 'Bre','height': 180,'weight': 70, } const measurement = 'cm'
为了让tk
更方便的被其他模块重用,这里选择增加一个measurement
数据源,而不是直接修改tk
。
在视图部分要增加一个radio单选表单,用来切换身高单位。
const createList = function(kvPairs){const createListItem = function (label, content) {const li = document.createElement('li')const labelSpan = document.createElement('span')labelSpan.textContent = labelconst contentSpan = document.createElement('span')contentSpan.textContent = contentli.appendChild(labelSpan)li.appendChild(contentSpan)return li}const root = document.createElement('ul')kvPairs.forEach(function (x) {root.appendChild(createListItem(x.key, x.value))})return root } const createToggle = function (options) {const createRadio = function (name, opt){const radio = document.createElement('input')radio.name = nameradio.value = opt.valueradio.type = 'radio'radio.textContent = opt.valueradio.addEventListener('click', opt.onclick)radio.checked = opt.checkedreturn radio}const root = document.createElement('form')options.opts.forEach(function (x) {root.appendChild(createRadio(options.name, x))root.appendChild(document.createTextNode(x.value))})return root } const createToggleableList = function(vm){const listView = createList(vm.kvPairs)const toggle = createToggle(vm.options)const root = document.createElement('div')root.appendChild(toggle)root.appendChild(listView)return root }
接下来是ViewModel
部分,createToggleableList
函数需要与之前的createList
函数不同的参数。因此,对View-Model结构重构是有必要的:
const createVm = function (model) {const calcHeight = function (measurement, cms) {if (measurement === 'm'){return cms / 100 + 'm'}else{return cms + 'cm'}}const options = {name: 'measurement',opts: [{value: 'cm',checked: model.measurement === 'cm',onclick: () => model.measurement = 'cm'},{value: 'm',checked: model.measurement === 'm',onclick: () => model.measurement = 'm'}]}const kvPairs = [{key: 'Name: ',value: model.student['first-name'] + ' ' + model.student['last-name']},{key: 'Height: ',value: calcHeight(model.measurement, model.student['height'])},{key: 'Weight: ',value: model.student['weight'] + 'kg'},{key: 'BMI: ',value: model.student['weight'] / (model.student['height'] * model.student['height'] / 10000)}]return {kvPairs, options} }
这里为createToggle
添加了ops
,并且将ops
封装成了一个对象。根据度量单位,使用不同的方式去计算身高。当任何一个radio
被点击,数据的度量单位将会改变。
看上去很完美,但是当你点击radio标签的时候,视图不会有任何改变。因为这里还没有为视图做更新算法。有关MVVM
如何处理视图更新,那是一个比较大的课题,需要另辟一个博文来讲,由于本文写的是一个精简的MVVM
框架,这里就不再赘述,并用最简单的方式实现视图更新:
const smvvm = function (root, {model, view, vm}) {let m = {...model}let m_old = {}setInterval( function (){if(!_.isEqual(m, m_old)){const rendered = view(vm(m))root.innerHTML = ''root.appendChild(rendered)m_old = {...m}}},1000) } smvvm(document.body, {model: {student:tk, measurement}, view: createToggleableList, vm: createVm })
上述代码引用了一个外部库lodash
的isEqual
方法来比较数据模型是否有更新。此段代码应用了轮询,每秒都会检测数据是否发生变化,有变化了再更新视图。这是最笨的方法,并且在DOM结构比较复杂时,性能也会受到很大的影响。还是同样的话,本文的主题是一个精简的MVVM框架,因此略去了很多细节性的东西,只把主要的东西提炼出来,以达到更好的理解MVVM模式的目的。
MVVM框架的诞生
以上便是一个简短精简的MVVM风格的学生信息的示例。至此,一个精简的MVVM框架其实已经出来了:
/** * @param {Node} root * @param {Object} model * @param {Function} view * @param {Function} vm */ const smvvm = function (root, {model, view, vm}) {let m = {...model}let m_old = {}setInterval( function (){if(!_.isEqual(m, m_old)){const rendered = view(vm(m))root.innerHTML = ''root.appendChild(rendered)m_old = {...m}}},1000) }
什么?你确定不是在开玩笑?一个只有十行的框架?
请记住: 框架是对如何组织代码和整个项目如何通用运作的抽象。
这并不意味着你应该有一堆代码或混乱的类,尽管企业可用的API列表经常都很可怕的长。但是如果你研读一个框架仓库的核心文件夹,你可能发现它会出乎意料的小(相比于整个项目来说)。其核心代码包含主要工作进程,而其他部分只是帮助开发人员以更加舒适的方式构建应用程序的附件。有兴趣的同学可以去看看cycle.js,这个框架只有124行(包含注释和空格)。
总结
此时用一张图来作为总结再好不过了!
本文来自网易云社区,经作者顾静授权发布。
了解网易云 :
网易云官网:https://www.163yun.com
网易云社区:https://sq.163yun.com/blog
网易云新用户大礼包:https://www.163yun.com/gift
更多网易研发、产品、运营经验分享请访问网易云社区。
转载于:https://www.cnblogs.com/163yun/p/9506056.html
一个只有十行的精简MVVM框架(下篇)相关推荐
- 一个类似JQuery的精简版框架
最近看了一段关于javascript的视频,讲的是一个VQuery.js的框架,这是一个类JQuery框架的缩水版,里面有一些通用的方法,这里记录了下来.VQuery方法是这个框架主要的方法,它接收三 ...
- 疯狂 java轻量级框架_ViewModel从未如此清爽 - 轻量级WPF MVVM框架Stylet
Stylet是我最近发现的一个WPF MVVM框架, 在博客园上搜了一下, 相关的文章基本没有, 所以写了这个入门的文章推荐给大家. Stylet是受Caliburn Micro项目的启发, 所以借鉴 ...
- android mvvm流程图,MVVM框架模式详解
MVVM 定义 MVVM 是 Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对 View 和 ViewModel 的双向数据绑定,这使得 ViewMod ...
- android 开源框架mvvm,relight: A light MVVM framework for Android. 一个轻量级的安卓MVVM框架...
优势 稳定 减少内存泄漏:新手很容易在线程切换的地方写出导致内存泄漏的代码,但如果把线程切换交给框架来做,出错的概率就大大降低. 减少 crash:根据我的开发经历,大部分 crash 都是空指针导致 ...
- 依赖注入[5]: 创建一个简易版的DI框架[下篇]
为了让读者朋友们能够对.NET Core DI框架的实现原理具有一个深刻而认识,我们采用与之类似的设计构架了一个名为Cat的DI框架.在<依赖注入[4]: 创建一个简易版的DI框架[上篇]> ...
- Android MVVM封装,MVVM: 这是一个android MVVM 框架,基于谷歌dataBinding技术实现
MVVM 这是一个android MVVM 框架,基于谷歌dataBinding技术实现.dataBinding 实现的 V 和 VM的关联:使用IOC架构实现了 M 和 V的关联. 框架具有以下功能 ...
- android mvvm官方文档,MVVM: 这是一个android MVVM 框架,基于谷歌dataBinding技术实现
MVVM 这是一个android MVVM 框架,基于谷歌dataBinding技术实现.dataBinding 实现的 V 和 VM的关联:使用IOC架构实现了 M 和 V的关联. 框架具有以下功能 ...
- android+捕获google账户+cancel按钮,MVVM: 这是一个android MVVM 框架,基于谷歌dataBinding技术实现...
MVVM 这是一个android MVVM 框架,基于谷歌dataBinding技术实现.dataBinding 实现的 V 和 VM的关联:使用IOC架构实现了 M 和 V的关联. 框架具有以下功能 ...
- 小白前端之路:手写一个简单的vue-router这几年,好像过的好快,怀念我的大学生活。 - 连某人 大三实习生,之前写过简单MVVM框架、简单的vuex、但是看了vue-router的源码(看了
这几年,好像过的好快,怀念我的大学生活. 连某人 大三实习生,之前写过简单MVVM框架.简单的vuex.但是看了vue-router的源码(看了大概)之后就没有写,趁着周末不用工作(大三趁着不开学出来 ...
最新文章
- MATLAB【十四】————遍历三层文件夹操作
- eclipse从svn检出项目
- 特征值 与特征向量(机器学习算法原理与实践)
- hashlist java_java中集合类HashSet、ArrayList、LinkedList总结
- 强网杯2021 CipherMan (内存取证分析)
- Python业务分析实战|共享单车数据挖掘
- android通知图标变白色,android 7.0通知图标出现白色方块
- 专升本c语言网课听谁的好_都说塑钢泥比玻璃胶好,填缝永不变黑,师傅却说不好用,听谁的?...
- 安卓开发入门到精通!免费Android高级工程师学习资源,系列篇
- java 加锁_Java并发之synchronized深入
- AI开发者顶会,这一次,人人都可以参加!
- 旧版台式计算机,7年前老电脑开机比拼 Windows8秒杀XP
- 一分钟了解contextlib模块
- 关于电量采集芯片(库仑计)DS2781相关操作及配置
- Juniper-SRX-基于域控认证的用户防火墙
- 同城货运主导全新商流体系:智慧物流成胜负关键?
- 4年亏损超6亿,摩贝化学赴美上市能否输血成功?
- 快速查看电脑内存型号方法
- DPR300 超声波高压脉冲发生/接收器
- git ------ git clone方法总结(可直接加账户和密码)