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>
- 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. - 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';
-
App
represents the vue instance type. -
DirectiveBinding
represents the parameter type of the instruction. If you need to constrain the value of the instruction, such as restricting the value ofv-touch=
to only be a number type, you need to writeDirectiveBinding<number>
. -
Options
is the parameter type ofany-touch
. -
SupportElement
is an element type supported byany-touch
, which is actuallyHTMLElement|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(); }, }); }, };
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 4, Interpreting Advanced Types
Special article, learn typescript in vue3🔥 source code🦕 - "is"
Lesson 6, what is a declaration file? 🦕 - Global 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)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。