- Start Date: 2020-03-25
- Target Major Version: 3.x
- Reference Issues: N/A
-
Breaking: Custom Elements whitelisting is now performed during template compilation, and should be configured via compiler options instead of runtime config.
-
Breaking: Restrict the special
isprop usage to the reserved<component>tag only. -
Introduce a new
v-isdirective to support 2.x use cases whereiswas used on native elements to work around native HTML parsing restrictions.
- Provide native custom element support in a more performant fashion
- Improve support for customized built-in elements.
In Vue 2.x, whitelisting tags as custom elements is done via Vue.config.ignoredElements. The downside is that when this config option is used, a check needs to be performed on every vnode creation call.
In Vue 3.0, this check is performed during template compilation. For example, given the following template:
<plastic-button></plastic-button>The default generated render function code is (pseudo code):
function render() {
const component_plastic_button = resolveComponent('plastic-button')
return createVNode(component_plastic_button)
}And it will emit a warning if no component named plastic-button was found.
If the user wishes to use a native custom element named plastic-button, the desired generated code should be:
function render() {
return createVNode('plastic-button') // render as native element
}To instruct the compiler to treat <plastic-button> as a custom element:
-
If using a build step: pass the
isCustomElementoption to the Vue template compiler. If usingvue-loader, this should be passed viavue-loader'scompilerOptionsoption:// in webpack config rules: [ { test: /\.vue$/, use: 'vue-loader', options: { compilerOptions: { isCustomElement: tag => tag === 'plastic-button' } } } // ... ]
-
If using on-the-fly template compilation, pass it via
app.config:const app = Vue.createApp(/* ... */) app.config.isCustomElement = tag => tag === 'plastic-button'
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:
<button is="plastic-button">Click Me!</button>Vue's usage of the is special prop was simulating what the native attribute does before it was made universally available in browsers. However, in 2.x it is interpreted as rendering a Vue component with the name plastic-button. This blocks the native usage of Customized Built-in Element mentioned above.
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 normal components, it will behave like a normal prop:
<foo is="bar" />
- 2.x behavior: renders the
barcomponent. - 3.x behavior: renders the
foocomponent and passing theisprop.
- 2.x behavior: renders the
-
When used on plain elements, it will be passed to the
createElementcall as theisoption, and also rendered as a native attribute. This supports the usage of customized built-in elements.<button is="plastic-button">Click Me!</button>
-
2.x behavior: renders the
plastic-buttoncomponent. -
3.x behavior: renders a native button by calling
document.createElement('button', { is: 'plastic-button' })
-
Note: this section only affects cases where Vue templates are directly written in the page's HTML.
When using in-DOM templates, the template is subject to native HTML parsing rules. Some HTML elements, such as <ul>, <ol>, <table> and <select> have restrictions on what elements can appear inside them, and some elements such as <li>, <tr>, and <option> can only appear inside certain other elements.
In 2.x we recommended working around with these restrictions by using the is prop on a native tag:
<table>
<tr is="blog-post-row"></tr>
</table>With the behavior change of is proposed above, we need to introduce a new directive v-is for working around these cases:
<table>
<tr v-is="'blog-post-row'"></tr>
</table>Note 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.
-
Compat build can detect use of
config.ignoredElementsand provide appropriate warning and guidance. -
A codemod can automatically convert all 2.x non
<component>tags withisusage to<component is>(for SFC templates) orv-is(for in-DOM templates).