Browse Source

use null hash for directives and filters as well

Evan You 12 years ago
parent
commit
a86dd143fc

+ 5 - 6
src/compiler.js

@@ -11,7 +11,6 @@ var Emitter     = require('./emitter'),
     
     // cache methods
     slice       = [].slice,
-    makeHash    = utils.hash,
     extend      = utils.extend,
     hasOwn      = ({}).hasOwnProperty,
     def         = Object.defineProperty,
@@ -46,7 +45,7 @@ function Compiler (vm, options) {
     compiler.destroyed  = false
 
     // process and extend options
-    options = compiler.options = options || makeHash()
+    options = compiler.options = options || {}
     utils.processOptions(options)
 
     // copy compiler options
@@ -54,7 +53,7 @@ function Compiler (vm, options) {
     // repeat indicates this is a v-repeat instance
     compiler.repeat   = compiler.repeat || false
     // expCache will be shared between v-repeat instances
-    compiler.expCache = compiler.expCache || makeHash()
+    compiler.expCache = compiler.expCache || {}
 
     // initialize element
     var el = compiler.el = compiler.setupElement(options)
@@ -62,7 +61,7 @@ function Compiler (vm, options) {
 
     // set other compiler properties
     compiler.vm       = el.vue_vm = vm
-    compiler.bindings = makeHash()
+    compiler.bindings = utils.hash()
     compiler.dirs     = []
     compiler.deferred = []
     compiler.computed = []
@@ -86,7 +85,7 @@ function Compiler (vm, options) {
     // VM ---------------------------------------------------------------------
 
     // set VM properties
-    vm.$         = makeHash()
+    vm.$         = {}
     vm.$el       = el
     vm.$options  = options
     vm.$compiler = compiler
@@ -258,7 +257,7 @@ CompilerProto.setupObserver = function () {
 
     // a hash to hold event proxies for each root level key
     // so they can be referenced and removed later
-    observer.proxies = makeHash()
+    observer.proxies = {}
     observer._ctx = compiler.vm
 
     // add own listeners which trigger binding updates

+ 3 - 0
src/directives/html.js

@@ -1,6 +1,9 @@
 var guard = require('../utils').guard,
     slice = [].slice
 
+/**
+ *  Binding for innerHTML
+ */
 module.exports = {
 
     bind: function () {

+ 3 - 0
src/directives/if.js

@@ -1,5 +1,8 @@
 var utils    = require('../utils')
 
+/**
+ *  Manages a conditional child VM
+ */
 module.exports = {
 
     bind: function () {

+ 111 - 93
src/directives/index.js

@@ -1,111 +1,129 @@
 var utils      = require('../utils'),
     config     = require('../config'),
-    transition = require('../transition')
+    transition = require('../transition'),
+    directives = module.exports = utils.hash()
 
-module.exports = {
-
-    on        : require('./on'),
-    repeat    : require('./repeat'),
-    model     : require('./model'),
-    'if'      : require('./if'),
-    'with'    : require('./with'),
-    html      : require('./html'),
-    style     : require('./style'),
-    partial   : require('./partial'),
-    view      : require('./view'),
-
-    component : {
-        isLiteral: true,
-        bind: function () {
-            if (!this.el.vue_vm) {
-                this.childVM = new this.Ctor({
-                    el: this.el,
-                    parent: this.vm
-                })
-            }
-        },
-        unbind: function () {
-            if (this.childVM) {
-                this.childVM.$destroy()
-            }
+/**
+ *  Nest and manage a Child VM
+ */
+directives.component = {
+    isLiteral: true,
+    bind: function () {
+        if (!this.el.vue_vm) {
+            this.childVM = new this.Ctor({
+                el: this.el,
+                parent: this.vm
+            })
         }
     },
-
-    attr: {
-        bind: function () {
-            var params = this.vm.$options.paramAttributes
-            this.isParam = params && params.indexOf(this.arg) > -1
-        },
-        update: function (value) {
-            if (value || value === 0) {
-                this.el.setAttribute(this.arg, value)
-            } else {
-                this.el.removeAttribute(this.arg)
-            }
-            if (this.isParam) {
-                this.vm[this.arg] = utils.checkNumber(value)
-            }
+    unbind: function () {
+        if (this.childVM) {
+            this.childVM.$destroy()
         }
-    },
+    }
+}
 
-    text: {
-        bind: function () {
-            this.attr = this.el.nodeType === 3
-                ? 'nodeValue'
-                : 'textContent'
-        },
-        update: function (value) {
-            this.el[this.attr] = utils.guard(value)
-        }
+/**
+ *  Binding HTML attributes
+ */
+directives.attr = {
+    bind: function () {
+        var params = this.vm.$options.paramAttributes
+        this.isParam = params && params.indexOf(this.arg) > -1
     },
+    update: function (value) {
+        if (value || value === 0) {
+            this.el.setAttribute(this.arg, value)
+        } else {
+            this.el.removeAttribute(this.arg)
+        }
+        if (this.isParam) {
+            this.vm[this.arg] = utils.checkNumber(value)
+        }
+    }
+}
 
-    show: function (value) {
-        var el = this.el,
-            target = value ? '' : 'none',
-            change = function () {
-                el.style.display = target
-            }
-        transition(el, value ? 1 : -1, change, this.compiler)
+/**
+ *  Binding textContent
+ */
+directives.text = {
+    bind: function () {
+        this.attr = this.el.nodeType === 3
+            ? 'nodeValue'
+            : 'textContent'
     },
+    update: function (value) {
+        this.el[this.attr] = utils.guard(value)
+    }
+}
 
-    'class': function (value) {
-        if (this.arg) {
-            utils[value ? 'addClass' : 'removeClass'](this.el, this.arg)
-        } else {
-            if (this.lastVal) {
-                utils.removeClass(this.el, this.lastVal)
-            }
-            if (value) {
-                utils.addClass(this.el, value)
-                this.lastVal = value
-            }
+/**
+ *  Binding CSS display property
+ */
+directives.show = function (value) {
+    var el = this.el,
+        target = value ? '' : 'none',
+        change = function () {
+            el.style.display = target
         }
-    },
+    transition(el, value ? 1 : -1, change, this.compiler)
+}
 
-    cloak: {
-        isEmpty: true,
-        bind: function () {
-            var el = this.el
-            this.compiler.observer.once('hook:ready', function () {
-                el.removeAttribute(config.prefix + '-cloak')
-            })
+/**
+ *  Binding CSS classes
+ */
+directives['class'] = function (value) {
+    if (this.arg) {
+        utils[value ? 'addClass' : 'removeClass'](this.el, this.arg)
+    } else {
+        if (this.lastVal) {
+            utils.removeClass(this.el, this.lastVal)
         }
-    },
+        if (value) {
+            utils.addClass(this.el, value)
+            this.lastVal = value
+        }
+    }
+}
+
+/**
+ *  Only removed after the owner VM is ready
+ */
+directives.cloak = {
+    isEmpty: true,
+    bind: function () {
+        var el = this.el
+        this.compiler.observer.once('hook:ready', function () {
+            el.removeAttribute(config.prefix + '-cloak')
+        })
+    }
+}
 
-    ref: {
-        isLiteral: true,
-        bind: function () {
-            var id = this.expression
-            if (id) {
-                this.vm.$parent.$[id] = this.vm
-            }
-        },
-        unbind: function () {
-            var id = this.expression
-            if (id) {
-                delete this.vm.$parent.$[id]
-            }
+/**
+ *  Store a reference to self in parent VM's $
+ */
+directives.ref = {
+    isLiteral: true,
+    bind: function () {
+        var id = this.expression
+        if (id) {
+            this.vm.$parent.$[id] = this.vm
+        }
+    },
+    unbind: function () {
+        var id = this.expression
+        if (id) {
+            delete this.vm.$parent.$[id]
         }
     }
+}
 
-}
+directives.on      = require('./on')
+directives.repeat  = require('./repeat')
+directives.model   = require('./model')
+directives['if']   = require('./if')
+directives['with'] = require('./with')
+directives.html    = require('./html')
+directives.style   = require('./style')
+directives.partial = require('./partial')
+directives.view    = require('./view')

+ 3 - 0
src/directives/model.js

@@ -15,6 +15,9 @@ function getMultipleSelectOptions (select) {
         })
 }
 
+/**
+ *  Two-way binding for form input elements
+ */
 module.exports = {
 
     bind: function () {

+ 3 - 0
src/directives/on.js

@@ -1,5 +1,8 @@
 var utils    = require('../utils')
 
+/**
+ *  Binding for event listeners
+ */
 module.exports = {
 
     isFn: true,

+ 3 - 0
src/directives/partial.js

@@ -1,5 +1,8 @@
 var utils = require('../utils')
 
+/**
+ *  Binding for partials
+ */
 module.exports = {
 
     isLiteral: true,

+ 3 - 0
src/directives/repeat.js

@@ -1,6 +1,9 @@
 var utils      = require('../utils'),
     config     = require('../config')
 
+/**
+ *  Binding that manages VMs based on an Array
+ */
 module.exports = {
 
     bind: function () {

+ 3 - 0
src/directives/style.js

@@ -5,6 +5,9 @@ function camelReplacer (m) {
     return m[1].toUpperCase()
 }
 
+/**
+ *  Binding for CSS styles
+ */
 module.exports = {
 
     bind: function () {

+ 4 - 0
src/directives/view.js

@@ -1,3 +1,7 @@
+/**
+ *  Manages a conditional child VM using the
+ *  binding's value as the component ID.
+ */
 module.exports = {
 
     bind: function () {

+ 3 - 0
src/directives/with.js

@@ -1,5 +1,8 @@
 var utils = require('../utils')
 
+/**
+ *  Binding for inheriting data from parent VMs.
+ */
 module.exports = {
 
     bind: function () {

+ 132 - 126
src/filters.js

@@ -1,7 +1,71 @@
 var utils    = require('./utils'),
     get      = utils.get,
     slice    = [].slice,
-    QUOTE_RE = /^'.*'$/
+    QUOTE_RE = /^'.*'$/,
+    filters  = module.exports = utils.hash()
+
+/**
+ *  'abc' => 'Abc'
+ */
+filters.capitalize = function (value) {
+    if (!value && value !== 0) return ''
+    value = value.toString()
+    return value.charAt(0).toUpperCase() + value.slice(1)
+}
+
+/**
+ *  'abc' => 'ABC'
+ */
+filters.uppercase = function (value) {
+    return (value || value === 0)
+        ? value.toString().toUpperCase()
+        : ''
+}
+
+/**
+ *  'AbC' => 'abc'
+ */
+filters.lowercase = function (value) {
+    return (value || value === 0)
+        ? value.toString().toLowerCase()
+        : ''
+}
+
+/**
+ *  12345 => $12,345.00
+ */
+filters.currency = function (value, sign) {
+    if (!value && value !== 0) return ''
+    sign = sign || '$'
+    var s = Math.floor(value).toString(),
+        i = s.length % 3,
+        h = i > 0 ? (s.slice(0, i) + (s.length > 3 ? ',' : '')) : '',
+        f = '.' + value.toFixed(2).slice(-2)
+    return sign + h + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
+}
+
+/**
+ *  args: an array of strings corresponding to
+ *  the single, double, triple ... forms of the word to
+ *  be pluralized. When the number to be pluralized
+ *  exceeds the length of the args, it will use the last
+ *  entry in the array.
+ *
+ *  e.g. ['single', 'double', 'triple', 'multiple']
+ */
+filters.pluralize = function (value) {
+    var args = slice.call(arguments, 1)
+    return args.length > 1
+        ? (args[value - 1] || args[args.length - 1])
+        : (args[value - 1] || args[0] + 's')
+}
+
+/**
+ *  A special filter that takes a handler function,
+ *  wraps it so it only gets triggered on specific keypresses.
+ *
+ *  v-on only
+ */
 
 var keyCodes = {
     enter    : 13,
@@ -14,143 +78,89 @@ var keyCodes = {
     esc      : 27
 }
 
-var filters = module.exports = {
-
-    /**
-     *  'abc' => 'Abc'
-     */
-    capitalize: function (value) {
-        if (!value && value !== 0) return ''
-        value = value.toString()
-        return value.charAt(0).toUpperCase() + value.slice(1)
-    },
-
-    /**
-     *  'abc' => 'ABC'
-     */
-    uppercase: function (value) {
-        return (value || value === 0)
-            ? value.toString().toUpperCase()
-            : ''
-    },
-
-    /**
-     *  'AbC' => 'abc'
-     */
-    lowercase: function (value) {
-        return (value || value === 0)
-            ? value.toString().toLowerCase()
-            : ''
-    },
-
-    /**
-     *  12345 => $12,345.00
-     */
-    currency: function (value, sign) {
-        if (!value && value !== 0) return ''
-        sign = sign || '$'
-        var s = Math.floor(value).toString(),
-            i = s.length % 3,
-            h = i > 0 ? (s.slice(0, i) + (s.length > 3 ? ',' : '')) : '',
-            f = '.' + value.toFixed(2).slice(-2)
-        return sign + h + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
-    },
-
-    /**
-     *  args: an array of strings corresponding to
-     *  the single, double, triple ... forms of the word to
-     *  be pluralized. When the number to be pluralized
-     *  exceeds the length of the args, it will use the last
-     *  entry in the array.
-     *
-     *  e.g. ['single', 'double', 'triple', 'multiple']
-     */
-    pluralize: function (value) {
-        var args = slice.call(arguments, 1)
-        return args.length > 1
-            ? (args[value - 1] || args[args.length - 1])
-            : (args[value - 1] || args[0] + 's')
-    },
-
-    /**
-     *  A special filter that takes a handler function,
-     *  wraps it so it only gets triggered on specific keypresses.
-     */
-    key: function (handler, key) {
-        if (!handler) return
-        var code = keyCodes[key]
-        if (!code) {
-            code = parseInt(key, 10)
-        }
-        return function (e) {
-            if (e.keyCode === code) {
-                handler.call(this, e)
-            }
+filters.key = function (handler, key) {
+    if (!handler) return
+    var code = keyCodes[key]
+    if (!code) {
+        code = parseInt(key, 10)
+    }
+    return function (e) {
+        if (e.keyCode === code) {
+            handler.call(this, e)
         }
-    },
-
-    filterBy: function (arr, searchKey, delimiter, dataKey) {
+    }
+}
 
-        // allow optional `in` delimiter
-        // because why not
-        if (delimiter && delimiter !== 'in') {
-            dataKey = delimiter
-        }
+/**
+ *  Filter filter for v-repeat
+ */
+filters.filterBy = function (arr, searchKey, delimiter, dataKey) {
 
-        // get the search string
-        var search = stripQuotes(searchKey) || this.$get(searchKey)
-        if (!search) return arr
-        search = search.toLowerCase()
+    // allow optional `in` delimiter
+    // because why not
+    if (delimiter && delimiter !== 'in') {
+        dataKey = delimiter
+    }
 
-        // get the optional dataKey
-        dataKey = dataKey && (stripQuotes(dataKey) || this.$get(dataKey))
+    // get the search string
+    var search = stripQuotes(searchKey) || this.$get(searchKey)
+    if (!search) return arr
+    search = search.toLowerCase()
 
-        // convert object to array
-        if (!Array.isArray(arr)) {
-            arr = utils.objectToArray(arr)
-        }
+    // get the optional dataKey
+    dataKey = dataKey && (stripQuotes(dataKey) || this.$get(dataKey))
 
-        return arr.filter(function (item) {
-            return dataKey
-                ? contains(get(item, dataKey), search)
-                : contains(item, search)
-        })
+    // convert object to array
+    if (!Array.isArray(arr)) {
+        arr = utils.objectToArray(arr)
+    }
 
-    },
+    return arr.filter(function (item) {
+        return dataKey
+            ? contains(get(item, dataKey), search)
+            : contains(item, search)
+    })
 
-    orderBy: function (arr, sortKey, reverseKey) {
+}
 
-        var key = stripQuotes(sortKey) || this.$get(sortKey)
-        if (!key) return arr
+filters.filterBy.computed = true
 
-        // convert object to array
-        if (!Array.isArray(arr)) {
-            arr = utils.objectToArray(arr)
-        }
+/**
+ *  Sort fitler for v-repeat
+ */
+filters.orderBy = function (arr, sortKey, reverseKey) {
 
-        var order = 1
-        if (reverseKey) {
-            if (reverseKey === '-1') {
-                order = -1
-            } else if (reverseKey.charAt(0) === '!') {
-                reverseKey = reverseKey.slice(1)
-                order = this.$get(reverseKey) ? 1 : -1
-            } else {
-                order = this.$get(reverseKey) ? -1 : 1
-            }
-        }
+    var key = stripQuotes(sortKey) || this.$get(sortKey)
+    if (!key) return arr
 
-        // sort on a copy to avoid mutating original array
-        return arr.slice().sort(function (a, b) {
-            a = get(a, key)
-            b = get(b, key)
-            return a === b ? 0 : a > b ? order : -order
-        })
+    // convert object to array
+    if (!Array.isArray(arr)) {
+        arr = utils.objectToArray(arr)
+    }
 
+    var order = 1
+    if (reverseKey) {
+        if (reverseKey === '-1') {
+            order = -1
+        } else if (reverseKey.charAt(0) === '!') {
+            reverseKey = reverseKey.slice(1)
+            order = this.$get(reverseKey) ? 1 : -1
+        } else {
+            order = this.$get(reverseKey) ? -1 : 1
+        }
     }
 
+    // sort on a copy to avoid mutating original array
+    return arr.slice().sort(function (a, b) {
+        a = get(a, key)
+        b = get(b, key)
+        return a === b ? 0 : a > b ? order : -order
+    })
+
 }
 
+filters.orderBy.computed = true
+
 // Array filter helpers -------------------------------------------------------
 
 /**
@@ -177,8 +187,4 @@ function stripQuotes (str) {
     if (QUOTE_RE.test(str)) {
         return str.slice(1, -1)
     }
-}
-
-// mark computed filters
-filters.filterBy.computed = true
-filters.orderBy.computed = true
+}