在上文中,我们讲了vue3.4.0-alpha.1 响应式逻辑的变动。
我们接下来讲剩下的两处变动。
导出错误代码
我们可以通过
import { errorMessages, DOMErrorMessages } from "@vue/compiler-dom"
来获取errorCode
对应的错误信息。
DOMErrorMessages
是在compiler-dom
包定义并导出的。
export const DOMErrorMessages: { [code: number]: string } = {
[DOMErrorCodes.X_V_HTML_NO_EXPRESSION]: `v-html is missing expression.`,
[DOMErrorCodes.X_V_HTML_WITH_CHILDREN]: `v-html will override element children.`,
[DOMErrorCodes.X_V_TEXT_NO_EXPRESSION]: `v-text is missing expression.`,
[DOMErrorCodes.X_V_TEXT_WITH_CHILDREN]: `v-text will override element children.`,
[DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT]: `v-model can only be used on <input>, <textarea> and <select> elements.`,
// 省略其他
// .....
}
DOMErrorMessages
包含的是与模板中的DOM
操作相关的错误信息。通常与特定的Vue
指令(例如 v-html
、v-text
、v-model
等)以及模板中的DOM
结构有关。
比如使用 v-html
时没有提供表达式、v-model
用在不支持的元素上等。他们通常发生在编译器处理模板指令时,涉及到模板和DOM
操作的结合。
而errorMessages
是在compiler-core
包定义并导出的。
export const errorMessages: Record<ErrorCodes, string> = {
// parse errors
[ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT]: 'Illegal comment.',
[ErrorCodes.CDATA_IN_HTML_CONTENT]:
'CDATA section is allowed only in XML context.',
[ErrorCodes.DUPLICATE_ATTRIBUTE]: 'Duplicate attribute.',
[ErrorCodes.END_TAG_WITH_ATTRIBUTES]: 'End tag cannot have attributes.',
[ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS]: "Illegal '/' in tags.",
[ErrorCodes.EOF_BEFORE_TAG_NAME]: 'Unexpected EOF in tag.',
[ErrorCodes.EOF_IN_CDATA]: 'Unexpected EOF in CDATA section.',
[ErrorCodes.EOF_IN_COMMENT]: 'Unexpected EOF in comment.',
// 省略其他
// .....
}
同时compiler-dom
包引入compiler-core
包并导出,因此errorMessages
和DOMErrorMessages
都可以在compiler-dom
包中获取。
errorMessages
包含的是一些通用的、与Vue
模板编译器相关的错误信息。这些错误信息通常涵盖了模板语法的基本规则,以及编译器在处理模板时的一般性错误。他们与模板的结构和语法有关,例如标签闭合、属性使用等。他们代表了一些核心的编译器错误,不仅仅局限于特定的DOM
操作。在编译器的各个阶段都可能出现这些错误。
同时,我们可以使用
import { ErrorTypeStrings } from "@vue/runtime-core"
来获取errorCode
对应的错误信息。
ErrorTypeStrings
是在runtime-core
包定义并导出的。
export const ErrorTypeStrings: Record<LifecycleHooks | ErrorCodes, string> = {
[LifecycleHooks.SERVER_PREFETCH]: 'serverPrefetch hook',
[LifecycleHooks.BEFORE_CREATE]: 'beforeCreate hook',
[LifecycleHooks.CREATED]: 'created hook',
[LifecycleHooks.BEFORE_MOUNT]: 'beforeMount hook',
[LifecycleHooks.MOUNTED]: 'mounted hook',
// 省略其他
// .....
}
ErrorTypeStrings
用于描述生命周期钩子函数(LifecycleHooks
)和编译器错误代码(ErrorCodes
)对应的字符串表示。包含了Vue
组件在不同阶段触发的生命周期钩子,以及编译器可能抛出的错误代码。这些字符串描述用于标识在Vue
应用程序中可能出现的不同生命周期阶段和编译阶段的错误和事件。
在生产环境中,当我们遇到特定的errorCode
时,可以使用导出的errorMessages
、DOMErrorMessages
和ErrorTypeStrings
来获取对应的错误信息,这样能够更方便地定位问题并进行修复。
once
watch
的options
增加了一个参数once
,代表这个watch
只会触发一次,之后不会再次触发。
在增加这个参数之前,我们可以使用以下逻辑来实现只触发一次的watch
import { watch, ref } from "vue"
const num = ref(0)
const stop = watch(num, (newVal, oldVal) => {
console.log(newVal, oldVal)
stop()
})
let times = 0
const timer = setInterval(() => {
times++
if (times >= 2) {
clearInterval(timer)
}
num.value++
}, 100)
//1 0
在增加once
之后,我们可以直接将stop
省略掉。
watch(num, (newVal, oldVal) => {
console.log(newVal, oldVal)
}, { once: true })
让代码看起来更加优雅(pr原话)。
而改动代码也是比较简洁。
// doWatch
if (cb && once) {
const _cb = cb
cb = (...args) => {
_cb(...args)
unwatch()
}
}
在doWatch
中,重新包装回调函数,当存在回调函数以及once
的时候,自动调用unwatch
。
其实就是第一个例子,不同的是当使用once
的时候,vue
会自动替你做这些事情,避免了手动管理停止的麻烦,减少了出错的可能性。