前端MVVM框架设计及实现(一)

时间:2023-02-27 18:56:33

最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造*写一个简单的MVVM框架了

借鉴的自然还是从正美的avalon开始了,我记得还是去年6月写过一个系列的avalon源码分析的,不过那时候0.7版本,不够健全,现在已经好太多了

 

框架是面向一个领域,提供一套解决方案,那么我们用前端的MVVM能为我们带来什么便利?

  • 关注点分离
  • 操作数据即操作DOM
  • 动态模板

关注点分离是MVVM与身俱来的,操作数据即操作DOM,是VM中的访问器带来的,动态模板是流程绑定实现的。

关于MV*的讨论太多了,这里不在讨论,我们重点就是分析如何实现前端MVMM框架

Avalon 地址 https://github.com/RubyLouvre/avalon

 


学会MVVM需要先会哪些东西?

1. javascript语言基础(作用域,原型链,闭包等等)

2. 简单设计模式,基本的数据结构

3. 阅读或者写过jQuery源码

为什么要这样说呢,因为avalon就是这些东东的综合体!

 


我是以avalon为蓝本,按照作者是思路模仿实现的,当然avalon的代码有4000多行,新手如果去学习的话估计无从下手,也力不从心

为什么呢?简单的说实现的手段有点另类,写的代码有点狂野(请原谅我不知道如何形容),不过用户体验倒是不错!

简单的看下代码结构

<div ms-controller="box">
<div style=" background: #a9ea00;" ms-css-width="w" ms-click="click"></div>
<p>{{ w }}p>
</div>
<script>
avalon.define("box", function(vm) {
vm.w = 100;
vm.click = function() {
vm.w = parseFloat(vm.w) + 10;
}
})
</script>

针对这个代码结构,我们要明白:

 

1:为什么要自定义大量标记(声明式绑定)

这就是MVVM 最原始的意义,数据逻辑展现分离。表现就是 数据 js逻辑代码 htmlcss展现

所以再HTML里加结构是自然而然的事情,如果html都用js生成,那就跟mvvm搭不上边

 

2:avalon.define里面为什么不需要操作dom?

在MVVM中,数据是核心,由于VM与V之间的双向绑定,操作了VM中的数据(当然只能是监控属性),就会同步到DOM,我们透过DOM事件监控用户对DOM的改动,也会同步到VM。

 


本章我们就实现第一步:搭建基本的分层结构,实现双向通知机制

第一版实现:300行代码,请对照分析看源码 https://github.com/JsAaron/aaMVVM

针对上面2个问题,我们看看如何才能做到操作数据即操作dom呢?

简单的说一下实现是思路:大家可以down下git的aaMVVM对照下,比原版的4000行代码友爱多了!

 

我们知道在MVVM中,M只是一个过客,它与其他表示业务状态的东西融入VM(ViewModel)中。ViewModel是一个状态的集合,当然还拖家带口监控着大量的回调

所以ViewModel就承载的几乎所有的功能,在avalon中ViewModel就包含所有的数据与方法的定义,沟通着V与M,起到承上启下的作用~

 


视图模型如何与数据跟视图关联起来?

通过avalon.define定义的vm中的属性与方法都与对应的html结构中的标记有映射关系,所以改变vm中的数据与之关联的dom就会自动刷新

分析下

vm.w = 100

当模型的数据改变为100时,对应的视图中div的宽度为100, 文本<p>100</p>  ,可见修改一个数据在同一个控制器内与之关联的2个映射动作都将会修改

一个是css操作,一个是text赋值

从这个操作我们可以大胆推测下vm.v中应该有一个列表,记录了当前控制器下对应的映射操作(多个)

为了实现set与get方法,avalon也类似emberjs,采用了Object.defineProperty

我用最简单的代码模拟下实现

测试VM

{{ w }}

也就是说

vm.w = 100  即要修改style也要修改p,就是一对多的关联方式

所以在avalon中针对每一个监控属性,都会生成set与get的访问控制器,那么在每一个监控属性的访问控制器里面都会有一个

accessor[subscribers] = [] //订阅者数组,这样的东东来存放与之相关的依赖

前端MVVM框架设计及实现(一)

当我们触发  vm.w = 100时,就会触发w:set方法,取出accessor[subscribers]中的依赖,从而各执执行,这样就实现了依赖执行了

对应的方法:自动更新自身的依赖

//通知依赖于这个访问器的订阅者更新自身
function notifySubscribers(accessor) {
var list = accessor[subscribers]
if (list && list.length) {
var args = [].slice.call(arguments, 1)
for (var i = list.length, fn; fn = list[--i];) {
var el = fn.element
fn.handler(fn.evaluator.apply(0, fn.args || []), el, fn)
}
}
}

 


上面只是简单的思路,真正实现的时候真要做到大而全的框架,考虑的问题可不是那么简单的事

1 框架是怎么解释声明式绑定的语法

2 如何把解析后的语法生成对应的处理句柄

3 用户的定义如何生成vm模型

4 如何收集这些依赖

5 如何自动更新依赖映射

 

GitHub上会同步更新最新的实现,。。。敬请关注~

