Custom Elements Interop changes breaking

Overview

  • BREAKING: Custom elements whitelisting is now performed during template compilation, and should be configured via compiler options instead of runtime config.
  • BREAKING: Special prop usage is restricted to the reserved <component> tag only.
  • NEW: There is new v-is directive to support 2.x use cases where is was used on native elements to work around native HTML parsing restrictions.

In Vue 2.x, whitelisting tags as custom elements was done via Vue.config.ignoredElements:

  1. // This will make Vue ignore custom element defined outside of Vue
  2. // (e.g., using the Web Components APIs)
  3. Vue.config.ignoredElements = ['plastic-button']

In Vue 3.0, this check is performed during template compilation. To instruct the compiler to treat <plastic-button> as a custom element:

  • If using on-the-fly template compilation, pass it via app.config.isCustomElement:

    It’s important to note the runtime config only affects runtime template compilation - it won’t affect pre-compiled templates.

The Custom Elements specification provides a way to use custom elements as Customized Built-in Element by adding the is attribute to a built-in element:

  1. <button is="plastic-button">Click Me!</button>

In 3.0, we are limiting Vue’s special treatment of the is prop to the <component> tag only.

  • When used on the reserved <component> tag, it will behave exactly the same as in 2.x;

  • When used on plain elements, it will be passed to the createElement call as the is option, and also rendered as a native attribute. This supports the usage of customized built-in elements.

    • 2.x behavior: renders the plastic-button component.

    • 3.x behavior: renders a native button by calling

      1. document.createElement('button', { is: 'plastic-button' })

In Vue 2 we recommended working around with these restrictions by using the is prop on a native tag:

  1. <table>
  2. <tr is="blog-post-row"></tr>
  3. </table>

With the behavior change of is, we introduce a new directive v-is for working around these cases:

WARNING

v-is functions like a dynamic 2.x :is binding - so to render a component by its registered name, its value should be a JavaScript string literal:

  1. <!-- Incorrect, nothing will be rendered -->
  2. <tr v-is="blog-post-row"></tr>
  3. <!-- Correct -->
  4. <tr v-is="'blog-post-row'"></tr>
  • Replace config.ignoredElements with either vue-loader‘s compilerOptions (with the build step) or app.config.isCustomElement (with on-the-fly template compilation)