瀏覽代碼

subclasses can now use asset registration methods too

Evan You 12 年之前
父節點
當前提交
2429b37ab8
共有 5 個文件被更改,包括 72 次插入84 次删除
  1. 3 2
      src/compiler.js
  2. 38 49
      src/main.js
  3. 7 15
      src/utils.js
  4. 10 13
      test/functional/fixtures/extend.html
  5. 14 5
      test/unit/specs/api.js

+ 3 - 2
src/compiler.js

@@ -627,11 +627,12 @@ CompilerProto.markComputed = function (binding, value) {
  */
 CompilerProto.getOption = function (type, id) {
     var opts = this.options,
-        parent = this.parentCompiler
+        parent = this.parentCompiler,
+        globalAssets = config.globalAssets
     return (opts[type] && opts[type][id]) || (
         parent
             ? parent.getOption(type, id)
-            : utils[type] && utils[type][id]
+            : globalAssets[type] && globalAssets[type][id]
     )
 }
 

+ 38 - 49
src/main.js

@@ -1,8 +1,36 @@
 var config      = require('./config'),
     ViewModel   = require('./viewmodel'),
-    directives  = require('./directives'),
-    filters     = require('./filters'),
-    utils       = require('./utils')
+    utils       = require('./utils'),
+    makeHash    = utils.hash,
+    assetTypes  = ['directive', 'filter', 'partial', 'transition', 'component']
+
+ViewModel.options = config.globalAssets = {
+    directives  : require('./directives'),
+    filters     : require('./filters'),
+    partials    : makeHash(),
+    transitions : makeHash(),
+    components  : makeHash()
+}
+
+/**
+ *  Expose asset registration methods
+ */
+assetTypes.forEach(function (type) {
+    ViewModel[type] = function (id, value) {
+        var hash = this.options[type + 's']
+        if (!hash) {
+            hash = this.options[type + 's'] = makeHash()
+        }
+        if (!value) return hash[id]
+        if (type === 'partial') {
+            value = utils.toFragment(value)
+        } else if (type === 'component') {
+            value = utils.toConstructor(value)
+        }
+        hash[id] = value
+        return this
+    }
+})
 
 /**
  *  Set config options
@@ -20,51 +48,6 @@ ViewModel.config = function (opts, val) {
     return this
 }
 
-/**
- *  Allows user to register/retrieve a directive definition
- */
-ViewModel.directive = function (id, fn) {
-    if (!fn) return directives[id]
-    directives[id] = fn
-    return this
-}
-
-/**
- *  Allows user to register/retrieve a filter function
- */
-ViewModel.filter = function (id, fn) {
-    if (!fn) return filters[id]
-    filters[id] = fn
-    return this
-}
-
-/**
- *  Allows user to register/retrieve a ViewModel constructor
- */
-ViewModel.component = function (id, Ctor) {
-    if (!Ctor) return utils.components[id]
-    utils.components[id] = utils.toConstructor(Ctor)
-    return this
-}
-
-/**
- *  Allows user to register/retrieve a template partial
- */
-ViewModel.partial = function (id, partial) {
-    if (!partial) return utils.partials[id]
-    utils.partials[id] = utils.toFragment(partial)
-    return this
-}
-
-/**
- *  Allows user to register/retrieve a transition definition object
- */
-ViewModel.transition = function (id, transition) {
-    if (!transition) return utils.transitions[id]
-    utils.transitions[id] = transition
-    return this
-}
-
 /**
  *  Expose internal modules for plugins
  */
@@ -133,6 +116,12 @@ function extend (options) {
     ExtendedVM.extend = extend
     ExtendedVM.super = ParentVM
     ExtendedVM.options = options
+
+    // allow extended VM to add its own assets
+    assetTypes.forEach(function (type) {
+        ExtendedVM[type] = ViewModel[type]
+    })
+
     return ExtendedVM
 }
 
@@ -150,7 +139,7 @@ function extend (options) {
  *  extension option, but only as an instance option.
  */
 function inheritOptions (child, parent, topLevel) {
-    child = child || utils.hash()
+    child = child || makeHash()
     if (!parent) return child
     for (var key in parent) {
         if (key === 'el' || key === 'methods') continue

+ 7 - 15
src/utils.js

@@ -12,23 +12,15 @@ var defer =
     window.webkitRequestAnimationFrame ||
     window.setTimeout
 
-/**
- *  Create a prototype-less object
- *  which is a better hash/map
- */
-function makeHash () {
-    return Object.create(null)
-}
-
 var utils = module.exports = {
 
-    hash: makeHash,
-
-    // global storage for user-registered
-    // vms, partials and transitions
-    components  : makeHash(),
-    partials    : makeHash(),
-    transitions : makeHash(),
+    /**
+     *  Create a prototype-less object
+     *  which is a better hash/map
+     */
+    hash: function () {
+        return Object.create(null)
+    },
 
     /**
      *  get an attribute and remove it.

+ 10 - 13
test/functional/fixtures/extend.html

@@ -26,19 +26,6 @@
                 data: {
                     vmMsg: 'component works'
                 }
-            },
-            'vm-w-model': {
-                data : {
-                    selfMsg: 'component with model '
-                }
-            }
-        },
-        partials: {
-            'partial-test': '{{partialMsg}}'
-        },
-        directives: {
-            hola: function (value) {
-                this.el.innerHTML = value + ' works'
             }
         },
         filters: {
@@ -47,6 +34,16 @@
             }
         }
     })
+    // test late asset addition
+    T.directive('hola', function (value) {
+        this.el.innerHTML = value + ' works'
+    })
+    T.partial('partial-test', '{{partialMsg}}')
+    T.component('vm-w-model', {
+        data : {
+            selfMsg: 'component with model '
+        }
+    })
     var C = T.extend({
         created: function () {
             log.textContent += ' C created'  

+ 14 - 5
test/unit/specs/api.js

@@ -1,6 +1,7 @@
 describe('UNIT: API', function () {
 
     var utils = require('vue/src/utils'),
+        assets = require('vue/src/config').globalAssets,
         nextTick = utils.nextTick
 
     describe('config()', function () {
@@ -176,12 +177,12 @@ describe('UNIT: API', function () {
 
         it('should register a Component constructor', function () {
             Vue.component(testId, Test)
-            assert.strictEqual(utils.components[testId], Test)
+            assert.strictEqual(assets.components[testId], Test)
         })
 
         it('should also work with option objects', function () {
             Vue.component(testId2, opts)
-            assert.ok(utils.components[testId2].prototype instanceof Vue)
+            assert.ok(assets.components[testId2].prototype instanceof Vue)
         })
 
         it('should retrieve the VM if has only one arg', function () {
@@ -212,14 +213,14 @@ describe('UNIT: API', function () {
 
         it('should register the partial as a dom fragment', function () {
             Vue.partial(testId, partial)
-            var converted = utils.partials[testId]
+            var converted = assets.partials[testId]
             assert.ok(converted instanceof window.DocumentFragment)
             assert.strictEqual(converted.querySelector('.partial-test a').innerHTML, '{{hi}}')
             assert.strictEqual(converted.querySelector('span').innerHTML, 'hahaha')
         })
 
         it('should retrieve the partial if has only one arg', function () {
-            assert.strictEqual(utils.partials[testId], Vue.partial(testId))
+            assert.strictEqual(assets.partials[testId], Vue.partial(testId))
         })
 
         it('should work with v-partial as a directive', function () {
@@ -254,7 +255,7 @@ describe('UNIT: API', function () {
 
         it('should register a transition object', function () {
             Vue.transition(testId, transition)
-            assert.strictEqual(utils.transitions[testId], transition)
+            assert.strictEqual(assets.transitions[testId], transition)
         })
 
         it('should retrieve the transition if has only one arg', function () {
@@ -341,6 +342,14 @@ describe('UNIT: API', function () {
             assert.notOk(child.test3.hi)
         })
 
+        it('should allow subclasses to attach private assets', function () {
+            var Sub = Vue.extend({})
+            Sub.component('test', {})
+            assert.strictEqual(Sub.options.components.test.super, Vue)
+            Sub.partial('test', '123')
+            assert.ok(Sub.options.partials.test instanceof window.DocumentFragment)
+        })
+
         describe('Options', function () {
 
             describe('methods', function () {