Fork https://github.com/JsAaron/aaMVVM

前端MVVM框架设计及实现(一)的更多相关文章

  1. 前端MVVM框架设计及实现(二)

    在前端MVVM框架设计及实现(一)中有一个博友提出一个看法: “html中使用mvvm徒增开发成本” 我想这位朋友要表达的意思应该是HTML定义了大量的语法标记,HTML中放入了太多的逻辑,从而增加了 ...

  2. js架构设计模式——前端MVVM框架设计及实现(二)

    前端MVVM框架设计及实现(二) 在前端MVVM框架设计及实现(一)中有一个博友提出一个看法: “html中使用mvvm徒增开发成本” 我想这位朋友要表达的意思应该是HTML定义了大量的语法标记,HT ...

  3. js架构设计模式——前端MVVM框架设计及实现(一)

    前端MVVM框架设计及实现(一) 最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造*写一个简单的MVVM框架了 借鉴的自然还是从正美的avalon开始了,我 ...

  4. 前端MVVM框架设计及实现

    最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造*写一个简单的MVVM框架了 借鉴的自然还是从正美的Avalon开始了,我2013年写过一个关于MVC MV ...

  5. 轻量级前端MVVM框架avalon - 初步接触

    迷你简单易用的MVVM框架 avalon的介绍http://rubylouvre.github.io/mvvm/ 按照作者的介绍,在HTML中添加绑定,在JS中用avalon.define定义View ...

  6. 前端MVVM框架avalon - 模型转换1

    轻量级前端MVVM框架avalon - 模型转换(一) 接上一章 ViewModel modelFactory工厂是如何加工用户定义的VM? 附源码 洋洋洒洒100多行内部是魔幻般的实现 1: fun ...

  7. 前端MVVM框架:Knockout&period;JS(一)

    前言 在我们平时开发 Web 应用程序的时候,如果项目不算特别大的话,一般都是拿 jQuery 再配合一些前端 UI 框架就在项目上面应用了.如果页面逻辑稍微复杂的话,那个在写前端 JavaScrip ...

  8. 不要听吹牛逼什么前端MVVM框架就是好,其实都是一帮没学好分层设计的搞出来的,让你彻底看清前端MVVM的本质

    最近前端圈子里面,发现大家都在热炒概念,什么knockout,angularJs,都被捧成神了,鄙人不才,最近心情也不好,特地写这篇文章来找骂 写代码的码农都知道,Java社区虽然不是一个提出分层思想 ...

  9. 轻量级前端MVVM框架avalon - 执行流程2

    接上一章 执行流程1 在这一大堆扫描绑定方法中应该会哪些实现? 首先我们看avalon能帮你做什么? 数据填充,比如表单的一些初始值,切换卡的各个面板的内容({{xxx}},{{xxx|html}}, ...

随机推荐

  1. 0909 a newbeginning

    操作系统无意是所有计算机系各专业的基础,如果不懂这门课程的知识,大学四年计算机可以说是白读了. 这学期很荣幸能上MISSDU的操作系统,我也希望能学到关于操作系统的知识,以至于丰富自己的专业知识. 下 ...

  2. mysql常用命令(3)

    一.启动与关闭 1.1 Linux下启动mysql 的命令: a. rpm包安装:service mysqld start b. 源码包安装:/usr/local/mysql/bin/mysqld_s ...

  3. shadowColor表示阴影颜色,shadowBlur表示模糊等级

    绘制之前的准备工作: 1.在body中加入canvas标签,设置它的id.width.height,当然也可以动态设置它的宽高. <canvas id="mycanvas" ...

  4. 使用RMAN对控制文件进行restore

    控制文件的默认备份格式是: c-IIIIIIIIII-YYYYMMDD-QQ 其中: c:表示控制文件 IIIIIIIIII:表示DBID YYYYMMDD:备份的时间戳 QQ:16进制的序列号,从0 ...

  5. 【原】window上安装elasticserach

    [window上安装elasticserach] 系统环境:2008R2 x64测试安装用的服务器IP:192.168.12.52elasticsearch版本:2.3.4JDK版本:jdk 1.8. ...

  6. middlewares in GCC

    Our GCC is a project developed by React that makes it painless to create interactive UIs. Design sim ...

  7. 为什么我们要使用ssh框架技术,及感想

    前言: 在公司从C++转向Java Web方向大概有3个月(11月初-1月底)了.三个月前对Java和Web还几乎是零基础.然后从安装Eclipse,MySQL,tomcat开始,到学习HTML/CS ...

  8. 终止TTask&period;Run启动的线程

    unit Unit15; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, Syste ...

  9. Chrome 插件编写日记

    Chrome 插件,你可以理解为打开了一个网页,但是里面只有前端语言,JavaScript, HTML + css 但是有一点区别的是,它是有一个名字为 manifest.json 的配置文件的,里面 ...

  10. Windows 如何远程登陆 Server 的 jupyter

    jupyter 安装就不用赘述了,本示例以 Putty 为例,展示如何从本地 windows 系统调用远程的 jupyter notebook 并且在本地 Chrome 中打开的方法 1. 首先,ss ...