Svelte使用指令

Svelte 使用指令

Actions 本质上是元素级生命周期函数。它们在以下方面很有用:与第三方库接口延迟加载图像工具提示添加自定义事件处理程序在此应用程序中,我们希望将橙色框设置为“pannable”。它具有用于 ​panstart​、​panmove​ 和 ​panend​ 事件的事件处理程序,但这些不是本机 DOM 事件。我们必须自己调度他们。首先,导入 ​pannable​ 函数...import { pannable } from './pannable.js';...然后将它与元素一起使用:<div class="box"

use:pannable

on:panstart={handlePanStart}

on:panmove={handlePanMove}

on:panend={handlePanEnd}

style="transform:

translate({$coords.x}px,{$coords.y}px)

rotate({$coords.x * 0.2}deg)"

></div>打开 ​pannable.js​ 文件。与 transition 函数一样,action 函数接收一个 ​node​和一些可选参数,并返回一个动作对象。该对象可以有一个 ​destroy​ 函数,该函数在元素被卸载时调用。我们希望在用户将鼠标放在元素上时触发 ​panstart​ 事件,在拖动元素时触发 ​panmove​ 事件(使用 ​dx​ 和 ​dy​ 属性显示鼠标移动的距离),并在鼠标松开时触发 ​panend​ 事件。一种可能的实现如下所示:export function pannable(node) {

let x;

let y;

function handleMousedown(event) {

x = event.clientX;

y = event.clientY;

node.dispatchEvent(new CustomEvent('panstart', {

detail: { x, y }

}));

window.addEventListener('mousemove', handleMousemove);

window.addEventListener('mouseup', handleMouseup);

}

function handleMousemove(event) {

const dx = event.clientX - x;

const dy = event.clientY - y;

x = event.clientX;

y = event.clientY;

node.dispatchEvent(new CustomEvent('panmove', {

detail: { x, y, dx, dy }

}));

}

function handleMouseup(event) {

x = event.clientX;

y = event.clientY;

node.dispatchEvent(new CustomEvent('panend', {

detail: { x, y }

}));

window.removeEventListener('mousemove', handleMousemove);

window.removeEventListener('mouseup', handleMouseup);

}

node.addEventListener('mousedown', handleMousedown);

return {

destroy() {

node.removeEventListener('mousedown', handleMousedown);

}

};

}更新 ​pannable​ 函数并尝试移动盒子。此实现仅用于演示目的——更完整的实现也会考虑触摸事件。示例代码App.svelte<script>

import { spring } from 'svelte/motion';

import { pannable } from './pannable.js';

const coords = spring({ x: 0, y: 0 }, {

stiffness: 0.2,

damping: 0.4

});

function handlePanStart() {

coords.stiffness = coords.damping = 1;

}

function handlePanMove(event) {

coords.update($coords =&gt; ({

x: $coords.x + event.detail.dx,

y: $coords.y + event.detail.dy

}));

}

function handlePanEnd(event) {

coords.stiffness = 0.2;

coords.damping = 0.4;

coords.set({ x: 0, y: 0 });

}

</script>

<style>

.box {

--width: 100px;

--height: 100px;

position: absolute;

width: var(--width);

height: var(--height);

left: calc(50% - var(--width) / 2);

top: calc(50% - var(--height) / 2);

border-radius: 4px;

background-color: #ff3e00;

cursor: move;

}

</style>

<div class="box"

use:pannable

on:panstart={handlePanStart}

on:panmove={handlePanMove}

on:panend={handlePanEnd}

style="transform:

translate({$coords.x}px,{$coords.y}px)

rotate({$coords.x * 0.2}deg)"

></div>pannable.jsexport function pannable(node) {

let x;

let y;

function handleMousedown(event) {

x = event.clientX;

y = event.clientY;

node.dispatchEvent(new CustomEvent('panstart', {

detail: { x, y }

}));

window.addEventListener('mousemove', handleMousemove);

window.addEventListener('mouseup', handleMouseup);

}

function handleMousemove(event) {

const dx = event.clientX - x;

const dy = event.clientY - y;

x = event.clientX;

y = event.clientY;

node.dispatchEvent(new CustomEvent('panmove', {

detail: { x, y, dx, dy }

}));

}

function handleMouseup(event) {

x = event.clientX;

y = event.clientY;

node.dispatchEvent(new CustomEvent('panend', {

detail: { x, y }

}));

window.removeEventListener('mousemove', handleMousemove);

window.removeEventListener('mouseup', handleMouseup);

}

node.addEventListener('mousedown', handleMousedown);

return {

destroy() {

node.removeEventListener('mousedown', handleMousedown);

}

};

}