博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
avalon2.2的VM生成过程
阅读量:6509 次
发布时间:2019-06-24

本文共 3100 字,大约阅读时间需要 10 分钟。

avalon2.2使用VBScript, Object.defineProperty, Proxy三种方式实现VM。现在市面上都是用Object.defineProperty。

clipboard.png

但是光是Object.defineProperty是不够用,这里面涉及许多机制才能实现视图与数据的双向绑定。

比如下面的这个VM。

var vm = avalon.define({   $id: "xxx",   $ddd: 111,   a: "可监控",   $computed: {b: function(){return this.a+"!"} },   c: new Date,   f1: function(){},   d: {     e:1,     f2:function(){}  }})

avalon.define要求传入一个带$id的对象。$id是必须的,没有会报错。

avalon.define的后面是modelFactory。它会遍历这个对象,从中筛选出所有可以监控的属性。

可以监控的属性,要求不能为函数,日期,正则,BOM,DOM,window这些特殊数据类型,如果你的类型为null, undefined,虽然也能转换,但会有警告。

此外,如果你的属性名是以$开头,$开头的属性是留给框架用的。

这些监控属性及位于$computed的计算属性,都会生成对应的监控对象,放在$mutations对象上。

遍历一遍,我们会将第一层的函数提出来,进行bind(vm)处理,这样可以解决IE6-8的差异化问题。至于子对象的函数,我们就不会处理了。

clipboard.png

我们看chrome的控制台中的vm对象,比如aaa,它的值是末知的,只有点击它,它才会勿勿从get aaa 方法中计算出来,如果对它进行赋值 vm.aaa = 88, 则需要经过set aaa方法处理。这种属性叫访问器属性,Object.defineProperty就是用来创建访问器属性的。可以说,这是我们实现MVVM的基石(在Proxy没出来之前)。

vm中有一个$mutations对象,里面存放着aaa的监控对象。当然这些可以不暴露出来,像vue,则称之为Depend,放在闭包内。

clipboard.png

$mutations内部的样子,每个访问器属性会对应的Mutation实例。Mutation是惰性创建的。

function createAccessor(key, val, isComputed) {    var mutation = null    var Accessor = isComputed ? Computed : Mutation    return {        get: function Getter() {            if (!mutation) {                mutation = new Accessor(key, val, this)            }            return mutation.get()        },        set: function Setter(newValue) {            if (!mutation) {                mutation = new Accessor(key, val, this)            }            mutation.set(newValue)        },        enumerable: true,        configurable: true    }}

比如我们为vm添加一个访问器属性,可以简化成这样的流程:

var accessor = createAccessor("aaa",111)Object.defineProperty(vm, "aaa", accessor)

clipboard.png

mutation实例有几个方法,当用户调用var a = vm.aaa,相当于调用vm.$muations.aaa.get()方法。我们会在属性取值时进行依赖收集,于是get里面会调用collect方法。如果赋值,则会调用它的set方法,从而调用它的notify方法与updateVerstion方法。

当一个vm创建完时,就会调用afterCreate方法,在这个方法中,我们会为vm添加$watch, $fire, $model等成员,在IE6-8中还会添加hasOwnProperty方法。

下面是modelFactory的完整代码,可以看到所有VM都是IProxy的实例

platform.modelFactory = function modelFactory(definition, dd) {    var $computed = definition.$computed || {}    delete definition.$computed    var core = new IProxy(definition, dd)    var $accessors = core.$accessors    var keys = []      platform.hideProperty(core, '$mutations', {})    for (let key in definition) {        if (key in $$skipArray)            continue        var val = definition[key]        keys.push(key)        if (canHijack(key, val)) {            $accessors[key] = createAccessor(key, val)        }    }    for (let key in $computed) {        if (key in $$skipArray)            continue        var val = $computed[key]        if (typeof val === 'function') {            val = {                get: val            }        }        if (val && val.get) {            val.getter = val.get            val.setter = val.set            avalon.Array.ensure(keys, key)            $accessors[key] = createAccessor(key, val, true)        }    }    //将系统API以unenumerable形式加入vm,    //添加用户的其他不可监听属性或方法    //重写$track    //并在IE6-8中增添加不存在的hasOwnPropert方法    var vm = platform.createViewModel(core, $accessors, core)    platform.afterCreate(vm, core, keys, !dd)    return vm}

转载地址:http://vudfo.baihongyu.com/

你可能感兴趣的文章
java数据库生成model_继承BaseModelGenerator 生成Model时添加数据库表字段 生成代码示例...
查看>>
smarty使用php代码,笑谈配置,使用Smarty技术_php
查看>>
silk v3 decoder php,解码转换QQ微信的SILK v3编码音频为MP3或其他格式
查看>>
linux不能访问80端口,lunux开放80端口(本地访问不了linux文件可能是这个原因)...
查看>>
android单位转换小程序,微信小程序中rpx与rem单位转换
查看>>
ps切图教程 android,PS前端切图完整教程
查看>>
HTML如何把输入框变成必填值,required输入框为必填项
查看>>
背锅侠逆袭之路
查看>>
演示:使用协议分析器取证IPv6的报文结构
查看>>
oracle 11gr2 rac中的4种IP解说
查看>>
为什么你找不到工作?
查看>>
汇编语言的应用
查看>>
device platform 相应的表
查看>>
php des 加密解密实例
查看>>
【Mac】Mac键盘实现Home, End, Page UP, Page DOWN
查看>>
实战使用Axure设计App,使用WebStorm开发(1) – 用Axure描述需求
查看>>
安德鲁斯----多媒体编程
查看>>
[zz]在linux中出现there are stopped jobs 的解决方法
查看>>
Delphi下实现全屏快速找图找色 一、数据提取
查看>>
查询表字段信息
查看>>