本文将深入介绍一下avalon的运作机理及与jQuery的区别。
许多人都知道MVVM是MVC的一个变体,但那些MVC是在后端的,包括微软的WPF,这意味着这个V与我们前端接触到的V差别很大。后端的V就是使用各种模板拼凑成一个静态页面给前端。而前端的V在JSer的眼中就是一个巨大的DOM树,要考虑加载时间,渲染顺序,浏览器对HTML的容错与修复,浏览器的默认事件,新图片与节点增删移动引起的reflow,是活生生的。前端的V就是一个DOM的世界,而后端就是字符串!
M,模型,一个数据体,用于填允我们的页面,通常PHP交给我们时数据已经填好了,想改变,就要再发出请求,然后通过jQuery寻找节点,修改它的innHTML与innerText。当然DOM操作是非常繁锁的,什么透明度,背景,位置等CSS属性我们都需要通过操作类名来修改。我们有时忙乎于这些细节,而把我们业务混在其中了。因此调试时,业务好了,但样式坏了,样好修好,这时务业又爆开了……
在MVVM中,M只是一个过客,它与其他表示业务状态的东西融入VM(ViewModel)中。ViewModel是一个状态的集合,当然还拖家带口监控着大量的回调。状态听起来是个深奥的概念,其实就是一个开关。比如if(aaa){}语句中的aaa,就是表示true与false,switch(bbb){}语句,它表示有多个值的状态,就像有人幼年,童年,少年,青年,中年,老年这几个阶段,它们都指向同一个东西。jQuery是什么管理状态的呢?比如我做个切换卡,点一下,这个面板显示,其他面板隐藏,它里面就使用了大量的hasClass来检测元素有没有某个表示显示的类名,有就隐藏,其他关闭。
$(button).click(function(){ var index = $(this).index(); $(panel).eq(index).show().siblings().hidden() })
而在MVVM中,只要妥善绑定好视图,直接像 vm.activated = 1,1 为你要显示的按钮,这样切换卡就切换过去,包括你点的按钮上的类名。你可以被动地在事件回调修改VM中的属性,也可以直接对VM中属性,无论哪一种,基本上很少看到DOM代码。
<div ms-controller="tabs" > <div ms-each-tab="tabs" class="triggers"> <a href="###" class="trigger" ms-class-selected="activated === $index" ms-click="activate">{{tab.title}}</a> </div> <div ms-each-tab="tabs" > <div class="panel" ms-visible="activated === $index">{{tab.panel}}</div> </div > </div >
avalon.ready(function() { avalon.define("tabs", function(a) { a.tabs = [ //tabs上的title, panel来源自后端的数据库,如果PHPer帮你把整个页面搞定,这个就不需要 { //只要下面的activated 与 activate title: "aaaa", panel: "aaaa panel" }, { title: "bbbb", panel: "ffffffffffffffffffff" }, { title: "cccc", panel: "cccc panel" } ] a.activated = 0 //这个是我们的务业产生的变量, a.activate = function(){ a.activated = this.$scope.$index;//这是我们的业务,就是改一下activated 的值。 } }) avalon.scan(); })
在MVVM中,数据是核心。而jQuery则以DOM为核心。而DOM只是HTML在JS的世界的抽象,是一个很易变的东西。因此如果业务代码遍历选择器表达式会非常难维护。但不可否认,jQuery是操作DOM的王者,让我们操作DOM顺手拈来。但如果不让你操作DOM,不是更好吗?就像jQuery不让你用getElementById,getElementsByTagName, querySelecterAll,大家都不知道里面有多少坑,短短几个字母$(expr)是背后sizzle选择器引擎1700行的实现!!!!jQuery其实是在用户代码与原生API中提供一层厚厚的粘合层,因此摸起来光溜溜。在MVVM中,DOM操作基本是水下运作了。由于VM与V之间的双向绑定,操作了VM中的数据(当然只能是监控属性),就会同步到DOM,我们透过DOM事件监控用户对DOM的改动,也会同步到VM。DOM隐形了,就像软件公司,到处跑出来活动的是业务员与不写代码的经理老总,程序员全部关起来加班!虽然这比喻有点残酷,但这正体现了各司其职的威力。能说会道去拉风投接单子没什么不妥,喜欢呆在电脑前的就让他呆吧。jQuery的世界就是一个混乱的公司,全能的程序员什么都做。
为了各司其职,必须有良好的分层。MVVM划分三层,M,VM,V,M是原始数据,用于转换为VM,VM管理状态与绑定回调,V通过绑定得到VM的状态与回调,渲染页面,绑定事件,切换类名,什么脏活都揽了——但用户只需要声明。avalon与其他前端MVVM框架最大的不同是,VM是用ecma262v5的新API, Object.defineProperties生成的一个充满访问器的对象,这样的对象,能通过用户对它的属性的读写,触发定义时的getter, setter函数。getter, setter对rubyer, pythoner, C#er应该很熟悉,我就不展开了。旧式IE,avalon利用VBScript的类实例,它也存在其他语言的访问器。不过,VBS对象不像JS对象那样随意添加新属性,删除已有属性,因此我们就无法监后添加的新属性。Object.defineProperties也一样,它能处理的属性也只是它定义时的属性,想监控后来的,需要再调用一次Object.defineProperties。尽管如此,也比其他MVVM框架魔幻多了。
如果监控属性不够用,可以用监控数组,计算属性与$watch, $fire方法。
比如下面一个监控数组fruits :
var model = avalon.define("form", [], function(vm) { vm.fruits = [{name: "xxx"}, {name: "yyy"}, {name: "ooo"}, {name: "ppp"}] vm.numbers = [1, 2, 3, 4] });
被改造成如下样子,我们可以在chrome的控制台看到它的正身:
首先这个数组的sort, splice, push, shift, reverse, pop, unshift等方法被重写,并添加了contains, ensure, remove, removeAll, removeAt, clear, upeate, set等方法, 还有表示它是个监控数组的isCollection, $id等属性。它内部四个对象也转换子ViewModel,name转换为监控属性,每个name在内部都有个set, get方法。我们只需要aaa.name = "xxx"; var d = aaa.name就能调用它们。而不像knockout那样全部转为真正的函数。
为了能互相同步,要写你绑定在页面上的字段为监控属性,如果它是一个复杂数据的某个子属性的子属性,那么至少也保持最后那个是监控属性,否则无法同步
var model = avalon.define("test", [], function(vm) { vm.fruits = [{name: "xxx"}, {name: "yyy"}, {name: "ooo"}, {name: "ppp"}] vm.numbers = [1, 2, 3, 4] vm.lang = "ruby" }); //在这里,我们可以监听当中的name 即{{ fruits[0].name }}, 但无法监控numbers中的元素,因为数字无法作为Object.defineProperty的第一个参数传入,因此转换不了。 // Object.defineProperty(object, propertyname, descriptor);//obj必须为对象
根据这思路,整个转换过程为:
Object.defineProperty(vm, "fruits", {set:fn, get: fn})//事实上,avalon是使用Object.defineProperties同时处理! Object.defineProperty(vm, "numbers ", {set:fn, get: fn}) Object.defineProperty(vm, "lang", {set:fn, get: fn}) Object.defineProperty(fruits[0], "name", {set:fn, get: fn}) Object.defineProperty(fruits[1], "name", {set:fn, get: fn}) Object.defineProperty(fruits[2], "name", {set:fn, get: fn}) Object.defineProperty(fruits[3], "name", {set:fn, get: fn})
比如像下面这样的复杂结构,avalon就有点为不从心了。因此不要直接把Model的数据整个扔到ViewModel中,你懒,avalon也懒——它只是监听对象属性的变化,数组长度与位置的变化。不会监听纯字符数组与纯字母数组。即便对于angular,google拥有这么多算法帝,它也要求你使用$watch来处理,而不是直接放在VM中就一了百了。emberjs, knockout就更呛了。要用好ViewModel必须对原始数据进行加工。
var model = avalon.define("class", [], function(vm) { vm.data = { rows: [ { "d": [ "PO00000078", "ABC" ] }, { "d": [ "PO00000079", "DEF" ] } ] } })
如果一定要监听,只能使用each绑定,你这个对象在层次结构上有多少个数组,就应该用多少次each绑定。比如这个对象,就有rows, d这个数组,需要用上两次。
var model = avalon.define("class", [], function(vm) { vm.data = { rows: [ { "d": [ "PO00000078", "ABC" ] }, { "d": [ "PO00000079", "DEF" ] } ] } })
<ul ms-each-row="rows" ms-controller="class"> <li ms-each-td="row.d"> {{td}} </li> </ul>
生成的结构如下:
不过真正强大的是各种绑定,帮你打包所有DOM操作。可详看这里的API说明。
MVVM是前端未来的发展方向,微软有knockout, winjs等MVVM框架; 著名的.Net组件开发公司 Telerik 推出了一套基于 jQuery的MVVM UI库kendoui; 谷歌组织开发angular;jQuery, rails,Sproutecore,Merb,Handlebars这几个著名框架的核心成员,超级大牛Yehuda Katz推出了emberjs!
外国有文章介绍,使用了AngularJS(MVVM)代替(Backbone),代码减少了一半。
http://www.localytics.com/blog/2013/angularjs-at-localytics/
现在园子里有不少人在用knockout与angular,在ruby china中,最爱玩新技术的rubyer最近也密集提到它们。毫无疑问,这是非常有吸引力,极具生产力的东西。
avalon作为现在最迷你的MVVM框架,易用性也堪称一绝,绝对可以一试。
相关推荐
本文将深入探讨基于司徒大神创建的轻量级MVVM框架——Avalon2.0,如何搭建一个简易的脚手架。Avalon2.0是一个成熟的JavaScript框架,它为开发者提供了构建复杂前端应用的能力,尤其适用于单页应用程序(SPA)的开发...
一个迷你框架
本项目“Android mvvm 框架,最流行的mvvm demo”旨在提供一个无bug的示例,帮助开发者深入理解并实践MVVM框架在Android应用中的应用。 MVVM模式源于微软的WPF开发,近年来在Android开发中逐渐流行,它通过解耦视图...
**WPF轻量级MVVM框架入门2.1.2** 在Windows Presentation Foundation(WPF)开发中,MVVM(Model-View-ViewModel)模式是一种常见的设计模式,它有助于实现应用程序的视图与业务逻辑之间的解耦。MVVM通过数据绑定、...
**MVVM 框架详解** MVVM(Model-View-ViewModel)框架是现代软件开发中的一个重要概念,尤其在移动应用和Web应用开发中广泛使用。这个框架模式旨在提高应用程序的可测试性、可维护性和代码的解耦程度。在这个“MVVM...
Vue.js是一套构建用户界面的轻量级MVVM框架,与其他重量级框架不同的是, Vue.js 的核心库只关注视图层,并且非常容易学习,很容易与其它前端技术或已有的项目整合。 本系课程,主要分为两部分完成。第一部分:掌握...
首先从http://mvvmlight.codeplex.com/或者http://files.cnblogs.com/chengxingliang/GalaSoft.MvvmLight.V3.rar下载它的MVVM框架下来,安装上之后,...该程序是我学习MVVM框架学习制作的小示例,很适合mvvm框架入门。
**WPF MVVM框架Stylet使用教程 - 窗体交互用法** Windows Presentation Foundation (WPF) 是Microsoft提供的一种用于构建桌面应用程序的框架,它引入了Model-View-ViewModel (MVVM) 设计模式,使得UI设计和业务逻辑...
在IT行业中,MVVM(Model-View-ViewModel)框架是前端开发的重要组成部分,尤其是在JavaScript领域。MVVM模式是由Microsoft的WPF(Windows Presentation Foundation)引入的,后来在Web开发中得到了广泛应用,例如...
【标题】: "史上最全 MVVM 框架学习指南" 在 Android 开发领域,MVVM(Model-View-ViewModel)框架已经成为了现代应用程序设计的重要组成部分。本学习资源旨在提供全面深入的 MVVM 架构理解和实践指导,帮助开发者...
mvvm框架整合demo 在demo内有其他的实例,和其他实用框架有利于初学都学习,也有很多的代码注释
DevExpress MVVM框架是DevExpress提供的一个用于支持MVVM模式的开发框架,旨在简化使用DevExpress控件的MVVM应用程序开发。MVVM模式,即Model-View-ViewModel模式,是一种软件架构设计模式,通过分离用户界面的展示...
MVVM是一种流行的设计模式,尤其在WPF和Xamarin等框架中广泛应用,但在WinForm中相对较少见。然而,通过巧妙的实现,我们可以在WinForm上实现类似Vue的体验。 1. **MVVM模式概述**: MVVM模式分为三个主要部分:...
在本文中,我们将深入探讨如何在WinForm应用中利用MVVM框架,并且通过引入Castle动态代理来提升效率和代码复用性。标题“winform上的mvvm框架--升级版(动态代理)”揭示了我们将在WinForm环境中实现一个基于MVVM...
MVVM(Model-View-ViewModel)框架是一种设计模式,尤其在现代UI开发中,如WPF(Windows Presentation Foundation)和UWP(Universal Windows Platform)应用中广泛应用。它将应用程序的界面逻辑分离开来,使开发者...
WPF中的MVVM框架提供了强大的工具和结构,帮助我们构建清晰、可维护的应用程序。通过"AlarmClock"实例,我们可以看到MVVM模式如何在实践中提升开发效率和代码质量。了解并熟练运用MVVM,对于任何WPF开发者来说都是至...
这个框架引入了一种新的概念——Model-View-ViewModel(MVVM),使得开发人员能够更加高效地处理复杂的用户界面交互,同时保持代码的可维护性和测试性。 在传统的MVVM模式中,模型(Model)代表应用程序的数据,...
**WPF MVVM 开发框架详解** Windows Presentation Foundation (WPF) 是 Microsoft 推出的一种用于构建桌面应用程序的用户界面框架,它集成了丰富的图形、多媒体、数据绑定和控件库,为开发者提供了强大的设计和开发...
**WPF采用MVVM框架实例** 在Windows Presentation Foundation(WPF)中,Model-View-ViewModel(MVVM)设计模式是一种广泛使用的架构模式,尤其适用于创建用户界面。它将业务逻辑、用户界面和数据绑定分离,使代码...