avalon.define = function(id, factory) {
var $id = id.$id || id
if (!$id) {
log("warning: vm必须指定$id")
}
if (VMODELS[$id]) {
log("warning: " + $id + " 已经存在于avalon.vmodels中")
}
if (typeof id === "object") {
var model = modelFactory(id)
} else {
var scope = {
$watch: noop
}
factory(scope) //得到所有定义
model = modelFactory(scope) //偷天换日,将scope换为model
stopRepeatAssign = true
factory(model)
stopRepeatAssign = false
}
model.$id = $id
return VMODELS[$id] = model
}

avalon.define源代码

运行这段代码的过程中,会把id在modelFactory中进行加工

function modelFactory(source, $special, $model) {
if (Array.isArray(source)) {
var arr = source.concat()
source.length = 0
var collection = Collection(source)
collection.pushArray(arr)
return collection
}
if (typeof source.nodeType === "number") {
return source
}
if (source.$id && source.$events) { //fix IE6-8 createWithProxy $val: val引发的BUG
return source
}
if (!Array.isArray(source.$skipArray)) {
source.$skipArray = []
}
source.$skipArray.$special = $special || {} //强制要监听的属性
var $vmodel = {} //要返回的对象, 它在IE6-8下可能被偷龙转凤
$model = $model || {} //vmodels.$model属性
var $events = {} //vmodel.$events属性
var watchedProperties = {} //监控属性
var initCallbacks = [] //初始化才执行的函数
for (var i in source) {
(function(name, val) {
$model[name] = val
if (!isObservable(name, val, source.$skipArray)) {
return //过滤所有非监控属性
}
//总共产生三种accessor
$events[name] = []
var valueType = avalon.type(val)
var accessor = function(newValue) {
var name = accessor._name
var $vmodel = this
var $model = $vmodel.$model
var oldValue = $model[name]
var $events = $vmodel.$events if (arguments.length) {
if (stopRepeatAssign) {
return
}
//计算属性与对象属性需要重新计算newValue
if (accessor.type !== 1) {
newValue = getNewValue(accessor, name, newValue, $vmodel)
}
if (!isEqual(oldValue, newValue)) {
$model[name] = newValue
if ($events.$digest) {
if (accessor.pedding)
return
accessor.pedding = true
setTimeout(function() {
notifySubscribers($events[name]) //同步视图
safeFire($vmodel, name, $model[name], oldValue) //触发$watch回调
accessor.pedding = false
})
} else {
notifySubscribers($events[name]) //同步视图
safeFire($vmodel, name, newValue, oldValue) //触发$watch回调
}
}
} else {
if (accessor.type === 0) { //type 0 计算属性 1 监控属性 2 对象属性
//计算属性不需要收集视图刷新函数,都是由其他监控属性代劳
return $model[name] = accessor.get.call($vmodel)
} else {
collectSubscribers($events[name]) //收集视图函数
return accessor.svmodel || oldValue
}
}
}
//总共产生三种accessor
if (valueType === "object" && isFunction(val.get) && Object.keys(val).length <= 2) {
//第1种为计算属性, 因变量,通过其他监控属性触发其改变
accessor.set = val.set
accessor.get = val.get
accessor.type = 0
initCallbacks.push(function() {
var data = {
evaluator: function() {
data.element = null
data.type = new Date - 0
$model[name] = accessor.get.call($vmodel)
},
element: head,
type: new Date - 0,
handler: noop,
args: []
}
Registry[expose] = data
accessor.call($vmodel)
delete Registry[expose]
})
} else if (rcomplexType.test(valueType)) {
//第2种为对象属性,产生子VM与监控数组
accessor.type = 2
accessor.valueType = valueType
initCallbacks.push(function() {
var svmodel = modelFactory(val, 0, $model[name])
accessor.svmodel = svmodel
svmodel.$events[subscribers] = $events[name]
})
} else {
accessor.type = 1
//第3种为监控属性,对应简单的数据类型,自变量
}
accessor._name = name
/*给需要监控的属性添加set和get方法*/
watchedProperties[name] = accessor
})(i, source[i])
} $$skipArray.forEach(function(name) {
delete source[name]
delete $model[name] //这些特殊属性不应该在$model中出现
})
/* 下面方法是给属性生成如下格式:
* var descriptorFactory = W3C ? function(obj) {
var descriptors = {}
for (var i in obj) {
descriptors[i] = {
get: obj[i],
set: obj[i],
enumerable: true,
configurable: true
}
}
return descriptors
} : function(a) {
return a
}
*/
$vmodel = defineProperties($vmodel, descriptorFactory(watchedProperties), source) //生成一个空的ViewModel
for (var name in source) {
if (!watchedProperties[name]) {
$vmodel[name] = source[name]
}
}
//添加$id, $model, $events, $watch, $unwatch, $fire
$vmodel.$id = generateID()
$vmodel.$model = $model
$vmodel.$events = $events
for (var i in EventBus) {
var fn = EventBus[i]
if (!W3C) { //在IE6-8下,VB对象的方法里的this并不指向自身,需要用bind处理一下
fn = fn.bind($vmodel)
}
$vmodel[i] = fn
} if (canHideOwn) {
Object.defineProperty($vmodel, "hasOwnProperty", {
value: function(name) {
return name in this.$model
},
writable: false,
enumerable: false,
configurable: true
}) } else {
$vmodel.hasOwnProperty = function(name) {
return name in $vmodel.$model
}
}
initCallbacks.forEach(function(cb) { //收集依赖
cb()
})
return $vmodel
}

