Skip to content

Commit

Permalink
简化计算属性
Browse files Browse the repository at this point in the history
  • Loading branch information
qincheng committed Sep 27, 2014
1 parent 22ac0c6 commit 96721e9
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 101 deletions.
96 changes: 40 additions & 56 deletions examples/avalon.$events.js
Expand Up @@ -448,20 +448,20 @@
var $model = {} //vmodels.$model属性
var watchedProperties = {} //监控属性
var computedProperties = [] //计算属性
var childrenProperties = [] //能转换为子VM或监控数组的属性
var childrenProperties = [] //能转换为子VM或监控数组的属性
var $events = {}
avalon.each($scope, function(name, val) {
if (!isObservable(name, val, $scope.$skipArray)) {
$model[name] = val
return //过滤所有非监控属性
}
//总共产生三种accessor
var accessor, oldArgs
var accessor
var valueType = avalon.type(val)
$events[name] = []
if (valueType === "object" && isFunction(val.get) && Object.keys(val).length <= 2) {
var setter = val.set,
getter = val.get
var setter = val.set
var getter = val.get
//第1种对应计算属性, 因变量,通过其他监控属性触发其改变
accessor = function(newValue) {
var $events = $vmodel.$events
Expand All @@ -476,21 +476,14 @@
setter.call($vmodel, newValue)
$events[name] = backup
}
if (!isEqual(oldArgs, newValue)) {
oldArgs = newValue
newValue = $model[name] = getter.call($vmodel) //同步$model
withProxyCount && updateWithProxy($vmodel.$id, name, newValue) //同步循环绑定中的代理VM
notifySubscribers($events[name]) //通知顶层改变
safeFire($vmodel, name, newValue, oldValue) //触发$watch回调
}
} else {
newValue = $model[name] = getter.call($vmodel)
if (!isEqual(oldValue, newValue)) {
oldArgs = void 0
safeFire($vmodel, name, newValue, oldValue)
}
return newValue
}
newValue = $model[name] = getter.call($vmodel) //同步$model
if (!isEqual(oldValue, newValue)) {
withProxyCount && updateWithProxy($vmodel.$id, name, newValue) //同步循环绑定中的代理VM
notifySubscribers($events[name]) //通知顶层改变
safeFire($vmodel, name, newValue, oldValue) //触发$watch回调
}
return newValue
}
computedProperties.push(function() {
var data = {
Expand Down Expand Up @@ -1796,6 +1789,27 @@
avalon.Array.ensure(list, data)
}
}

var ronduplex = /^(duplex|on)$/
function registerSubscriber(data, val) {
var fn = data.evaluator
if (fn) { //如果是求值函数
try {
var c = ronduplex.test(data.type) ? data : fn.apply(0, data.args)
data.handler(c, data.element, data)
} catch (e) {
delete data.evaluator
if (data.nodeType === 3) {
if (kernel.commentInterpolate) {
data.element.replaceChild(DOC.createComment(data.value), data.node)
} else {
data.node.data = openTag + data.value + closeTag
}
}
log("warning:evaluator of [" + data.value + "] throws error!")
}
}
}
function notifySubscribers(list, nofire) {
if (list && list.length) {
var args = aslice.call(arguments, 1)
Expand All @@ -1804,15 +1818,6 @@
if (el) {
var inTree = avalon.contains(root, el)
var remove = !inTree
// var remove = !ifSanctuary.contains(el) && !inTree
// var comment = fn.placehoder
// if (fn.type === "if" && comment) {
// var recycle = fn.msInDocument ? !inTree : !avalon.contains(root, comment)
// if (recycle) {
// breakCircularReference([fn])
// remove = true
// }
// }
} else if (fn.type === "if" || fn.node === null) {
remove = true
}
Expand All @@ -1822,12 +1827,12 @@
breakCircularReference(removed)
} else if (nofire === true) {
//nothing
} else if (typeof fn === "function") {
// fn.apply(0, args) //待处理, 强制重新计算自身
} else if (fn.$repeat) {
}
if (fn.$repeat) {
fn.handler.apply(fn, args) //处理监控数组的方法
} else if (fn.node || fn.element) {
var fun = fn.evaluator || noop
// console.log(fun+"")
fn.handler(fun.apply(0, fn.args || []), el, fn)
}
}
Expand Down Expand Up @@ -2443,30 +2448,11 @@
//方便调试
//这里非常重要,我们通过判定视图刷新函数的element是否在DOM树决定
//将它移出订阅者列表
executeBinding(data)
registerSubscriber(data)
}
}

