Evan You 12 лет назад
Родитель
Сommit
bc84435133
7 измененных файлов с 62 добавлено и 36 удалено
  1. 1 1
      examples/todomvc/index.html
  2. 22 14
      examples/todomvc/js/app.js
  3. 14 8
      src/compiler.js
  4. 11 10
      src/directives/each.js
  5. 2 2
      src/directives/index.js
  6. 1 1
      src/directives/on.js
  7. 11 0
      src/viewmodel.js

+ 1 - 1
examples/todomvc/index.html

@@ -6,7 +6,7 @@
         <link rel="stylesheet" type="text/css" href="common/base.css">
     </head>
     <body>
-        <section id="todoapp" sd-controller="todos">
+        <section id="todoapp">
             <header id="header">
                 <h1>todos</h1>
                 <input

+ 22 - 14
examples/todomvc/js/app.js

@@ -1,13 +1,21 @@
+seed.config({ debug: true })
+
 var filters = {
     all: function () { return true },
     active: function (todo) { return !todo.completed },
     completed: function (todo) { return todo.completed }
 }
 
-var Todos = Seed.ViewModel.extend({
+var todos = [
+            {title: 'hi', completed: true},
+            {title: 'ha', completed: false},
+            {title: 'ho', completed: false},
+        ]
+
+var Todos = seed.ViewModel.extend({
 
     init: function () {
-        this.todos = todoStorage.fetch()
+        this.todos = todos//todoStorage.fetch()
         this.remaining = this.todos.filter(filters.active).length
         this.updateFilter()
     },
@@ -30,7 +38,7 @@ var Todos = Seed.ViewModel.extend({
 
         // dynamic context computed property using info from target viewmodel
         todoFiltered: {get: function (ctx) {
-            return filters[this.filter]({ completed: ctx.vm.completed })
+            return filters[this.filter]({ completed: ctx.vm.todo.completed })
         }},
 
         // dynamic context computed property using info from target element
@@ -64,32 +72,32 @@ var Todos = Seed.ViewModel.extend({
         },
 
         removeTodo: function (e) {
-            this.todos.remove(e.vm)
-            this.remaining -= e.vm.completed ? 0 : 1
+            this.todos.remove(e.item)
+            this.remaining -= e.item.completed ? 0 : 1
             todoStorage.save(this.todos)
         },
 
         toggleTodo: function (e) {
-            this.remaining += e.vm.completed ? -1 : 1
+            this.remaining += e.item.completed ? -1 : 1
             todoStorage.save(this.todos)
         },
 
         editTodo: function (e) {
-            this.beforeEditCache = e.vm.title
-            e.vm.editing = true
+            this.beforeEditCache = e.item.title
+            e.item.editing = true
         },
 
         doneEdit: function (e) {
-            if (!e.vm.editing) return
-            e.vm.editing = false
-            e.vm.title = e.vm.title.trim()
-            if (!e.vm.title) this.removeTodo(e)
+            if (!e.item.editing) return
+            e.item.editing = false
+            e.item.title = e.item.title.trim()
+            if (!e.item.title) this.removeTodo(e)
             todoStorage.save(this.todos)
         },
 
         cancelEdit: function (e) {
-            e.vm.editing = false
-            e.vm.title = this.beforeEditCache
+            e.item.editing = false
+            e.item.title = this.beforeEditCache
         },
 
         removeCompleted: function () {

+ 14 - 8
src/compiler.js

@@ -55,8 +55,6 @@ function Compiler (vm, options) {
     vm.$el = el
     // link it up!
     vm.$compiler = this
-    // possible info inherited as an each item
-    vm.$index    = options.index
     vm.$parent   = options.parentCompiler && options.parentCompiler.vm
 
     // now for the compiler itself...
@@ -97,8 +95,7 @@ function Compiler (vm, options) {
     // check for async compilation (vm.$wait())
     if (vm.__wait__) {
         var self = this
-        this.observer.on('ready', function () {
-            self.observer.off('ready')
+        this.observer.once('ready', function () {
             vm.__wait__ = null
             self.compile()
         })
@@ -133,6 +130,9 @@ CompilerProto.setupObserver = function () {
             }
         })
         .on('set', function (key, val) {
+            if (key.match(/todo\./)) {
+                console.log(key, val)
+            }
             if (!bindings[key]) compiler.createBinding(key)
             bindings[key].update(val)
         })
@@ -285,10 +285,11 @@ CompilerProto.bindDirective = function (directive) {
     directive.vm       = this.vm
 
     var key = directive.key,
+        baseKey = key.split('.')[0],
         compiler = traceOwnerCompiler(directive, this)
 
     var binding
-    if (compiler.vm.hasOwnProperty(key)) {
+    if (compiler.vm.hasOwnProperty(baseKey)) {
         // if the value is present in the target VM, we create the binding on its compiler
         binding = compiler.bindings.hasOwnProperty(key)
             ? compiler.bindings[key]
@@ -386,7 +387,10 @@ CompilerProto.define = function (key, binding) {
             return binding.isComputed
                 ? binding.value.get({
                     el: compiler.el,
-                    vm: compiler.vm
+                    vm: compiler.vm,
+                    item: compiler.each
+                        ? compiler.vm[compiler.eachPrefix.slice(0, -1)]
+                        : null
                 })
                 : binding.value
         },
@@ -447,9 +451,11 @@ CompilerProto.destroy = function () {
         }
         dir.unbind()
     }
-    // unbind all bindings
+    // unbind all own bindings
     for (key in bindings) {
-        bindings[key].unbind()
+        if (bindings.hasOwnProperty(key)) {
+            bindings[key].unbind()
+        }
     }
     // remove el
     el.parentNode.removeChild(el)

+ 11 - 10
src/directives/each.js

@@ -97,7 +97,7 @@ module.exports = {
         // force a compile so that we get all the bindings for
         // dependency extraction.
         if (!this.collection && !collection.length) {
-            this.buildItem(this.ref, null, null)
+            this.buildItem(this.ref, null, true)
         }
         this.collection = collection
         this.vms = []
@@ -108,11 +108,13 @@ module.exports = {
 
         // create child-seeds and append to DOM
         for (var i = 0, l = collection.length; i < l; i++) {
-            this.buildItem(this.ref, collection[i], i)
+            var item = this.buildItem(this.ref, collection[i])
+            this.container.appendChild(item.$el)
+            this.vms.push(item)
         }
     },
 
-    buildItem: function (ref, data, index) {
+    buildItem: function (ref, data, dummy) {
         var node = this.el.cloneNode(true)
         this.container.insertBefore(node, ref)
         ViewModel = ViewModel || require('../viewmodel')
@@ -123,16 +125,15 @@ module.exports = {
             each: true,
             eachPrefix: this.arg + '.',
             parentCompiler: this.compiler,
-            index: index,
             delegator: this.container,
             data: {
                 todo: data
             }
         })
-        if (index) {
-            this.vms[index] = item
-        } else {
+        if (dummy) {
             item.$destroy()
+        } else {
+            return item
         }
     },
 
@@ -145,10 +146,10 @@ module.exports = {
 
     unbind: function () {
         if (this.collection) {
-            this.collection.off('mutate', this.mutationListener)
-            var i = this.collection.length
+            this.collection.__observer__.off('mutate', this.mutationListener)
+            var i = this.vms.length
             while (i--) {
-                this.collection[i].$destroy()
+                this.vms[i].$destroy()
             }
         }
         var ctn = this.container,

+ 2 - 2
src/directives/index.js

@@ -51,7 +51,7 @@ module.exports = {
             if (this.oneway) return
             var el = this.el, self = this
             this.change = function () {
-                self.vm[self.key] = el.value
+                self.vm.$set(self.key, el.value)
             }
             el.addEventListener('keyup', this.change)
         },
@@ -69,7 +69,7 @@ module.exports = {
             if (this.oneway) return
             var el = this.el, self = this
             this.change = function () {
-                self.vm[self.key] = el.checked
+                self.vm.$set(self.key, el.checked)
             }
             el.addEventListener('change', this.change)
         },

+ 1 - 1
src/directives/on.js

@@ -45,8 +45,8 @@ module.exports = {
             dHandler = delegator.sd_dHandlers[identifier] = function (e) {
                 var target = delegateCheck(e.target, delegator, identifier)
                 if (target) {
-                    e.el = target
                     e.vm = target.sd_viewmodel
+                    e.item = e.vm[compiler.eachPrefix.slice(0, -1)]
                     handler.call(ownerVM, e)
                 }
             }

+ 11 - 0
src/viewmodel.js

@@ -20,6 +20,17 @@ VMProto.$ready = function () {
     this.$compiler.observer.emit('ready')
 }
 
+VMProto.$set = function (key, value) {
+    var path = key.split('.'),
+        level = 0,
+        target = this
+    while (level < path.length - 1) {
+        target = target[path[level]]
+        level++
+    }
+    target[path[level]] = value
+}
+
 /*
  *  watch a key on the viewmodel for changes
  *  fire callback with new value