Explorar o código

Component Change

- `v-component` now takes only a string value (the component id)
- `Vue.component()` now also registers the component id as a custom element
- add new directive: `v-with`, which can be used in combination with `v-component` or standalone
Evan You %!s(int64=12) %!d(string=hai) anos
pai
achega
04249e320a

+ 1 - 1
component.json

@@ -27,7 +27,7 @@
         "src/directives/repeat.js",
         "src/directives/on.js",
         "src/directives/model.js",
-        "src/directives/component.js"
+        "src/directives/with.js"
     ],
     "dependencies": {
         "component/emitter": "*"

+ 9 - 12
src/compiler.js

@@ -226,9 +226,11 @@ CompilerProto.compile = function (node, root) {
 
         // special attributes to check
         var repeatExp,
-            componentExp,
+            withKey,
             partialId,
-            directive
+            directive,
+            componentId = utils.attr(node, 'component') || tagName.toLowerCase(),
+            componentCtor = compiler.getOption('components', componentId)
 
         // It is important that we access these attributes
         // procedurally because the order matters.
@@ -244,21 +246,16 @@ CompilerProto.compile = function (node, root) {
             // repeat block cannot have v-id at the same time.
             directive = Directive.parse('repeat', repeatExp, compiler, node)
             if (directive) {
+                directive.Ctor = componentCtor
                 compiler.bindDirective(directive)
             }
 
-        // v-component has 2nd highest priority
-        } else if (!root && (componentExp = utils.attr(node, 'component'))) {
+        // v-with has 2nd highest priority
+        } else if (!root && ((withKey = utils.attr(node, 'with')) || componentCtor)) {
 
-            directive = Directive.parse('component', componentExp, compiler, node)
+            directive = Directive.parse('with', withKey || '', compiler, node)
             if (directive) {
-                // component directive is a bit different from the others.
-                // when it has no argument, it should be treated as a
-                // simple directive with its key as the argument.
-                if (componentExp.indexOf(':') === -1) {
-                    directive.isSimple = true
-                    directive.arg = directive.key
-                }
+                directive.Ctor = componentCtor
                 compiler.bindDirective(directive)
             }
 

+ 1 - 0
src/config.js

@@ -4,6 +4,7 @@ var prefix = 'v',
         'text',
         'repeat',
         'partial',
+        'with',
         'component',
         'component-id',
         'transition'

+ 1 - 1
src/directives/index.js

@@ -7,7 +7,7 @@ module.exports = {
     repeat    : require('./repeat'),
     model     : require('./model'),
     'if'      : require('./if'),
-    component : require('./component'),
+    'with'    : require('./with'),
 
     attr: function (value) {
         this.el.setAttribute(this.arg, value)

+ 3 - 4
src/directives/repeat.js

@@ -90,9 +90,8 @@ module.exports = {
             ctn  = self.container = el.parentNode
 
         // extract child VM information, if any
-        ViewModel       = ViewModel || require('../viewmodel')
-        var componentId = utils.attr(el, 'component')
-        self.ChildVM    = self.compiler.getOption('components', componentId) || ViewModel
+        ViewModel = ViewModel || require('../viewmodel')
+        self.Ctor = self.Ctor || ViewModel
 
         // extract transition information
         self.hasTrans   = el.hasAttribute(config.attrs.transition)
@@ -169,7 +168,7 @@ module.exports = {
             }, this.compiler)
         }
 
-        item = new this.ChildVM({
+        item = new this.Ctor({
             el: node,
             data: data,
             compilerOptions: {

+ 5 - 6
src/directives/component.js → src/directives/with.js

@@ -1,4 +1,4 @@
-var utils = require('../utils')
+var ViewModel
 
 module.exports = {
 
@@ -17,16 +17,15 @@ module.exports = {
     },
 
     build: function (value) {
-        var Ctor = this.compiler.getOption('components', this.arg)
-        if (!Ctor) utils.warn('unknown component: ' + this.arg)
-        var options = {
+        ViewModel = ViewModel || require('../viewmodel')
+        var Ctor = this.Ctor || ViewModel
+        this.component = new Ctor({
             el: this.el,
             data: value,
             compilerOptions: {
                 parentCompiler: this.compiler
             }
-        }
-        this.component = new Ctor(options)
+        })
     },
 
     unbind: function () {

+ 51 - 0
test/functional/fixtures/component.html

@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <title>Component</title>
+        <meta charset="utf-8">
+    </head>
+    <body>
+        <div id="test">
+            <!-- v-component + v-with -->
+            <div id="component-and-with" v-component="avatar" v-with="user"></div>
+
+            <!-- custom element + v-with -->
+            <avatar id="element-and-with" v-with="user"></avatar>
+
+            <!-- v-with alone -->
+            <div id="with" v-with="user">{{hi}} {{name}}</div>
+
+            <!-- v-component alone -->
+            <div id="component" v-component="simple"></div>
+
+            <!-- custom element alone -->
+            <simple id="element"></simple>
+        </div>
+        <script src="../../../dist/vue.js"></script>
+        <script>
+
+            Vue.config({debug: true})
+
+            Vue.component('avatar', {
+                template: '{{hi}} {{name}}',
+                ready: function () {
+                    console.log(JSON.stringify(this))
+                }
+            })
+
+            Vue.component('simple', {
+                template: '{{hi}} {{user.name}}'
+            })
+
+            var app = new Vue({
+                el: '#test',
+                data: {
+                    hi: '123',
+                    user: {
+                        name: 'Jack'
+                    }
+                }
+            })
+        </script>
+    </body>
+</html>

+ 1 - 1
test/functional/fixtures/extend.html

@@ -12,7 +12,7 @@
             <div class="filter">{{filterMsg | nodigits}}</div>
             <div class="partial" v-partial="partial-test"></div>
             <div class="vm" v-component="vm-test">{{vmMsg}}</div>
-            <div class="vm-w-model" v-component="vm-w-model:vmData">{{selfMsg + msg}}</div>
+            <div class="vm-w-model" v-component="vm-w-model" v-with="vmData">{{selfMsg + msg}}</div>
         </div>
         <div id="child">
             <div class="cvm" v-component="vm-test">{{vmMsg}}</div>

+ 17 - 0
test/functional/specs/component.js

@@ -0,0 +1,17 @@
+casper.test.begin('Components', 5, function (test) {
+    
+    casper
+    .start('./fixtures/component.html')
+    .then(function () {
+        var expected = '123 Jack'
+        test.assertSelectorHasText('#component-and-with', expected)
+        test.assertSelectorHasText('#element-and-with', expected)
+        test.assertSelectorHasText('#component', expected)
+        test.assertSelectorHasText('#with', expected)
+        test.assertSelectorHasText('#element', expected)
+    })
+    .run(function () {
+        test.done()
+    })
+
+})

+ 11 - 14
test/unit/specs/directives.js

@@ -511,7 +511,7 @@ describe('UNIT: Directives', function () {
 
     describe('component', function () {
         
-        it('should work with no args', function () {
+        it('should create a child viewmodel with given constructor', function () {
             var testId = 'component-test'
             mock(testId, '<div v-component="' + testId + '"></div>')
             var t = new Vue({
@@ -528,25 +528,22 @@ describe('UNIT: Directives', function () {
             assert.strictEqual(t.$el.querySelector('span').textContent, '123')
         })
 
-        it('should work with arg (passed-in model from parent)', function () {
-            var testId = 'component-test-2'
-            mock(testId, '<div v-component="' + testId + ':options.test"></div>')
+    })
+
+    describe('with', function () {
+        
+        it('should create a child viewmodel with given data', function () {
+            var testId = 'with-test'
+            mock(testId, '<span v-with="test">{{msg}}</span>')
             var t = new Vue({
                 el: '#' + testId,
                 data: {
-                    options: {
-                        test: {
-                            msg: '123'
-                        }
-                    }
-                },
-                components: {
-                    'component-test-2': {
-                        template: '<span>{{msg}}</span>'
+                    test: {
+                        msg: testId
                     }
                 }
             })
-            assert.strictEqual(t.$el.querySelector('span').textContent, '123')
+            assert.strictEqual(t.$el.querySelector('span').textContent, testId)
         })
 
     })