var ronduplex = /^(duplex|on)$/
function executeBinding(data, val) {
var fn = data.evaluator
if (fn) { //如果是求值函数
try {
var c = ronduplex.test(data.type) ? data : fn.apply(0, data.args)
data.handler(c, data.element, data)
} catch (e) {
delete data.evaluator
if (data.nodeType === 3) {
if (kernel.commentInterpolate) {
data.element.replaceChild(DOC.createComment(data.value), data.node)
} else {
data.node.data = openTag + data.value + closeTag
}
}
log("warning:evaluator of [" + data.value + "] throws error!")
}
}
}

avalon.parseExprProxy = parseExprProxy
/*********************************************************************
* 绑定处理系统 *
Expand Down Expand Up @@ -2981,7 +2967,7 @@
if (typeof duplexBinding[tagName] === "function") {
data.changed = getBindingCallback(elem, "data-duplex-changed", vmodels) || noop
//由于情况特殊,不再经过parseExprProxy
parseExpr(data.value, vmodels, data, "duplex")
parseExpr(data.value, vmodels, data)
if (data.evaluator && data.args) {
var form = elem.form
if (form && form.msValidate) {
Expand Down Expand Up @@ -3331,8 +3317,7 @@
return false
}
})
executeBinding(data)
// registerSubscriber(data)
registerSubscriber(data)
var timer = setTimeout(function() {
if (!firstTigger) {
callback.call(element, element.value)
Expand Down Expand Up @@ -3424,8 +3409,7 @@
if (currHTML === innerHTML) {
clearInterval(id)
//先等到select里的option元素被扫描后,才根据model设置selected属性
// registerSubscriber(data)
executeBinding(data)
registerSubscriber(data)
data.changed.call(element, evaluator())
} else {
innerHTML = currHTML
Expand Down
84 changes: 39 additions & 45 deletions examples/test1.html
Expand Up @@ -3,16 +3,13 @@
<head>
<title>avalon入门</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="avalon.$events.js" type="text/javascript"></script>
<!-- <script src="../avalon.js" type="text/javascript"></script>-->
<script src="avalon.$events.js" type="text/javascript"></script>
<!-- <script src="../avalon.js" type="text/javascript"></script>-->
<script>
var first = 0;
var model = avalon.define("test", function(vm) {
vm.a = 1
vm.c = 3
vm.b = 2
// vm.d = {a: "222222222", b: "ddddd", c: 345435}
vm.firstName = "ddd"
vm.lastName = "fgfg"
vm.firstName = "司徒"
vm.lastName = "正美"
vm.fullName = {//一个包含set或get的对象会被当成PropertyDescriptor,
set: function(val) {//里面必须用this指向scope,不能使用scope
var array = (val || "").split(" ");
Expand All @@ -23,48 +20,45 @@
return this.firstName + " " + this.lastName;
}
}
vm.arr = ["aaa", 'bbb', "ccc", "ddd"]
vm.selected = ["bbb", "ccc"]
vm.checkAllbool = false
vm.checkAll = function() {
if (!first) {
first++
return
}
if (this.checked) {
vm.selected = vm.arr
} else {
vm.selected.clear()
}
}
vm.checkOne = function() {
var bool = this.checked
if (!bool) {
vm.checkAllbool = false
} else {
vm.checkAllbool = vm.selected.size() === vm.arr.length
}
}
})

vm.$skipArray = ["a"]
// vm.array = [5, 2, 3, 4]
});
// model.$watch("b", function(a) {
// avalon.log(a + "--------------")
// })
// setTimeout(function(){
// model.array.splice(2,0,9)
// model.array.sort()
// model.array.pop()
// },1000)
// console.log(model)
// setTimeout(function() {
// model.d = {
// 11: 111,
// 22: 3333,
// 34: 345,
// ddd: 465546
// }
// model.d.ddd = 4000
// model.array.push(8)
// setTimeout(function() {
// model.array = [2, 3, 4, 9]
// console.log(model)
// console.log(model.d)
// setTimeout(function() {
// model.array.clear()
// model.d = {}
// }, 1000)
// }, 1000)
//
// }, 1000)

</script>
</head>
<body>
<div ms-controller="test" >

<!-- <ul>
<li ms-repeat="array">{{el}}<strong>{{$index}}</strong></li>
</ul>-->
<div ms-controller="test">
<p>First name: <input ms-duplex="firstName" /></p>
<p>Last name: <input ms-duplex="lastName" /></p>
<p>Hello, <input ms-duplex="fullName"></p>
<div>{{firstName +" | "+ lastName }}</div>
<ul>
<li><input type="checkbox" ms-duplex-radio="checkAllbool" data-duplex-changed="checkAll"/>全选</li>
<li ms-repeat="arr" ><input type="checkbox" ms-value="el" ms-duplex="selected" data-duplex-changed="checkOne"/>{{el}} <strong>{{$index}}</strong></li>
</ul>
</div>


</body>
</html>

0 comments on commit 96721e9

Please sign in to comment.