diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js
index 2a31451bcd..29012f1f91 100644
--- a/src/.vuepress/config.js
+++ b/src/.vuepress/config.js
@@ -100,7 +100,8 @@ const sidebar = {
'migration/fragments',
'migration/render-function-api',
'migration/slots-unification',
- 'migration/keycode-modifiers'
+ 'migration/keycode-modifiers',
+ 'migration/custom-elements-interop'
]
},
{
diff --git a/src/api/directives.md b/src/api/directives.md
index c6ff396fa1..3aa44e51cb 100644
--- a/src/api/directives.md
+++ b/src/api/directives.md
@@ -453,3 +453,32 @@
- **See also:**
- [Data Binding Syntax - interpolations](../guide/template-syntax.html#text)
+
+## v-is
+
+> Note: this section only affects cases where Vue templates are directly written in the page's HTML.
+
+- **Expects:** string literal
+
+- **Limited to:** native HTML elements
+
+- **Usage:** When using in-DOM templates, the template is subject to native HTML parsing rules. Some HTML elements, such as `
`, ``, `
` and `
```
-The custom component `` will be hoisted out as invalid content, causing errors in the eventual rendered output. Fortunately, the `is` special attribute offers a workaround:
+The custom component `` will be hoisted out as invalid content, causing errors in the eventual rendered output. Fortunately, we can use `v-is` special directive as a workaround:
```html
-
+
```
+:::warning
+`v-is` value should be a JavaScript string literal:
+
+```html
+
+
+
+
+
+```
+
+:::
+
Also, HTML attribute names are case-insensitive, so browsers will interpret any uppercase characters as lowercase. That means when you’re using in-DOM templates, camelCased prop names and event handler parameters need to use their kebab-cased (hyphen-delimited) equivalents:
```js
diff --git a/src/guide/component-dynamic-async.md b/src/guide/component-dynamic-async.md
index 3619a4e8ab..d1b648d0a4 100644
--- a/src/guide/component-dynamic-async.md
+++ b/src/guide/component-dynamic-async.md
@@ -7,7 +7,7 @@
Earlier, we used the `is` attribute to switch between components in a tabbed interface:
```vue-html
-
+
```
When switching between these components though, you'll sometimes want to maintain their state or avoid re-rendering for performance reasons. For example, when expanding our tabbed interface a little:
@@ -26,7 +26,7 @@ Recreating dynamic components is normally useful behavior, but in this case, we'
```vue-html
-
+
```
diff --git a/src/guide/migration/custom-elements-interop.md b/src/guide/migration/custom-elements-interop.md
new file mode 100644
index 0000000000..efdda91626
--- /dev/null
+++ b/src/guide/migration/custom-elements-interop.md
@@ -0,0 +1,141 @@
+---
+types:
+ - breaking
+---
+
+# Custom Elements Interop changes {{ type }}
+
+# Overview
+
+- **BREAKING:** Custom elements whitelisting is now performed during template compilation, and should be configured via compiler options instead of runtime config.
+- **BREAKING:** Special `is` prop usage is restricted to the reserved `` 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.
+
+## Autonomous Custom Elements
+
+If we want to add a custom element defined outside of Vue (e.g. using the Web Components API), we need to 'instruct' Vue to treat it as a custom element. Let's use the following template as an example.
+
+```html
+
+```
+
+### 2.x Syntax
+
+In Vue 2.x, whitelisting tags as custom elements was done via `Vue.config.ignoredElements`:
+
+```js
+// This will make Vue ignore custom element defined outside of Vue
+// (e.g., using the Web Components APIs)
+
+Vue.config.ignoredElements = ['plastic-button']
+```
+
+### 3.x Syntax
+
+**In Vue 3.0, this check is performed during template compilation.** To instruct the compiler to treat `` as a custom element:
+
+- If using a build step: pass the `isCustomElement` option to the Vue template compiler. If using `vue-loader`, this should be passed via `vue-loader`'s `compilerOptions` option:
+
+ ```js
+ // 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.isCustomElement`:
+
+ ```js
+ const app = Vue.createApp({})
+ app.config.isCustomElement = tag => tag === 'plastic-button'
+ ```
+
+ It's important to note the runtime config only affects runtime template compilation - it won't affect pre-compiled templates.
+
+## Customized Built-in Elements
+
+The Custom Elements specification provides a way to use custom elements as [Customized Built-in Element](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-customized-builtin-example) by adding the `is` attribute to a built-in element:
+
+```html
+
+```
+
+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 was 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 `` tag only.
+
+- When used on the reserved `` tag, it will behave exactly the same as in 2.x;
+- When used on normal components, it will behave like a normal prop:
+
+ ```html
+
+ ```
+
+ - 2.x behavior: renders the `bar` component.
+ - 3.x behavior: renders the `foo` component and passing the `is` prop.
+
+- 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.
+
+ ```html
+
+ ```
+
+ - 2.x behavior: renders the `plastic-button` component.
+ - 3.x behavior: renders a native button by calling
+
+ ```js
+ document.createElement('button', { is: 'plastic-button' })
+ ```
+
+## `v-is` for In-DOM Template Parsing Workarounds
+
+> 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 `