avalon大家可能不熟悉,但是Knockout估计或多或少听过用过,那么说说KO的几个概念

  1. 监控属性(Observables)和依赖跟踪(Dependency tracking)
  2. 声明式绑定(Declarative bindings)
  3. 模板(Templating)

本章主要提到 监控属于依赖跟踪(后改名叫计算属性)

监控顾名思义,监听着你设定目标的变化,换句话说能够通知订阅者它的改变以及自动探测到相关的依赖。

计算属性,就是依赖监控属性变化而自动调用处理更新

KO的一个例子

如果你已经有了监控属性firstName和lastName,你想显示全称怎么办? 这就需要用到依赖监控属性了 – 这些函数是一个或多个监控属性, 如果他们的依赖对象改变,他们会自动跟着改变。

例如,下面的view model,

var viewModel = {
firstName: ko.observable('Bob'),
lastName: ko.observable('Smith')
};

… 你可以添加一个依赖监控属性来返回姓名全称:

viewModel.fullName = ko.dependentObservable(function () {
return this.firstName() + " " + this.lastName();
}, viewModel);

并且绑定到UI的元素上,例如:

The name is <span data-bind="text: fullName"></span>

… 不管firstName还是lastName改变,全称fullName都会自动更新(不管谁改变,执行函数都会调用一次,不管改变成什么,他的值都会更新到UI或者其他依赖监控属性上)

OK

KO是怎么实现双向机制的呢?

  • 通过转换VM中所有要监听的东西为函数,然后执行它们,得到某一时刻中,一共有多少函数被执行,将它们放到栈中,最底的就是最先被执行的,它上面的就是此函数所依赖的函数,从而得到依赖关系。
  • 然后设计一个观察者模式,从上面的依赖检测中,将依赖函数作为被依赖者(最先执行的那个的)的订阅者,以后我们对被依赖者进行赋值时,就会通先订阅者更新自身,从而形成一个双向绑定链。
  • knockout会将视图中的绑定属性进行转换,分解出求值函数与视图刷新函数,视图刷新函数依赖于求值函数,而求值函数亦依赖于我们VM中的某些属性(这时,它们都转换为函数),在第一次扫描时,它们会加入对应属性的订阅者列队中, 从而VM中的某个属性改变,就会自动刷新视图、

猪脚登场

avalon实现双向绑定跟ko的实现其实大同小异,但是ko的实现异常的复杂,avalon则清晰很多

上列子,然后分析

HTML结构

<div id='box' ms-controller="box">
<div style=" background: #a9ea00;" ms-css-width="w" ms-css-height="h" ms-click="click"></div>
<p>{{ w }} x {{ h }}</p>
<p>W: <input type="text" ms-model="w" data-event="change"/></p>
<p>H: <input type="text" ms-model="h" /></p>
</div>

JS

