记录生活中的点滴,分享、学习、创新
提示:在阅读本文前,建议您先阅读 Vue 3 官方文档 自定义指令 章节的内容。
1 2 3 4 5 6 7 8 9 10 | const app = Vue.createApp({}) // 注册一个全局自定义指令 v-focus app.directive( 'focus' , { // 当被绑定的元素挂载到 DOM 中时被调用 mounted(el) { // 聚焦元素 el.focus() } }) |
1 2 3 | < div id = "app" > < input v-focus /> </ div > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <div id= "app" > <input v-focus /> </div> <script> const { createApp } = Vue const app = Vue.createApp({}) // ① app.directive( 'focus' , { // ② // 当被绑定的元素挂载到 DOM 中时被调用 mounted(el) { el.focus() // 聚焦元素 } }) app.mount( '#app' ) // ③ </script> |
当页面加载完成后,页面中的输入框元素将自动获得焦点。该示例的代码比较简单,主要包含 3 个步骤:创建 App 对象、注册全局自定义指令和应用挂载。其中创建 App 对象的细节,阿宝哥会在后续的文章中单独介绍,下面我们将重点分析其他 2 个步骤。首先我们先来分析注册全局自定义指令的过程。
在以上示例中,我们使用 app 对象的 directive 方法来注册全局自定义指令:
1 2 3 4 5 6 | app.directive( 'focus' , { // 当被绑定的元素挂载到 DOM 中时被调用 mounted(el) { el.focus() // 聚焦元素 } }) |
当然,除了注册全局自定义指令外,我们也可以注册局部指令,因为组件中也接受一个 directives 的选项:
1 2 3 4 5 6 7 | directives: { focus: { mounted(el) { el.focus() } } } |
对于以上示例来说,我们使用的 app.directive 方法被定义在 runtime-core/src/apiCreateApp.ts 文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // packages/runtime-core/src/apiCreateApp.ts export function createAppAPI<HostElement>( render: RootRenderFunction, hydrate?: RootHydrateFunction ): CreateAppFunction<HostElement> { return function createApp(rootComponent, rootProps = null ) { const context = createAppContext() let isMounted = false const app: App = (context.app = { // 省略部分代码 _context: context, // 用于注册或检索全局指令。 directive(name: string, directive?: Directive) { if (__DEV__) { validateDirectiveName(name) } if (!directive) { return context.directives[name] as any } if (__DEV__ && context.directives[name]) { warn(`Directive "${name}" has already been registered in target app.`) } context.directives[name] = directive return app }, return app } } |
通过观察以上代码,我们可以知道 directive 方法支持以下两个参数:
name 参数比较简单,所以我们重点分析 directive 参数,该参数的类型是 Directive 类型:
1 2 3 4 | // packages/runtime-core/src/directives.ts export type Directive<T = any, V = any> = | ObjectDirective<T, V> | FunctionDirective<T, V> |
由上可知 Directive 类型属于联合类型,所以我们需要继续分析 ObjectDirective 和 FunctionDirective 类型。这里我们先来看一下 ObjectDirective 类型的定义:
1 2 3 4 5 6 7 8 9 10 11 | // packages/runtime-core/src/directives.ts export interface ObjectDirective<T = any, V = any> { created?: DirectiveHook<T, null , V> beforeMount?: DirectiveHook<T, null , V> mounted?: DirectiveHook<T, null , V> beforeUpdate?: DirectiveHook<T, VNode<any, T>, V> updated?: DirectiveHook<T, VNode<any, T>, V> beforeUnmount?: DirectiveHook<T, null , V> unmounted?: DirectiveHook<T, null , V> &nbs
*
|