4

When is it encapsulated into a component? When is it encapsulated into an instruction?

In general, if the code to be encapsulated contains a lot of HTML, you need to use components. On the contrary , if you only operate on the root DOM of a DOM/component, you can choose to encapsulate it as an instruction.

The recognition of gestures such as "drag and drop" is only to recognize "mouse/touch" on a certain element/component, and does not involve DOM operations, so the "instruction" is selected for encapsulation here.

Final goal (v-touch instruction)

Look at the target first, then analyze it.

 // 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. Since we need to initialize with app.use , we need to encapsulate it as a vue plug-in. The plug-in has an inherent format, which we will develop and write later.
  2. Gestures need to be supported, here use the no-dependency js gesture recognition library any-touch .

Knowledge points (🚀Tips)

In Vue, custom DOM events can be received directly through the "@" syntax, so we can actually implement any "xx" events by ourselves, and finally we can listen to them through "@xx".

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

The gesture events triggered inside 'any-touch' are all native DOM events that are triggered , so vue can listen directly, just like "@tap" etc.

Format for writing plugins

The vue plugin first needs to be an object, which contains a key value install , the corresponding value is a function, and the parameter is a vue instance, that is:

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

Components also have a life cycle, such as mounted and unmounted , which represent "execute after loading" and "execute when destroyed" of the element where the instruction is located.

Here we use these two hooks to perform any-touch initialization and destruction.

Let's start to encapsulate the "v-touch" instruction. Note: In the code, we name the instruction " touch ", but when using it in the component, we need to write "v-touch", properties starting with "v-", vue will know He is the command.

 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(); }, }); }, };

Here WeakMap is used to store the "any-touch" instance generated each time "v-touch" is used. The implementation of this function is completed. But our goal is to write in ts, so please continue to look down.

typescript

First, we need to introduce the types that will be used to annotate our code.

 import type { App, DirectiveBinding } from 'vue'; import type { Options, SupportElement } from 'any-touch';
  1. App represents the vue instance type.
  2. DirectiveBinding represents the parameter type of the instruction. If you need to constrain the value of the instruction, such as restricting the value of v-touch= to only be a number type, you need to write DirectiveBinding<number> .
  3. Options is the parameter type of any-touch .
  4. SupportElement is an element type supported by any-touch , which is actually HTMLElement|SvgElement .

How to get the value of the command

The following code adds a parameter value to the v-touch command, and passes the parameter to any-touch through the value of the command. The value is obtained through the second parameter of the mounted hook function. The parameter is an object, and its "value" field is v-touch= The value behind.

Since the parameter of any-touch is the value of the directive, we mark the type of the second parameter as: DirectiveBinding<Options>

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

full code

Below we mark all types.

 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(); }, }); }, };

Source address

It's all implemented here. If you don't know the knowledge of ts, you can take a look at my ts basic course.

Basics of getting started with typescript

The first lesson, experience typescript

Lesson 2, Basic Types and Introductory Advanced Types

Lesson 3, Generics

Lesson 4, Interpreting Advanced Types

Lesson 5, What is a namespace

Special article, learn typescript in vue3🔥 source code🦕 - "is"

Lesson 6, what is a declaration file? 🦕 - Global Declaration

Lesson 7, talk about how to use the declare module syntax through the vue3 example 🦕 module declaration

🍕Learn to interact

Thank you for reading, if you have any questions, you can add me on WeChat, and I will pull you into the WeChat group (due to Tencent's limit of 100 people in WeChat groups, after more than 100 people must be pulled in by group members)


铁皮饭盒
5k 声望1.2k 粉丝

喜欢写程序: [链接]