avalon.define("box", function(vm) {
vm.w = 100;
vm.h = 100;
vm.click = function() {
vm.w = parseFloat(vm.w) + 10;
vm.h = parseFloat(vm.h) + 10;
}
})
avalon.scan(document.getElementById('box')

就是官网提供的一个DEMO  http://rubylouvre.github.io/mvvm/

分析HTML结构:

  1. ms-controller="box"  作用域范围
  2. ms-css-width="w"     css样式绑定宽度
  3. ms-css-height="h"    css样式绑定高度
  4. ms-click="click"         绑定click处理事件
  5. {{ w }} x {{ h }}     插值表达式 数据填充
  6. ms-model="w"         改名叫ms-duplex 双向绑定

JS处理中:

  1. avalon.define   构建一个view model视图模型  box就是作用域范围
  2. vm.w = 100;   定义一个监控属性宽,默认值是100
  3. vm.h = 100;   定义一个监控属性高,默认值是100
  4. vm.click          定义一个click处理方法
  5. avalon.scan     扫描节点指定绑定

view model视图模型的构建在以前已经讲过了,这里主要讲下双向绑定的构建及处理的原理

1.构建VM的时候,对监控属性进程转化处理,生成一个监控对象

监控对象是通过Object.defineProperty转换过的处理函数,所以在setter,getter时候会调用转化的处理函数,这个用户是不可见的

赋值时处理 setter

var old = value;
if (valueType === "array" || valueType === "object") { //监控数组
if (value && value.$id) {
updateViewModel(value, neo, Array.isArray(neo))
} else if (Array.isArray(neo)) {
value = Collection(neo)
value._add(neo)
} else {
value = modelFactory(neo, neo)
}
} else {
value = neo
}
accessor.value = value;
model[name] = value && value.$id ? value.$model : value;
//值变化了,通知顶层改变
notifySubscribers(accessor);
vmodel.$fire && vmodel.$fire(name, value, old)

取值时处理 getter

collectSubscribers(accessor); //收集视图函数
return value

操作时

vm.w = 100  setter,就会默认调用赋值处理函数

vm.w  同样,getter 调用取值函数

这样方式,比ko的this.firstName() + " " + this.lastName();  友爱多了,因为KO转换的是处理函数,必须要函数调用。。。别提多变扭

关键点:

collectSubscribers  //收集视图函数

notifySubscribers //值变化了,通知顶层改变

这个2个方法,用来处理依赖关系的

实现的流程:

预处理过程:

  1. 生成监控属性,其中监控属性subscribers用来收集依赖处理的回调
  2. 扫描DOM节点上的对应的属性编码 比如,ms-css-width="w"
  3. 根据css类型找到对应bindingHandlers处理句柄函数
  4. 通过parseExpr分解出求值函数
  5. 通过watchView函数生成视图更新函数
  6. 视图更新函数updateView加入到当前对应监控属性的subscribers队列中,形成依赖关系

交互时:

  1. 用户点击某个通过ms-click="click” 绑定事件的元素(当value变化时改变model的值)视图通知模型
  2. 执行预先生成updateModel函数,通过执行’取值时处理’通知notifySubscribers(accessor)
  3. 执行accessor中subscribers的所有依赖函数,从而更新所有依赖

画了张图。。

本文只是很简单的说了下监控属性大概的逻辑,还有计算属性的处理,转化,调用,之后会分解

评价:实现非常巧妙,而且代码写的清晰易懂

前端MVVM框架avalon揭秘 - 双向绑定原理的更多相关文章

  1. 前端MVVM框架avalon揭秘 - HTML编译器

    MVVM试图更加清晰的讲用户界面(UI)开发从应用程序的业务逻辑与行为中心分离,因为,很多这样的模式的实现都需要利用声明式数据绑定来实现讲View(视图)工作从其他层分离 所以出现了一大堆自定义的声明 ...

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

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

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

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

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

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

  5. 轻量级前端MVVM框架avalon源码分析-总结

    距avalon0.7版本发布有一段时间,由于之前的稳定性,就停止一段时间更新,期间研究了下Knockout源码,也尝试写了一个小型的mvvm的实现模型,仅仅只是仿造ko的核心实现,把无关的东西给剥离掉 ...

  6. 轻量级前端MVVM框架avalon - ViewModel

    废话说了大几篇,我们开始来点干货了~ ViewModel的内部机制 在MVVM中,数据是核心.而jQuery则以DOM为核心. 而DOM只是HTML在JS的世界的抽象,是一个很易变的东西.因此如果业务 ...

  7. 轻量级前端MVVM框架avalon - 控制器

    引子: 最近工作挺忙,avalon只能断断续续的写下去了,大概看了下angular的源码,看到小一半就比较难坚持了,是块硬骨头,慢慢啃吧 不过angular的的文档中用词还是很优雅: HTML编译器 ...

  8. MVVM 框架解析之双向绑定

    更好的阅读体验,点击 原文地址 MVVM 框架 近年来前端一个明显的开发趋势就是架构从传统的 MVC 模式向 MVVM 模式迁移.在传统的 MVC 下,当前前端和后端发生数据交互后会刷新整个页面,从而 ...

  9. 简简单单的Vue1(MVVM与Vue的双向绑定原理)

    既然选择了远方,便只顾风雨兼程 __ HANS许 系列:零基础搭建前后端分离项目 系列:零基础搭建前后端分离项目 Vue 在此之前的文章我们讲述了前端开发的工具,语言的知识,接下来我们从头开始学习一个 ...

随机推荐

  1. centos中docker mongodb 配置

    安装docker,对于Centos7,如下: $ sudo yum update$ sudo yum -y install docker$ sudo systemctl start docker 首先 ...

  2. Linux上Tomcat部署JavaWeb项目

    一.安装JDK 配置java的环境变量,修改/etc/profile文件:vi /etc/profile 然后按下字母i进入插入模式, shift+insert粘贴; esc退出编辑; :wq保存退出 ...

  3. 关于Linux系统下错误“浮点数异常(核心已转储)”的分析

    1.问题发现 有这样一段代码: #include <stdio.h> int main() { int a, b, num1, num2, temp; printf("pleas ...

  4. JavaScript数组去重的几种方法

    这个老问题,网上普遍都有了,为什么要再写一遍呢,主要是为了记个笔记... 遍历时搜索结果数组 思路很明确,如下 新建一个数组存放结果 循环遍历原数组,对于每一个元素,在结果数组中搜索是否存在 若不存在 ...

  5. Web前端开发推荐阅读书籍

    前言 前端工程师在中国兴起也就5年左右,以前公司里没有专门前端工程师的这个职位,很多前端方面的任务都是由全栈工程师来完成,有的基础一点的后台或者设计的帮助分担一些.但是随着互联网的快速发展,特别是所谓 ...

  6. java并发编程(十六)happen-before规则

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17348313 happen-before规则介绍 Java语言中有一个"先行发生 ...

  7. 华为oj 挑7

    #include<iostream> using namespace std; bool ishave_7(int n); int main(){ int num,k=0; cin> ...

  8. Visual 2015创建新项,缺少ADO.NET 实体数据模型的解决方法

    现在的某度查资料真的很麻烦,突然我自身的VS2015创建EF的时候找不到 ADO.NET 实体数据模型,但是使用CodeFrist是可以生成数据表的.所有特别郁闷. 打开界面如下 某度半天,都没有查出 ...

  9. CQOI 2016 不同的最小割

    题目大意:一个无向图,求所有点对不同的最小割种类数 最小割最多有n-1个,这n-1个最小割构成一个最小割树 分治法寻找n-1个最小割.对于当前点集X,任选两点为ST做最小割,然后找出与S相连的所有点和 ...

  10. 跨平台移动开发UI语言 -XAML

    Xamarin.Forms 把XAML (Extensible Application Markup Language, XAML) 带进了ios,android的界面开发,也就使得使用Xamarin ...