Explorar o código

separate computed properties into `computed` option

Evan You %!s(int64=12) %!d(string=hai) anos
pai
achega
7a6169caf9

+ 6 - 3
examples/firebase/app.js

@@ -29,7 +29,9 @@ var app = new Vue({
         validation: {
             name: false,
             email: false
-        },
+        }
+    },
+    computed: {
         isValid: {
             $get: function () {
                 var valid = true
@@ -45,13 +47,14 @@ var app = new Vue({
     methods: {
         addUser: function (e) {
             e.preventDefault()
+            console.log(this)
             if (this.isValid) {
                 Users.push(this.newUser)
                 this.newUser = {}
             }
         },
-        removeUser: function (e) {
-            new Firebase(baseURL + 'users/' + e.targetVM.id).remove()
+        removeUser: function (user) {
+            new Firebase(baseURL + 'users/' + user.id).remove()
         }
     }
 })

+ 1 - 1
examples/firebase/index.html

@@ -12,7 +12,7 @@
             <ul>
                 <li class="user" v-repeat="users" v-transition>
                     <span>{{name}} - {{email}}</span>
-                    <button v-on="click:removeUser">X</button>
+                    <button v-on="click:removeUser(this)">X</button>
                 </li>
             </ul>
             <form id="form" v-on="submit:addUser">

+ 4 - 2
examples/todomvc/js/app.js

@@ -37,9 +37,11 @@ var app = new Vue({
 
     // data
     data: {
-        // fetch the saved todos from localStorage
         todos: todoStorage.fetch(),
-        // a computed property with custom getter/setter
+    },
+
+    // computed property
+    computed: {
         allDone: {
             $get: function () {
                 return this.remaining === 0

+ 24 - 13
src/compiler.js

@@ -72,6 +72,14 @@ function Compiler (vm, options) {
     // setup observer
     compiler.setupObserver()
 
+    // create bindings for computed properties
+    var computed = options.computed
+    if (computed) {
+        for (var key in computed) {
+            compiler.createBinding(key)
+        }
+    }
+
     // beforeCompile hook
     compiler.execHook('beforeCompile', 'created')
 
@@ -482,21 +490,24 @@ CompilerProto.define = function (key, binding) {
     var compiler = this,
         data     = compiler.data,
         vm       = compiler.vm,
-        ob       = data.__observer__
-
-    if (!(key in data)) {
-        data[key] = undefined
-    }
+        comps    = compiler.options.computed,
+        ob       = data.__observer__,
+        value
 
-    // if the data object is already observed, but the key
-    // is not observed, we need to add it to the observed keys.
-    if (ob && !(key in ob.values)) {
-        Observer.convert(data, key)
-    }
-
-    var value = binding.value = data[key]
-    if (utils.typeOf(value) === 'Object' && value.$get) {
+    if (comps && comps[key]) {
+        // computed property
+        value = binding.value = comps[key]
         compiler.markComputed(binding)
+    } else {
+        if (!(key in data)) {
+            data[key] = undefined
+        }
+        // if the data object is already observed, but the key
+        // is not observed, we need to add it to the observed keys.
+        if (ob && !(key in ob.values)) {
+            Observer.convert(data, key)
+        }
+        value = binding.value = data[key]
     }
 
     Object.defineProperty(vm, key, {

+ 6 - 4
test/functional/fixtures/nested-props.html

@@ -29,15 +29,17 @@
                     this.a = data
                 },
                 data: {
+                    hidden: {
+                        a: 1,
+                        b: 2
+                    }
+                },
+                computed: {
                     d: {
                         $get: function () {
                             return this.msg + (this.a.b.c || '') + (this.a.c || '')
                         }
                     },
-                    hidden: {
-                        a: 1,
-                        b: 2
-                    },
                     sum: {
                         $get: function () {
                             return this.hidden.a + this.hidden.b

+ 3 - 1
test/functional/fixtures/share-data.html

@@ -41,7 +41,9 @@
             new Vue({
                 el: '#d',
                 data: {
-                    shared: shared,
+                    shared: shared
+                },
+                computed: {
                     source: {
                         $get: function () {
                             return JSON.stringify(this.shared)

+ 42 - 5
test/functional/fixtures/validation.html

@@ -12,22 +12,59 @@
     </head>
     <body>
         <div id="test">
-            email: <input type="text" v-model="a | email" v-class="valid:validation.email" name="email">
+            name: <input type="text" v-model="name | nameValidator" v-class="valid:validation.name" name="name">
+            email: <input type="text" v-model="email | emailValidator" v-class="valid:validation.email" name="email">
+            <a id="go" v-on="click:go">Go</a>
+            <ul>
+                <li class="user" v-repeat="users">
+                    {{name}} {{email}}
+                </li>
+            </ul>
         </div>
         <script>
             var RE = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
             var test = new Vue({
                 el: '#test',
                 filters: {
-                    email: function (val) {
-                        this.validation.email = val === '' || RE.test(val)
+                    nameValidator: function (val) {
+                        this.validation.name = !!val
+                        return val
+                    },
+                    emailValidator: function (val) {
+                        this.validation.email = RE.test(val)
                         return val
                     }
                 },
                 data: {
-                    a: 'hihi',
+                    name: '',
+                    email: '',
+                    users: [],
                     validation: {
-                        email: true
+                        email: false,
+                        name: false
+                    }
+                },
+                computed: {
+                    isValid: {
+                        $get: function () {
+                            var valid = true
+                            for (var key in this.validation) {
+                                if (!this.validation[key]) {
+                                    valid = false
+                                }
+                            }
+                            return valid
+                        }
+                    }
+                },
+                methods: {
+                    go: function () {
+                        if (this.isValid) {
+                            this.users.push({
+                                name: this.name,
+                                email: this.email
+                            })
+                        }
                     }
                 }
             })

+ 22 - 6
test/functional/specs/validation.js

@@ -1,23 +1,39 @@
-casper.test.begin('Validation', 4, function (test) {
+casper.test.begin('Validation', 9, function (test) {
     
     casper
     .start('./fixtures/validation.html')
     .then(function () {
         test.assertElementCount('.valid', 0)
-        this.sendKeys('input', '@hello.com')
+        this.sendKeys('input[name="name"]', 'haha')
     })
     .then(function () {
         test.assertElementCount('.valid', 1)
+        this.sendKeys('input[name="email"]', 'hello')
     })
+    .then(function () {
+        // email should be invalid
+        test.assertElementCount('.valid', 1)
+        this.sendKeys('input[name="email"]', 'heo@bar.com', { reset: true })
+    })
+    .then(function () {
+        // email should be valid now
+        test.assertField('email', 'heo@bar.com')
+        test.assertElementCount('.valid', 2)
+    })
+    // test edit/insertion when there are filters
     .thenEvaluate(function () {
-        document.querySelector('input').setSelectionRange(4,4)
+        document.querySelector('input[name="email"]').setSelectionRange(2,2)
     })
     .then(function () {
-        this.sendKeys('input', 'hoho')
+        this.sendKeys('input[name="email"]', 'll')
     })
     .then(function () {
-        test.assertElementCount('.valid', 1)
-        test.assertField('email', 'hihihoho@hello.com')
+        test.assertElementCount('.valid', 2)
+        test.assertField('email', 'hello@bar.com')
+    })
+    .thenClick('#go', function () {
+        test.assertElementCount('.user', 1)
+        test.assertSelectorHasText('.user', 'haha hello@bar.com')
     })
     .run(function () {
         test.done()