运行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的兼 ...
随机推荐
- careercup-递归和动态规划 9.9
9.9 设计一种算法,打印八皇后在8*8棋盘上的各种摆法,其中每个皇后都不同行.不同列,也不在对角线上.这里的“对角线”指的是所有的对角线,不只是平分整个棋盘的那两条对角线. 类似leetcode:N ...
- oracle 查看表属主和表空间sql
查看表空间 select * from user_tablespaces where table_name = 'TableName' 查看表属主 select Owner from all_ta ...
- 玩转Android之Drawable的使用
Drawable天天用,可你是否对Drawable家族有一个完整的认知?今天我们就来系统的学习一下Drawable的使用. 1.概述 用过Drawable的筒子都知道Drawable有很多种,有的时候 ...
- quartz多个scheduler实现
1.首先排除错误用法 SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = sche ...
- mysql sqlmap 注入尝试
假设注入点为 http://www.abc.com/news.php?id=12 //探测数据库信息 sqlmap -u http://www.abc.com/news.php?id=12 –dbs ...
- xilinx仿真库的作用(原创)
① secureip库:硬核(HARD IP)仿真(功能仿真和时序仿真)模型(hard IP simulation model),比如PowerPC.PCIE.SRIO.DDR等.Simulation ...
- ThinkPHP函数详解:cookie方法
cookie函数也是一个多元化操作函数,完成cookie的设置.获取和删除操作. Cookie 用于Cookie 设置.获取.删除操作 用法cookie($name, $value='', $opti ...
- UIImagePickerController显示中文界面
iOS开发中,我们经常遇到获取拍照.相册中图片的功能,就必然少不了UIImagePickerController,但是我们发现当我们使用它的时候,它的页面是英文的,看着很别扭,国人还是比较喜欢看中文界 ...
- Eclipse使用Maven创建Web项目
一.Maven插件下载.jdk下载 1.maven下载地址: http://maven.apache.org/download.cgi 2.jdk下载地址: http://www.oracle.com ...
- 新建DragonBones动画文件
本篇文章由:http://www.sollyu.com/new-dragonbones-animation-file/ 说明 我在网上找了很久都没找到关于怎么创建一个DragonBones动画的文章, ...