运行avalon.define()发生的事情
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()发生的事情的更多相关文章
- [C# 基础知识系列]专题五:当点击按钮时触发Click事件背后发生的事情 (转载)
当我们在点击窗口中的Button控件VS会帮我们自动生成一些代码,我们只需要在Click方法中写一些自己的代码就可以实现触发Click事件后我们Click方法中代码就会执行,然而我一直有一个疑问的—— ...
- Vue生命周期各阶段发生的事情
首先,参考之前一篇vue生命周期的总结:Vue生命周期总结 接下来我们来分析下官方文档经典流程图,每个阶段到底发生了什么事情. 1.在beforeCreate和created钩子函数之间的生命周期 在 ...
- 安装meteor运行基本demo发生错误。
bogon:~ paul$ curl https://install.meteor.com/ | sh % Total % Received % Xferd Average Speed Time Ti ...
- [Android]新版的sdk中新建一个android应用,增加的PlaceholderFragment这个静态类发生的事情
1,首先发生的是有两个布局xml,一个activity_main.xml,一个是fragment_main.xml一开始没在意,后来仔细看了原来是新功能的fragment概念等于多个场景在这个acti ...
- 输入 URL 到页面完成加载过程中的所有发生的事情?
转到浏览器中输入URL给你一个页面后,.有些事情,你每天都在使用,学的是计算机网络知道是怎么回事.DNS解析然后页面的回馈,只是要讲好还是有难度. 之前fex团队的nwind专门写过这个问题的博客: ...
- WinForm程序运行 Just-In-Time Exception发生时
debug时运行正常, 但exe程序却发生Just-In-Time Exception (具体是做了异步里面更新画面内容) 解决对策: [app.config]文件: jitDebugging设为tu ...
- 关于 unsigned 型变量在计算过程中发生的事情
运行环境:CentOS release 5.8 (Final) #include<stdio.h> #include<iostream> using namespace std ...
- 《超级IP》:伪理论,没能比现有的市场营销理论更高明,只敢勉强去解释已经发生的事情,不敢去预测未来。2星。
超级IP是作者造出来的一个词.作者尝试把“超级IP”作为一种理论来解释2015年以来的各种网红现象.读完全书后,我的感觉是这个理论不怎么样: 1:作者完全不提现有的市场营销理论.我的问题是:现有的理论 ...
- 黄聪:visual studio 2017编译运行出现脚本发生错误等问题如何解决?
升级VS2017后,编译运行程序会出现 /Community/Common7/IDE/PrivateAssemblies/plugin.vs.js 错误 先说VS2017-15.6.1跟旧版本IE的兼 ...
随机推荐
- tcp_tw_reuse 与 net.ipv4.tcp_tw_recycle
最近发现几个监控用的脚本在连接监控数据库的时候偶尔会连不上,报错: Couldn't connect to host:3306/tcp: IO::Socket::INET: connect: Cann ...
- hdu2565java
放大的X Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissio ...
- javascript笔记09:javascript的下拉式导航菜单
<!DOCTYPE html> <html> <body> <script> function hideAll() { for(i=0;i<odi ...
- Java实现简单选择排序
package select; import java.util.Scanner; /*采用最简单的选择方式:从头到尾扫描序列找出最小的记录和第一个记录交换,接着在剩下的记录中继续这种选择和交换,最终 ...
- iOS9.0之后不支持http请求解决方案
打开info.plist文件,添加关键字 NSAppTransportSecurity 类型 Dictionary 在 NSAppTransportSecurity 下添加关键字 NSAllowsAr ...
- Java集合和PHP的对比
这里突然感觉到在java中的集合,和php的数组非常相似 .
- uploadify上传控件使用
uploadify是JQuery的一个上传插件,实现的效果非常不错,并且带进度显示,我将给大家演示如何使用uploadify进行图片上传, 1.点我下载http://www.uploadify.com ...
- Redis Cache 简介
Microsoft Azure Redis Cache 是基于流行的开源Redis Cache 1.Microsoft Azure Redis Cache 可分为以下几个级别: Basic – 单节点 ...
- 安装oracle pl/sql developer
1.在官网上下载oracle 11g R2版本的数据库,直接常规安装.数据库可以下载32bit. 2.在这里下载oracle client (32bit)http://www.oracle.com/t ...
- 【CF493E】【数学】Vasya and Polynomial
Vasya is studying in the last class of school and soon he will take exams. He decided to study polyn ...