运行avalon.define()发生的事情的更多相关文章

  1. [C# 基础知识系列]专题五:当点击按钮时触发Click事件背后发生的事情 (转载)

    当我们在点击窗口中的Button控件VS会帮我们自动生成一些代码,我们只需要在Click方法中写一些自己的代码就可以实现触发Click事件后我们Click方法中代码就会执行,然而我一直有一个疑问的—— ...

  2. Vue生命周期各阶段发生的事情

    首先,参考之前一篇vue生命周期的总结:Vue生命周期总结 接下来我们来分析下官方文档经典流程图,每个阶段到底发生了什么事情. 1.在beforeCreate和created钩子函数之间的生命周期 在 ...

  3. 安装meteor运行基本demo发生错误。

    bogon:~ paul$ curl https://install.meteor.com/ | sh % Total % Received % Xferd Average Speed Time Ti ...

  4. [Android]新版的sdk中新建一个android应用,增加的PlaceholderFragment这个静态类发生的事情

    1,首先发生的是有两个布局xml,一个activity_main.xml,一个是fragment_main.xml一开始没在意,后来仔细看了原来是新功能的fragment概念等于多个场景在这个acti ...

  5. 输入 URL 到页面完成加载过程中的所有发生的事情?

    转到浏览器中输入URL给你一个页面后,.有些事情,你每天都在使用,学的是计算机网络知道是怎么回事.DNS解析然后页面的回馈,只是要讲好还是有难度. 之前fex团队的nwind专门写过这个问题的博客: ...

  6. WinForm程序运行 Just-In-Time Exception发生时

    debug时运行正常, 但exe程序却发生Just-In-Time Exception (具体是做了异步里面更新画面内容) 解决对策: [app.config]文件: jitDebugging设为tu ...

  7. 关于 unsigned 型变量在计算过程中发生的事情

    运行环境:CentOS release 5.8 (Final) #include<stdio.h> #include<iostream> using namespace std ...

  8. 《超级IP》:伪理论,没能比现有的市场营销理论更高明,只敢勉强去解释已经发生的事情,不敢去预测未来。2星。

    超级IP是作者造出来的一个词.作者尝试把“超级IP”作为一种理论来解释2015年以来的各种网红现象.读完全书后,我的感觉是这个理论不怎么样: 1:作者完全不提现有的市场营销理论.我的问题是:现有的理论 ...

  9. 黄聪:visual studio 2017编译运行出现脚本发生错误等问题如何解决?

    升级VS2017后,编译运行程序会出现 /Community/Common7/IDE/PrivateAssemblies/plugin.vs.js 错误 先说VS2017-15.6.1跟旧版本IE的兼 ...

随机推荐

  1. Match+Faq

    假如在GameLayer.h中有Card类型的变量,那么在Card.h文件中,不要有GameLayer.h的导入.这样子会导致编译器找不到对Card类型的定义而导致报错.但是,在Card.cpp中可以 ...

  2. How Network Load Balancing Technology Works--reference

    http://technet.microsoft.com/en-us/library/cc756878(v=ws.10).aspx In this section Network Load Balan ...

  3. Android 开发第二天

    开发入门HelloWorld 首先打开开发工具 第一步 第二步 效果图 以后可以点击一直下去 第三步骤介绍一下里面项目的作用 SRC是用来保存源代码的东西MainAcrivity.java主视图res ...

  4. iOS自定义UICollectionViewLayout之瀑布流

    目标效果 因为系统给我们提供的 UICollectionViewFlowLayout 布局类不能实现瀑布流的效果,如果我们想实现 瀑布流 的效果,需要自定义一个 UICollectionViewLay ...

  5. jhipster

    Client side: yeoman,grunt,bower,angularjs Server side: maven,spring,spring mvc rest,spring data jpa

  6. mysql中查询某字段所在的表方法

    select TABLE_NAME from information_schema.COLUMNS where COLUMN_NAME = 'type'

  7. FxCop

    下载地址:http://www.microsoft.com/en-us/download/details.aspx?id=8279 FxCop是一个代码分析工具,和StyleCop(代码规范)一起配合 ...

  8. python中关于正则表达式一

    ab+,描述一个'a'和任意个'b',那么'ab','abb','abbbbb' 正则表达式可以:1.验证字符串是否符合指定特征,比如验证是否是合法的邮件地址 2.用来查找字符串,从一个长的文本中查找 ...

  9. OS X EL Capitan安装Cocoapods 报错ERROR

    升级OS X EL Capitan10.11之后,原来的pod不能用了,重新安装cocoapods,发现 在运行 “sudo gem install cocoapods” 的时候出现问题: ERROR ...

  10. objective-c ios webkit 本地存储local-storage

    我有一个Cocoa / Objective-C的应用程序,它嵌入了一个WebKit的web视图.我需要打开的数据库支持和本地存储.我知道这是可以做到-我有它在Safari中工作-但我无法找到如何设置这 ...