- 开始时间:2020-03-25
- 目标主要版本:3.x
- 引用 issue:N/A
- 实现的 PR:N/A
摘要
- 破坏性:自定义元素白名单现在在模版编译过程中执行,应该通过编译器选项而不是运行时 config 来配置。
- 破坏性:将特殊的
isprop 的使用限制在保留的标签中。 - 引入一个新的
v-is指令,以支持 2.x 的使用情况,即在原生元素上使用is来解决原生 HTML 解析的限制。
基本范例
N/A
动机
- 以更有效的方式提供原生自定义元素支持。
- 改进对自定义内置元素的支持。
具体设计
自主定制元素
在 Vue 2.x 中,将标签作为自定义元素的白名单是通过 Vue.config.ignoreElements 完成的。缺点是,当使用这个配置选项时,需要在每次调用 vnode 创建时进行检查。
在 Vue3.0 中,这种检查是在模版编译时进行的。例如,给定以下模版:
<plastic-button></plastic-button>
默认生成的渲染函数代码是(伪代码):
function render() {const component_plastic_button = resolveComponent('plastic-button')return createVNode(component_plastic_button)}
如果没有找到名为 plastic-button 的组件,它将发出一个警告。
如果用户希望使用一个名为 plastic-button 的原生自定义元素,所需的生成代码应该是:
function render() {return createVNode('plastic-button') // render as native element}
指示编译器将 <plastic-button> 作为一个自定义元素:
如果使用构建步骤:将
isCustomElement选项传递给 Vue 模版编译器。如果使用vue-loader,这应该通过vue-loader的compilerOptions选项来传递:// in webpack configrules: [{test: /\.vue$/,use: 'vue-loader',options: {compilerOptions: {isCustomElement: tag => tag === 'plastic-button'}}}// ...]
如果使用 on-the-fly 模版编译,则通过 app.config 传递: ```javascript const app = Vue.createApp(/ … /)
app.config.isCustomElement = tag => tag === ‘plastic-button’
注意,运行时配置只影响运行时模版编译 —— 它不会影响预编译的模版。<a name="YMu7k"></a>## 自定义内置元素自定义元素规范提供了一种方法,通过向内置元素添加 `is` 属性,将自定义元素作为[自定义内置元素](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-customized-builtin-example)使用:```vue<button is="plastic-button">Click Me!</button>
Vue 对 is 这个特殊的 prop 的使用是在模拟原生属性在浏览器中普遍使用之前的作用。然而,在 2.x 中,它被解释为渲染一个名称为 plastic-button 的 Vue 组件。这就阻碍了上面提到的自定义内置元素的原生用法。
在 3.0 中,我们将 Vue 对 is prop 的特殊处理限制在 <component> 标签上。
- 当在保留的
<component>标签上使用时,它的行为与 2.x 中完全相同。 当使用在正常的组件上时,它的行为就像正常的 prop:
<foo is="bar" />
- 2.x 行为:渲染 bar 组件
- 3.x 行为:渲染 foo 组件并传递
isprop。
当在普通元素上使用时,它将作为
is选项传递给createElement调用,并作为一个原生特性呈现。这支持自定义的内置元素的使用。<button is="plastic-button">Click Me!</button>
- 2.x 行为:渲染
plastic-button组件 - 3.x 行为:通过调用渲染一个原生 button。
document.createElement('button', { is: 'plastic-button' })
v-is 用于 In-DOM 模版解析的解决方法
注意:本节只影响 Vue 模版直接写在页面 HTML 中的情况。
当使用 DOM 内模版时,模版要遵守本地 HTML 解析规则。一些 HTML 元素,如 <ul>、<ol>、<table> 和 <select> 对其内部可以出现的元素有限制,一些元素如 <li>、<tr> 和 <option> 只能出现在某些其他元素的内部。
在 2.x 中,我们建议通过在原生标签上使用 is prop 来解决这些限制:
<table><tr is="blog-post-row"></tr></table>
随着上面提出的 is 的行为变化,我们需要引入一个新的指令 v-is 来解决这些情况:
<table><tr v-is="'blog-post-row'"></tr></table>
注意,v-is 的功能就像一个动态的 2.x :is 绑定 —— 所以要通过它的注册名称来渲染一个组件,它的值应该是一个 JavaScript 字符串字面量。
缺点
N/A
备选方案
N/A
采纳策略
- compat 编译可以检测
config.ignoredElements的使用,并提供适当的警告和指导。 - codemod 可以自动将所有使用
is的 2.x 非<component>标签转为<component is>(用于 SFC 模版)或者v-is(用于 DOM 内模版)。
没有解决的问题
N/A
