Skip to content

Commit 5cf33ae

Browse files
committed
support "is" on any element
1 parent d0241f2 commit 5cf33ae

File tree

9 files changed

+68
-39
lines changed

9 files changed

+68
-39
lines changed

src/compiler/transclude.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,15 @@ function transcludeTemplate (el, options) {
8383
// single nested component
8484
tag === 'component' ||
8585
_.resolveAsset(options, 'components', tag) ||
86-
replacer.hasAttribute(config.prefix + 'component') ||
86+
replacer.hasAttribute('is') ||
87+
replacer.hasAttribute(':is') ||
88+
replacer.hasAttribute('bind-is') ||
8789
// element directive
8890
_.resolveAsset(options, 'elementDirectives', tag) ||
8991
// for block
90-
replacer.hasAttribute(config.prefix + 'for')
92+
replacer.hasAttribute(config.prefix + 'for') ||
93+
// if block
94+
replacer.hasAttribute(config.prefix + 'if')
9195
) {
9296
return frag
9397
} else {

src/util/component.js

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,47 @@ var _ = require('./index')
1212
exports.commonTagRE = /^(div|p|span|img|a|b|i|br|ul|ol|li|h1|h2|h3|h4|h5|h6|code|pre|table|th|td|tr|form|label|input|select|option|nav|article|section|header|footer)$/
1313
exports.checkComponent = function (el, options) {
1414
var tag = el.tagName.toLowerCase()
15-
if (tag === 'component') {
16-
// dynamic syntax
17-
var exp = el.getAttribute('is')
18-
if (exp != null) {
19-
el.removeAttribute('is')
20-
return { id: exp }
21-
} else {
22-
exp = _.getBindAttr(el, 'is')
23-
if (exp != null) {
24-
return { id: exp, dynamic: true }
25-
}
26-
}
27-
} else if (!exports.commonTagRE.test(tag)) {
15+
var hasAttrs = el.hasAttributes()
16+
if (!exports.commonTagRE.test(tag) && tag !== 'component') {
2817
if (_.resolveAsset(options, 'components', tag)) {
2918
return { id: tag }
30-
} else if (process.env.NODE_ENV !== 'production') {
31-
if (tag.indexOf('-') > -1 ||
32-
/HTMLUnknownElement/.test(Object.prototype.toString.call(el))) {
33-
_.warn(
34-
'Unknown custom element: <' + tag + '> - did you ' +
35-
'register the component correctly?'
36-
)
19+
} else {
20+
var is = hasAttrs && getIsBinding(el)
21+
if (is) {
22+
return is
23+
} else if (process.env.NODE_ENV !== 'production') {
24+
if (tag.indexOf('-') > -1 ||
25+
/HTMLUnknownElement/.test(Object.prototype.toString.call(el))) {
26+
_.warn(
27+
'Unknown custom element: <' + tag + '> - did you ' +
28+
'register the component correctly?'
29+
)
30+
}
3731
}
3832
}
33+
} else if (hasAttrs) {
34+
return getIsBinding(el)
3935
}
40-
/* eslint-disable no-cond-assign */
41-
if (tag = _.attr(el, 'component')) {
42-
/* eslint-enable no-cond-assign */
43-
return { id: tag }
36+
}
37+
38+
/**
39+
* Get "is" binding from an element.
40+
*
41+
* @param {Element} el
42+
* @return {Object|undefined}
43+
*/
44+
45+
function getIsBinding (el) {
46+
// dynamic syntax
47+
var exp = el.getAttribute('is')
48+
if (exp != null) {
49+
el.removeAttribute('is')
50+
return { id: exp }
51+
} else {
52+
exp = _.getBindAttr(el, 'is')
53+
if (exp != null) {
54+
return { id: exp, dynamic: true }
55+
}
4456
}
4557
}
4658

test/unit/specs/api/lifecycle_spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,12 @@ if (_.inBrowser) {
253253

254254
it('safely teardown partial compilation', function () {
255255
var vm = new Vue({
256-
template: '<div v-component="dialog"><div v-partial="hello"></div></div>',
256+
template: '<test><partial name="hello"></partial></test>',
257257
partials: {
258258
hello: 'Hello {{name}}'
259259
},
260260
components: {
261-
dialog: {
261+
test: {
262262
template: '<slot></slot>'
263263
}
264264
}

test/unit/specs/compiler/transclude_spec.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ if (_.inBrowser) {
6767
res = transclude(el, options)
6868
expect(res instanceof DocumentFragment).toBe(true)
6969

70-
// single component: v-component
71-
options.template = '<div v-component="test"></div>'
70+
// single component: is
71+
options.template = '<div is="test"></div>'
7272
res = transclude(el, options)
7373
expect(res instanceof DocumentFragment).toBe(true)
7474

@@ -82,6 +82,11 @@ if (_.inBrowser) {
8282
options.template = '<div v-for="item in list"></div>'
8383
res = transclude(el, options)
8484
expect(res instanceof DocumentFragment).toBe(true)
85+
86+
// v-if
87+
options.template = '<div v-if="ok"></div>'
88+
res = transclude(el, options)
89+
expect(res instanceof DocumentFragment).toBe(true)
8590
})
8691

8792
it('direct fragment instance', function () {

test/unit/specs/directives/internal/ref_spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ if (_.inBrowser) {
3434
expect(vm.$.test2.$options.id).toBe('test2')
3535
})
3636

37-
it('with dynamic v-component', function (done) {
37+
it('with dynamic component', function (done) {
3838
var vm = new Vue({
3939
el: el,
4040
components: components,

test/unit/specs/directives/public/component_spec.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ if (_.inBrowser) {
4848
expect(el.innerHTML).toBe('<p>123</p>')
4949
})
5050

51-
it('allow v-component on table elements', function () {
51+
it('"is" on table elements', function () {
5252
var vm = new Vue({
5353
el: el,
54-
template: '<table><tbody><tr v-component="test"></tr></tbody></table>',
54+
template: '<table><tbody><tr is="test"></tr></tbody></table>',
5555
components: {
5656
test: {
5757
data: function () {
@@ -239,7 +239,7 @@ if (_.inBrowser) {
239239
vm.ok = true
240240
_.nextTick(function () {
241241
expect(vm.$children.length).toBe(1)
242-
expect(vm._directives.length).toBe(3) // v-if, v-component, v-text
242+
expect(vm._directives.length).toBe(3) // v-if, component, v-text
243243
expect(el.textContent).toBe('hello world')
244244
done()
245245
})
@@ -483,7 +483,7 @@ if (_.inBrowser) {
483483
})
484484

485485
it('already mounted warn', function () {
486-
el.setAttribute('v-component', 'test')
486+
el.setAttribute('is', 'test')
487487
new Vue({
488488
el: el
489489
})
@@ -494,7 +494,7 @@ if (_.inBrowser) {
494494
expect(function () {
495495
new Vue({
496496
el: el,
497-
template: '<div v-component="non-existent"></div>'
497+
template: '<div is="non-existent"></div>'
498498
})
499499
}).not.toThrow()
500500
})

test/unit/specs/directives/public/for/for_spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,13 @@ if (_.inBrowser) {
106106
assertMutations(vm, el, done)
107107
})
108108

109-
it('v-component', function (done) {
109+
it('is component', function (done) {
110110
var vm = new Vue({
111111
el: el,
112112
data: {
113113
items: [{a: 1}, {a: 2}]
114114
},
115-
template: '<p v-for="item in items" v-component="test" bind-index="$index" bind-item="item"></p>',
115+
template: '<p v-for="item in items" is="test" bind-index="$index" bind-item="item"></p>',
116116
components: {
117117
test: {
118118
props: ['index', 'item'],

test/unit/specs/directives/public/if_spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ if (_.inBrowser) {
6565
})
6666
})
6767

68-
it('v-if + v-component', function (done) {
68+
it('v-if + component', function (done) {
6969
var attachSpy = jasmine.createSpy()
7070
var detachSpy = jasmine.createSpy()
7171
var readySpy = jasmine.createSpy()

test/unit/specs/util/component_spec.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,13 @@ describe('Util - component', function () {
3333
components: { test: true }
3434
})
3535
expect(res.id).toBe('test')
36+
37+
// is on undefined custom element
38+
el = document.createElement('test2')
39+
el.setAttribute('is', 'what')
40+
res = _.checkComponent(el, {
41+
components: {}
42+
})
43+
expect(res.id).toBe('what')
3644
})
3745
})

0 commit comments

Comments
 (0)