关于javascript:vue3中什么时候封装成组件-什么时候封装成指令-通过实例告诉你typescript

46次阅读

共计 2540 个字符,预计需要花费 7 分钟才能阅读完成。

什么时候封装成组件? 什么时候封装成指令?

个别状况下, 如果要封装的代码中, 蕴含大量的 HTML, 就须要用组件,反之 如果仅仅对某一个 DOM/ 组件的根 DOM 进行操作, 那么能够抉择封装成指令.

“ 拖拽 ” 等手势的辨认仅仅是对某一个元素 / 组件上的 ”mouse/touch” 进行辨认, 并不波及 DOM 操作, 所以这里封装就抉择 ” 指令 ”.

最终目标(v-touch 指令)

先看下指标, 而后剖析.

// main.js
import VTouch from '@any-touch/vue3';
// ... 省略
const app = createApp(App);
app.mountd('#app');
app.use(VTouch);
<template>
    <u-component
        v-touch
        @tap="onTap"
        @swipe="onSwipe"
        @press="onPress"
        @pan="onPan"
        @pinch="onPinch"
        @rotate="onRotate"
    >
    </u-component>
</template>
  1. 既然要用 app.use 初始化, 那咱们就须要封装成 vue 的插件, 插件是有固有格局的, 前面咱们开发写.
  2. 须要反对手势, 这里应用无依赖的 js 手势辨认库 any-touch.

知识点(🚀小技巧)

在 vue 中, 自定义的 DOM 事件, 能够间接通过 ”@” 语法接管, 所以理论咱们能够本人实现任意 ”xx” 事件, 最终都能够通过 ”@xx” 来监听.

const event = new Event('xx');
this.$refs.xxEl.dispatchEvent(event);

‘any-touch’ 外部触发的手势事件都是触发的原生 DOM 事件, 所以 vue 都能够间接监听到, 就如同 ”@tap” 等.

写插件的格局

vue 的插件首先须要是一个对象, 其蕴含一个键值install, 对应值为函数, 且参数为 vue 实例, 也就是这样:

export default {install: (app) => {// 逻辑},
};

组件也是有生命周期的, 比方 mountedunmounted, 他们别离代表指令所在元素 ” 加载结束后执行 ” 和 ” 销毁时执行 ”.

这里咱们用这 2 个钩子, 来执行 any-touch 的初始化和销毁工作.

上面咱们开始封装 ”v-touch” 指令, 留神: 代码中咱们给指令起名叫 ”touch“, 但在组件中应用的时候要写 ”v-touch”,”v-“ 结尾的属性, vue 会晓得他是指令.

import ATouch from 'any-touch';
const elAndAtMap = new WeakMap();
export default {install: (app) => {
        app.directive('touch', {mounted(el) {
                // 初始化
                const at = new ATouch(el);
                elAndAtMap.set(el, at);
            },

            unmounted(el: SupportElement) {
                // 销毁
                elAndAtMap.get(el).destroy();},
        });
    },
};

这里用 WeakMap 来存储每次应用应用 ”v-touch” 时候生成的 ”any-touch” 实例. 写到这性能实现实现了. 然而咱们指标是用 ts 写, 所以请持续向下看.

typescript

首先咱们要引入会用到的类型, 用来对咱们的代码进行标注.

import type {App, DirectiveBinding} from 'vue';
import type {Options, SupportElement} from 'any-touch';
  1. App示意 vue 实例类型.
  2. DirectiveBinding示意指令的参数类型. 如果须要对指令的 进行束缚, 比方限度 v-touch= 的值只能是数字类型, 就须要写成DirectiveBinding<number>.
  3. Optionsany-touch 的参数类型.
  4. SupportElementany-touch 反对的元素类型, 理论就是HTMLElement|SvgElement.

指令的值怎么获取

上面的代码中给 v-touch 指令减少了一个参数值, 通过指令的值给 any-touch 传参, 值咱们通过 mounted 钩子函数的第二个参数获取, 参数是个对象, 其的 ”value” 字段就是 v-touch= 前面的值.

既然 any-touch 的参数就是指令的值, 那么咱们标记第二个参数的类型为:DirectiveBinding<Options>

mounted(el: SupportElement, binding: DirectiveBinding<Options>) {}

残缺代码

上面咱们把类型都标记上.

import {App, DirectiveBinding} from 'vue';
import type {Options, SupportElement} from 'any-touch';
import ATouch from 'any-touch';
const elAndAtMap = new WeakMap();
export default {install: (app: App) => {
        app.directive('touch', {mounted(el: SupportElement, { value}: DirectiveBinding<Options>) {elAndAtMap.set(el, new ATouch(el, value));
            },

            unmounted(el: SupportElement) {elAndAtMap.get(el).destroy();},
        });
    },
};

源码地址

到这里就都实现结束了, 如果小伙伴对 ts 的常识不理解, 能够看看我的 ts 根底课程.

typescript 入门根底

第一课, 体验 typescript

第二课, 根底类型和入门高级类型

第三课, 泛型

第四课, 解读高级类型

第五课, 命名空间 (namespace) 是什么

特别篇, 在 vue3🔥源码中学会 typescript🦕 – “is”

第六课, 什么是申明文件(declare)? 🦕 – 全局申明篇

第七课, 通过 vue3 实例说说 declare module 语法怎么用🦕模块申明篇

🍕学习互动

感激大家的浏览, 如有疑难能够加我微信, 我拉你进入 微信群(因为腾讯对微信群的 100 人限度, 超过 100 人后必须由群成员拉入)

正文完
 0