Vue 3.1.0 的 beta 版发布
编辑 | KnowsCount
QC-L
本次 beta 版本带来了一些有趣的新特性和错误修复。
新特性
onServerPrefetch
:composition-api 版本的 serverPrefetch组件级别的 compilerOptions
@vue/compiler-core
支持了空白字符处理策略支持通过 app.config.compilerOptions
配置运行时的编译器devtools 改进了对 KeepAlive 的支持 支持通过 is="vue:xxx"
将普通元素转换为组件
onServerPrefetch
具体请参见 PR 3070[1] 和 PR 2902[2]
此特性主要解决在 composition-api
情况下没有提供 serverPrefetch 生命周期钩子函数的问题。
这个钩子函数名为 onServerPrefetch
。
如果你也这方面的需求,可以尝试升级至 3.1.0-beta
版
相关讨论:
vue-apollo[3] app-extension-apollo[4]
@vue/complier-core
支持了空白字符处理策略
具体内容请参阅 PR 1600[5] 和 v2 原有效果[6]。
应用
我们来测试下此策略:
先装个 beta 版本的 @vue/compiler-core
yarn add @vue/compiler-core@beta
新建 index.js
文件
const core = require('@vue/compiler-core')
const { baseCompile: complie } = core
const { ast } = complie(` foo \n bar baz `, {
whitespace: 'preserve' // condense
})
console.log(ast.children[0])
console.log(ast.children[0].content)
大概效果如示例所示:
<!-- 源代码 -->
foo \n bar baz
<!-- whitespace: 'preserve' -->
foo \n bar baz
<!-- whitespace: 'condense' -->
foo bar baz
源码
原本只在 compiler-core
的 parse
文件中的 defaultParserOptions
提供了默认的 condense
情况
whitespace: 'condense'
在 compiler-core
的 options 文件中新增了 whitespace
:
whitespace?: 'preserve' | 'condense'
相关链接:
PR 1600[7] stackoverflow[8] vue 2.0/compiler[9] vue 2.0 的 `whitespace`[10] vue 2.0 的 PR[11]
通过 is="vue:xxx"
支持普通元素的转换
这条特性的更新,从源码上看,兼容了两种类型。
弃用的 v-is
指令is="vue:xxx"
的属性
源码
let { tag } = node
// 1. 动态组件
const isExplicitDynamic = isComponentTag(tag)
const isProp =
findProp(node, 'is') || (!isExplicitDynamic && findDir(node, 'is'))
if (isProp) {
if (!isExplicitDynamic && isProp.type === NodeTypes.ATTRIBUTE) {
// <button is="vue:xxx">
// 如果不是 <component>,仅仅是 "vue:" 开头
// 在解析阶段会被视为组件,并在此处进行
// tag 被重新赋值为 "vue:" 以后的内容
tag = isProp.value!.content.slice(4)
} else {
const exp =
isProp.type === NodeTypes.ATTRIBUTE
? isProp.value && createSimpleExpression(isProp.value.content, true)
: isProp.exp
if (exp) {
return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
exp
])
}
}
}
// 当 tag 为 <component>,或者 is="vue:xxx",跳过后续处理
if (
name === 'is' &&
(isComponentTag(tag) || (value && value.content.startsWith('vue:')))
) {
continue
}
// ...
上述代码中有几个点:
首先 isComponentTag
,用以判断是否为动态组件:
// 此方法用于判断是否为动态组件
function isComponentTag(tag: string) {
return tag[0].toLowerCase() + tag.slice(1) === 'component'
}
查找是否含有 is
属性
// 先查属性
findProp(node, 'is')
// 否则判断是不是动态组件,如果不是,判断是不是指令
!isExplicitDynamic && findDir(node, 'is')
其主要原因是,两者的 AST 结构不同。
相关链接:
Support casting plain element[12] Custom Elements Interop[13]
附上 ChangeLog
Bug 修复
兼容: 处理并针对 config.optionMergeStrategies 实现告警 (94e69fd[14]) compiler-core: 当注释选项启用时,在生产环境下将保留注释 (e486254[15]) hmr: 禁止从组件类型中移除 __file 的 key 值 (9db3cbb[16]) hydration: 修复 asnyc 组件 hydrated 前的更新 (#3563[17]) (c8d9683[18]), closes #3560[19] reactivity: 修复 readonly + reactive Map 的追溯 (#3604[20]) (5036c51[21]), closes #3602[22] runtime-core: 确保声明 props 的 key 永远存在 (4fe4de0[23]), closes #3288[24] runtime-core: computed 监听多个 source (#3066[25]) (e7300eb[26]), closes #3068[27] Teleport: 避免改变对 vnode.dynamicChildren 的引用 (#3642[28]) (43f7815[29]), closes #3641[30] watch: 避免遍历 non-plain 对象 (62b8f4a[31]) watch: this.$watch 应该支持监听键路径 (870f2a7[32])
特性
onServerPrefetch (#3070[33]) (349eb0f[34]) 运行时编译器支持了组件级 compilerOptions
(ce0bbe0[35])compiler-core: whitespace 处理策略 (dee3d6a[36]) config: 利用 app.config.compilerOptions
支持配置运行时编译器 (091e6d6[37])devtools: 升级对 KeepAlive 的支持 (03ae300[38]) 支持利用 is="vue:xxx" 将 plain 元素 cast 到组件 (af9e699[39])
性能提升
仅当实际改变时才会触发 $attrs 的更新 (5566d39[40]) compiler: 解析结束标签时跳过不必要的检查 (048ac29[41])
参考资料
PR 3070: https://github.com/vuejs/vue-next/pull/3070
[2]PR 2902: https://github.com/vuejs/vue-next/pull/2902
[3]vue-apollo: https://github.com/vuejs/vue-apollo/issues/1102
[4]app-extension-apollo: https://github.com/quasarframework/app-extension-apollo/issues/51#issuecomment-791977057
[5]PR 1600: https://github.com/vuejs/vue-next/pull/1600
[6]v2 原有效果: https://github.com/vuejs/vue/blob/dev/flow/compiler.js#L10
[7]PR 1600: https://github.com/vuejs/vue-next/pull/1600
[8]stackoverflow: https://stackoverflow.com/questions/64432182/vue-3-removes-white-space-between-inline-block-elements
[9]vue 2.0/compiler: https://github.com/vuejs/vue/blob/dev/flow/compiler.js#L10
[10]vue 2.0 的 whitespace
: https://github.com/vuejs/vue/issues/9208#issuecomment-450012518
vue 2.0 的 PR: https://github.com/vuejs/vue/commit/e1abedb9e66b21da8a7e93e175b9dabe334dfebd
[12]Support casting plain element: https://github.com/vuejs/vue-next/commit/af9e6999e1779f56b5cf827b97310d8e4e1fe5ec
[13]Custom Elements Interop: https://v3.vuejs.org/guide/migration/custom-elements-interop.html
[14]94e69fd: https://github.com/vuejs/vue-next/commit/94e69fd3896214da6ff8b9fb09ad942c598053c7
[15]e486254: https://github.com/vuejs/vue-next/commit/e4862544310a4187dfc8b3a49944700888bb60e3
[16]9db3cbb: https://github.com/vuejs/vue-next/commit/9db3cbbfc1a072675a8d0e53edf3869af115dc60
[17]#3563: https://github.com/vuejs/vue-next/issues/3563
[18]c8d9683: https://github.com/vuejs/vue-next/commit/c8d96837b871d7ad34cd73b4669338be5fdd59fd
[19]#3560: https://github.com/vuejs/vue-next/issues/3560
[20]#3604: https://github.com/vuejs/vue-next/issues/3604
[21]5036c51: https://github.com/vuejs/vue-next/commit/5036c51cb78435c145ffea5e82cd620d0d056ff7
[22]#3602: https://github.com/vuejs/vue-next/issues/3602
[23]4fe4de0: https://github.com/vuejs/vue-next/commit/4fe4de0a49ffc2461b0394e74674af38ff5e2a20
[24]#3288: https://github.com/vuejs/vue-next/issues/3288
[25]#3066: https://github.com/vuejs/vue-next/issues/3066
[26]e7300eb: https://github.com/vuejs/vue-next/commit/e7300eb47960a153311d568d7976ac5256eb6297
[27]#3068: https://github.com/vuejs/vue-next/issues/3068
[28]#3642: https://github.com/vuejs/vue-next/issues/3642
[29]43f7815: https://github.com/vuejs/vue-next/commit/43f78151bfdff2103a9be25e66e3f3be68d03a08
[30]#3641: https://github.com/vuejs/vue-next/issues/3641
[31]62b8f4a: https://github.com/vuejs/vue-next/commit/62b8f4a39ca56b48a8c8fdf7e200cb80735e16ae
[32]870f2a7: https://github.com/vuejs/vue-next/commit/870f2a7ba35245fd8c008d2ff666ea130a7e4704
[33]#3070: https://github.com/vuejs/vue-next/issues/3070
[34]349eb0f: https://github.com/vuejs/vue-next/commit/349eb0f0ad78f9cb491278eb4c7f9fe0c2e78b79
[35]ce0bbe0: https://github.com/vuejs/vue-next/commit/ce0bbe053abaf8ba18de8baf535e175048596ee5
[36]dee3d6a: https://github.com/vuejs/vue-next/commit/dee3d6ab8b4da6653d15eb148c51d9878007f6b6
[37]091e6d6: https://github.com/vuejs/vue-next/commit/091e6d67bfcc215227d78be578c68ead542481ad
[38]03ae300: https://github.com/vuejs/vue-next/commit/03ae3006e1e678ade4377cd10d206e8f7b4ad0cb
[39]af9e699: https://github.com/vuejs/vue-next/commit/af9e6999e1779f56b5cf827b97310d8e4e1fe5ec
[40]5566d39: https://github.com/vuejs/vue-next/commit/5566d39d467ebdd4e4234bc97d62600ff01ea28e
[41]048ac29: https://github.com/vuejs/vue-next/commit/048ac299f35709b25ae1bc1efa67d2abc53dbc3b