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

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

最近抽出点时间想弄个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

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>测试VM</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
</head>
<body>
<div id=‘box‘ ao-controller="box">
<div id=‘aa-attr‘ style="background: #a9ea00;width:100px;height:100px;" ao-css-width="w" ao-click=‘click‘ ></div>
<p id=‘aa-text‘>{{ w }}</p>
</div>

<script>

var vm = {}

var bindings = {
w: function(value) {
if (value) {
document.getElementById(‘aa-attr‘).style.width = value + ‘px‘;
} else {
return document.getElementById(‘aa-attr‘).style.width;
}
}
}

var access = function(newValue){
if (newValue) { //set
bindings[‘w‘](newValue);
} else { //get
return bindings[‘w‘]();
}
}

Object.defineProperty(vm, ‘w‘, {
get : access,
set : access,
enumerable : true,
configurable : true
})

vm.w = 300 //设置element.style.width == 300

alert(vm.w)

</script>

</body>
</html>

也就是说

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

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

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

当我们触发  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 如何自动更新依赖映射

时间: 2025-02-01 08:00:20

js架构设计模式——前端MVVM框架设计及实现(一)的相关文章

前端MVVM框架:Knockout.JS(一)

前言 在我们平时开发 Web 应用程序的时候,如果项目不算特别大的话,一般都是拿 jQuery 再配合一些前端 UI 框架就在项目上面应用了.如果页面逻辑稍微复杂的话,那个在写前端 JavaScript 代码时,势必会充斥前大量 jQuery 的选择器的应用.我并不想说它好或不好.只想问一下,有没有更方便的方法呢?有过 WPF 开发经验的同学一定会知道 MVVM(Model View ViewModel) 这种开发模式.它可以很轻松的将 View 与 对应的后端代码隔离开来.使项目易于维护.那么

js架构设计模式——你对MVC、MVP、MVVM 三种组合模式分别有什么样的理解?

你对MVC.MVP.MVVM 三种组合模式分别有什么样的理解? MVC(Model-View-Controller)MVP(Model-View-Presenter)MVVM(Model-View-ViewModel)请大家谈一谈各自的理解吧,对比之下更能明确特征和适用的范围,菜鸟们畅所欲言,老鸟大牛们请多多指点! 2 条评论 按投票排序 按时间排序 10 个回答 王韦恩卑鄙,我编程序,我约. 知乎用户.里德.jogen 等人赞同 只是一点浅见啊 折叠也活该... M-V- X 本质都是一样的

js架构设计模式——理解javascript中的MVVM开发模式

理解javascript中的MVVM开发模式 http://blog.csdn.net/slalx/article/details/7856769 MVVM的全称是Model View ViewModel,这种架构模式最初是由微软的MartinFowler作为微软软件的展现层设计模式的规范提出,它是MVC模式的衍生物,MVVM模式的关注点在能够支持事件驱动的UI开发平台,例如HTML5,[2][3] WindowsPresentation Foundation (WPF), Silverligh

Vue.js前端MVVM框架实战篇

相信大家对vue.js这个前端框架有了一定的了解.想必也想把Vue急切的运用在项目中,看看它的魅力到底有多大?别急,今天我会满足大家的想法. 我们一起来看看“Webpack+Vue”的开发模式相比以往老项目(Gulp+jQuery)的开发模式的魅力在哪里. 一.配置开发环境 1.先安装Node和Webpack 2.建立一个文件夹为:Vue-project,然后初始化生成package.json.运行以下指令: npm init 初始化完成后,添加项目开发所依赖的包 "dependencies&q

js架构设计模式——MVVM模式下,ViewModel和View,Model有什么区别

MVVM模式下,ViewModel和View,Model有什么区别 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就是展现出来的用户界面. 基本上,绝大多数软件所做的工作无非就是从数据存储中读出数据,展现到用户界面上,然后从用户界面接收输入,写入到数据存储里面去.所以,对于数据 存储(model)和界面(view)这两层,大家基本没什么异议.但是,如何把model展现到view上,以及如何把数据从view写入到m

前端之框架设计

项目系统集众人之期待,人来人往的变动中,还能够在前端各色人等通力合作下构建出一个中级复杂程度的业务系统,有坚持,有妥协,有苦劳.个中滋味非经历过的人无法感受,如同创业之初,无数期待于一身,而后各种时间,精力,人员变动种种限制,有人会放弃,有人漠不关心,有人选择主动离开,然而项目要继续,要对得起自己更要对得起一同奋斗的人. 创新 -- 守旧 之辩 大浪淘沙,留下来的不一定是金子.前端各种作死的概念翻新,各种新框架层出不穷,选择合适的框架不仅仅是玩具式的尝鲜,更要考虑的是团队之间的协作和稳定的性能以

前端Mvvm QC 上传了测试版

QC是一个前端MVVM框架,适合用来构建复杂的业务逻辑 项目地址:https://github.com/time-go/qc 技术支持QQ群:330603020 QC特点: 1.良好的浏览器兼容性(兼容IE8) 2.强大的组件化支持 3.卓越的性能 4.数据智能补齐5.灵活的自定义事件 6.自动特殊字符转义 QC依赖哪些文件 大家把代码当下来后 js文件  qc.js 就是我们要引用的文件  event.js 是对移动端事件tap和longtap的扩展这个可以不易用 tool文件夹   inde

vue.js学习笔记(一):什么是mvvm框架,vue.js的核心思想

一:MVVM框架 MVVM框架的应用场景:  1.针对具有复杂交互逻辑的前端应用 2.提供基础的架构抽象 3.提供ajax数据持久化,保证前端用户体验 二:vue.js的核心思想 (一):数据驱动 (二):数据响应原理 (三):组件化 (四)组件设计原则 1:页面上每个独立的可视/可交互区域视为一个组件 2:每个组件对应一个工程目录,组件所需要的各种资源在这个目录下就近维护 3:页面只不过是组件的容器,组件可以嵌套自由组合形成完整的页面

细说Android框架设计三剑客MVC、MVP和MVVM

最近几年的移动端开发越来越火,功能越来越强大,处理业务越来越复杂,因此对系统扩展性的要求越来越高.而为了更好地进行移动端架构设计,我们最常用的就是MVC和MVP,今天本篇博客就和大家一起聊一聊这两种框架设计. MVC框架 MVC的定义 MVC (Model-View-Controller):M是指逻辑模型,V是指视图模型,C则是控制器.使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式,而C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新,这与<设计模式>