「这是我参与2022首次更文挑战的第28天,活动详情查看:2022首次更文挑战」。
写在前面
- 前面一篇文章已经实现了我们想要的 dom 元素的运动
- 但是里面涉及到异步操作的时候,使用的是最原始的回掉地狱式的写法
- 导致代码非常不优雅,不利于阅读,不利于维护
- 那么我们这篇文章来介绍一种相对而言更优雅的实现方式
自定义事件
- 在 js 中使用自定义事件的方式有两种,Event 与 CustomEvent,他们最大的区别在于,Event 不能传递数据,而 CustomEvent 可以,具体大家可以自己去看看 MDN 文档,这里关注我们要实现的主题
- 由于实现的效果是相同的,所以本文的代码可以机遇上一篇文章进行改写
- 下面是 move 函数的改写的代码
let move = (ele, direction, target, cb) => {
let start = parseInt(getComputedStyle(ele, null)[direction]);
let speed = ((target - start) / Math.abs(target - start)) * 2;
start += speed;
ele.style[direction] = `${start}px`;
setTimeout(() => {
if (Math.abs(target - start) <= 2) {
ele.style[direction] = `${target}px`;
// cb & cb();
ele.dispatchEvent(new CustomEvent(`myEvent-${num++}`));
} else {
move(ele, direction, target, cb);
}
}, 10);
};
- 可以看到,上面的获取 dom 元素样式使用 getComputedStyle 和设置样式的逻辑都没有变
- 之前的,调用回掉函数的代码换成了使用自定义事件
- new CustomEvent 生成一个自定义事件对象
- 通过 dispatchEvent 将事件派发出去
- 有了事件的派发,必然有事件的监听
let ele = document.querySelector(".box");
// move(ele, "left", 301, () => {
// console.log("右移 ok");
// move(ele, "top", 301, () => {
// console.log("下移 ok");
// move(ele, "left", 0, () => {
// console.log("左移 ok");
// move(ele, "top", 0, () => {
// console.log("上移 ok");
// });
// });
// });
// });
move(ele, "left", 301);
ele.addEventListener("myEvent-1", () => {
console.log("右移 ok");
move(ele, "top", 301);
});
ele.addEventListener("myEvent-2", () => {
console.log("下移 ok");
move(ele, "left", 0);
});
ele.addEventListener("myEvent-3", () => {
console.log("左移 ok");
move(ele, "top", 0);
});
ele.addEventListener("myEvent-4", () => {
console.log("上移 ok");
});
- 为了能监听到上面派发的事件,我们需要给 dom 元素绑定运动对应的事件回掉,在事件的回掉函数中,我们即可执行下一个动画的函数
- 为了能区分派发的事件类型,我们在实例化 CustomEvent 对象的时候传入的是一个模版字符串
myEvent-${num++},其中的 num 则是一个全局变量,表示当前的事件 ID - 至此,我们基于自定义事件的改造已经完成
小结
- 上面虽然解决了,前一篇文章的回掉地狱问题,并且代码看起来也是同步的写法
- 但是上面为了区分不同的事件类型,定义了一个全局变量,难免有些不优雅
- 那还有没有比较优雅的方式呢,下篇文章我们将使用 promise 的写法来改造这个例子
最后
- 今天的分享就到这里了,欢迎大家在评论区里面进行讨论 👏。
- 如果觉得文章写的不错的话,希望大家不要吝惜点赞,大家的鼓励是我分享的最大动力 🥰