Browse Source

is attribute that are not resolved should be preserved for native custom elements (fix #2642)

Evan You 10 years ago
parent
commit
2fc82bf57d

+ 10 - 6
src/util/component.js

@@ -1,6 +1,6 @@
 import { warn } from './debug'
 import { resolveAsset } from './options'
-import { getAttr, getBindAttr } from './dom'
+import { getBindAttr } from './dom'
 
 export const 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)$/i
 export const reservedTagRE = /^(slot|partial|component)$/i
@@ -41,7 +41,7 @@ export function checkComponentAttr (el, options) {
     if (resolveAsset(options, 'components', tag)) {
       return { id: tag }
     } else {
-      var is = hasAttrs && getIsBinding(el)
+      var is = hasAttrs && getIsBinding(el, options)
       if (is) {
         return is
       } else if (process.env.NODE_ENV !== 'production') {
@@ -64,7 +64,7 @@ export function checkComponentAttr (el, options) {
       }
     }
   } else if (hasAttrs) {
-    return getIsBinding(el)
+    return getIsBinding(el, options)
   }
 }
 
@@ -72,14 +72,18 @@ export function checkComponentAttr (el, options) {
  * Get "is" binding from an element.
  *
  * @param {Element} el
+ * @param {Object} options
  * @return {Object|undefined}
  */
 
-function getIsBinding (el) {
+function getIsBinding (el, options) {
   // dynamic syntax
-  var exp = getAttr(el, 'is')
+  var exp = el.getAttribute('is')
   if (exp != null) {
-    return { id: exp }
+    if (resolveAsset(options, 'components', exp)) {
+      el.removeAttribute('is')
+      return { id: exp }
+    }
   } else {
     exp = getBindAttr(el, 'is')
     if (exp != null) {

+ 4 - 2
test/unit/specs/directives/internal/component_spec.js

@@ -534,9 +534,11 @@ describe('Component', function () {
   })
 
   it('already mounted warn', function () {
-    el.setAttribute('is', 'test')
     new Vue({
-      el: el
+      el: document.createElement('test'),
+      components: {
+        test: {}
+      }
     })
     expect('cannot mount component "test" on already mounted element').toHaveBeenWarned()
   })

+ 14 - 15
test/unit/specs/util/component_spec.js

@@ -3,42 +3,41 @@ var _ = require('src/util')
 describe('Util - component', function () {
   it('checkComponentAttr', function () {
     var el = document.createElement('component')
+    var mockOptions = { components: {
+      foo: {}
+    }}
 
     // <component> with no is attr
-    var res = _.checkComponentAttr(el)
+    var res = _.checkComponentAttr(el, mockOptions)
     expect(res).toBeUndefined()
 
     // static <component is="...">
     el.setAttribute('is', 'foo')
-    res = _.checkComponentAttr(el)
+    res = _.checkComponentAttr(el, mockOptions)
     expect(res.id).toBe('foo')
     expect(res.dynamic).toBeFalsy()
 
     // <component :is="...">
     el.setAttribute(':is', 'foo')
-    res = _.checkComponentAttr(el)
+    res = _.checkComponentAttr(el, mockOptions)
     expect(res.id).toBe('foo')
     expect(res.dynamic).toBe(true)
 
     // custom element, not defined
     el = document.createElement('test')
-    res = _.checkComponentAttr(el, {
-      components: {}
-    })
+    res = _.checkComponentAttr(el, mockOptions)
     expect(res).toBeUndefined()
 
     // custom element, defined
-    res = _.checkComponentAttr(el, {
-      components: { test: true }
-    })
-    expect(res.id).toBe('test')
+    el = document.createElement('foo')
+    res = _.checkComponentAttr(el, mockOptions)
+    expect(res.id).toBe('foo')
 
     // is on undefined custom element
+    // should be preserved in case it is a native custom element usage
     el = document.createElement('test2')
-    el.setAttribute('is', 'foo')
-    res = _.checkComponentAttr(el, {
-      components: {}
-    })
-    expect(res.id).toBe('foo')
+    el.setAttribute('is', 'bar')
+    res = _.checkComponentAttr(el, mockOptions)
+    expect(res).toBeUndefined()
   })
 })