directly use array length

This commit is contained in:
Evan You 2013-08-22 16:30:51 -04:00
parent 0a45bb813f
commit 77ce1fc355
4 changed files with 77 additions and 15 deletions

View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>SEED repeated items</title>
<meta charset="utf-8">
</head>
<body>
<div id="app">
<ul>
<li sd-each="item:items" sd-text="item.title"></li>
</ul>
<p>Total items: {{items.length}}</p>
</div>
<script src="../dist/seed.js"></script>
<script>
seed.config({debug: true})
var items = [
{ title: 'hi' },
{ title: 'ha' },
{ title: 'hu' },
{ title: 'ho' },
{ title: 'he' }
]
var test = {
test: [1, 2, 3]
}
var demo = new seed.ViewModel({
el: '#app',
data: {
items: items,
test: test
}
})
</script>
</body>
</html>

View File

@ -73,6 +73,7 @@ function Compiler (vm, options) {
var observables = this.observables = []
var computed = this.computed = [] // computed props to parse deps from
var ctxBindings = this.contextBindings = [] // computed props with dynamic context
var arrays = this.arrays = []
// prototypal inheritance of bindings
var parent = this.parentCompiler
@ -113,12 +114,18 @@ function Compiler (vm, options) {
binding = observables[i]
Observer.observe(binding.value, binding.key, this.observer)
}
// emit set events for array lengths
i = arrays.length
while (i--) {
binding = arrays[i]
this.observer.emit('set', binding.key + '.length', binding.value.length)
}
// extract dependencies for computed properties
if (computed.length) DepsParser.parse(computed)
// extract dependencies for computed properties with dynamic context
if (ctxBindings.length) this.bindContexts(ctxBindings)
this.observables = this.computed = this.contextBindings = null
// unset these no longer needed stuff
this.observables = this.computed = this.contextBindings = this.arrays = null
}
var CompilerProto = Compiler.prototype
@ -141,14 +148,17 @@ CompilerProto.setupObserver = function () {
// add own listeners which trigger binding updates
observer
.on('get', function (key) {
if (depsOb.isObserving && bindings[key]) {
console.log('get ' + key)
if (bindings[key] && depsOb.isObserving) {
depsOb.emit('get', bindings[key])
}
})
.on('set', function (key, val) {
console.log('set ' + key)
if (bindings[key]) bindings[key].update(val)
})
.on('mutate', function (key) {
console.log('mutate ' + key)
if (bindings[key]) bindings[key].pub()
})
}
@ -300,7 +310,9 @@ CompilerProto.bindDirective = function (directive) {
}
// set initial value
directive.update(binding.value)
if (binding.value) {
directive.update(binding.value)
}
if (binding.isComputed) {
directive.refresh()
}
@ -375,13 +387,16 @@ CompilerProto.define = function (key, binding) {
this.computed.push(binding)
} else {
// observe objects later, becase there might be more keys
// to be added to it
// to be added to it. we also want to emit all the set events
// when values are available.
this.observables.push(binding)
}
} else if (type === 'Array') {
// observe arrays right now, because they will be needed in
// sd-each directives.
Observer.observe(value, key, compiler.observer)
// we need to later emit set event for the arrays length.
this.arrays.push(binding)
}
Object.defineProperty(vm, key, {

View File

@ -83,7 +83,7 @@ module.exports = {
ctn.removeChild(this.el)
this.collection = null
this.vms = null
this.mutationListener = (function (mutation) {
this.mutationListener = (function (path, arr, mutation) {
mutationHandlers[mutation.method].call(this, mutation)
}).bind(this)
},
@ -102,7 +102,6 @@ module.exports = {
this.collection = collection
this.vms = []
console.log(collection)
// listen for collection mutation events
// the collection has been augmented during Binding.set()
collection.__observer__.on('mutate', this.mutationListener)
@ -120,16 +119,16 @@ module.exports = {
this.container.insertBefore(node, ref)
ViewModel = ViewModel || require('../viewmodel')
var vmID = node.getAttribute(config.prefix + '-viewmodel'),
ChildVM = utils.getVM(vmID) || ViewModel
ChildVM = utils.getVM(vmID) || ViewModel,
wrappedData = {}
wrappedData[this.arg] = data
var item = new ChildVM({
el: node,
each: true,
eachPrefix: this.arg,
parentCompiler: this.compiler,
delegator: this.container,
data: {
todo: data
}
data: wrappedData
})
if (dummy) {
item.$destroy()

View File

@ -101,10 +101,10 @@ function emitSet (obj, observer) {
module.exports = {
observe: function (obj, path, observer) {
observe: function (obj, rawPath, observer) {
if (isWatchable(obj)) {
path = path + '.'
var ob, alreadyConverted = !!obj.__observer__
var path = rawPath + '.',
ob, alreadyConverted = !!obj.__observer__
if (!alreadyConverted) {
defProtected(obj, '__observer__', new Emitter())
}
@ -117,7 +117,15 @@ module.exports = {
observer.emit('set', path + key, val)
},
mutate: function (key, val, mutation) {
observer.emit('mutate', path + key, val, mutation)
// if the Array is a root value
// the key will be null
var fixedPath = key ? path + key : rawPath
observer.emit('mutate', fixedPath, val, mutation)
// also emit set for Array's length when it mutates
var m = mutation.method
if (m !== 'sort' && m !== 'reverse') {
observer.emit('set', fixedPath + '.length', val.length)
}
}
}
ob