当前位置: 首页 > news >正文

avalon2.2的VM生成过程

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
}

相关文章:

  • rdesktop tsclient
  • 金额大小写转换(3)
  • Python 元组
  • mybatis mapper文件sql语句传入hashmap参数
  • 完全重装python和yum
  • angular源码分析:图解angular的启动流程
  • redis持久化方法对比分析
  • 接口和抽象类区别
  • 关于图片填充问题
  • 直播视频
  • SLAM学习
  • 轻松精通数据库管理之道——运维巡检之一(服务器状态及个硬件指标)
  • css3+js实现漂亮时钟
  • 时序数据合并场景加速分析和实现 - 复合索引,窗口分组查询加速,变态递归加速...
  • 帧中继
  • 深入了解以太坊
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • 分享的文章《人生如棋》
  • Apache的基本使用
  • C# 免费离线人脸识别 2.0 Demo
  • ERLANG 网工修炼笔记 ---- UDP
  • ES学习笔记(12)--Symbol
  • Js基础——数据类型之Null和Undefined
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • nodejs实现webservice问题总结
  • spring + angular 实现导出excel
  • webpack+react项目初体验——记录我的webpack环境配置
  • 力扣(LeetCode)965
  • 前端面试题总结
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 大数据全解:定义、价值及挑战
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • #《AI中文版》V3 第 1 章 概述
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (Matlab)使用竞争神经网络实现数据聚类
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (二)Eureka服务搭建,服务注册,服务发现
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (十) 初识 Docker file
  • (一)SpringBoot3---尚硅谷总结
  • (原)Matlab的svmtrain和svmclassify
  • (转) ns2/nam与nam实现相关的文件
  • (转)Unity3DUnity3D在android下调试
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .NET 常见的偏门问题
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .NET是什么
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • @javax.ws.rs Webservice注解