手写一个setInterval

模拟setInterval的技巧
本文探讨了setInterval定时器在JavaScript中的工作原理及其潜在问题。由于执行栈的限制,实际执行间隔可能与预期不符。文章提供了一种使用setTimeout递归调用来模拟setInterval的方法,以确保更精确的定时任务执行。

setInterval定时器的一些问题

// setInterval的所用是每隔一段指定的时间执行一个函数,但是这个执行不是真的到了时间立即执行,
// 它真正的作用是每隔一段时间将事件加入事件队列中去,只有当前的执行栈为空的时候,才能去从事件
// 队列中取出事件执行。所以可能会出现这样的问题,就是当前执行栈执行的时间很长导致事件队列里面
// 累积多个定时器加入的事件,当执行栈结束的时候,这些事件会依次执行,因此就不能做到每隔一段时间
// 执行的效果了
// 针对setInterval的这个缺点,我们可以使用setTimeout递归调用来模拟 setInterval,这样我们确保了只有一个事件
// 结束了,我们才会触发下一个定时器事件,这样解决了 setInterval 的问题


// 模拟setInterval
    function mySetInterval(fn, delay, ...args) {
      const timer = { flag: true }
      function interval() {
        if (timer.flag) {
          fn(...args)
          setTimeout(() => {
            interval()
          }, delay)
        }
      }
      setTimeout(() => {
        interval()
      }, delay)
      return timer
    }


好的,以下是一个简单的手写Vue版本的swiper: ```vue <template> <div class="swiper"> <div class="swiper-container" ref="swiperContainer"> <div class="swiper-wrapper" ref="swiperWrapper"> <div class="swiper-slide" v-for="(item, index) in swiperList" :key="index"> {{ item }} </div> </div> </div> <div class="swiper-pagination" ref="pagination"></div> <div class="swiper-button-prev" ref="prev"></div> <div class="swiper-button-next" ref="next"></div> </div> </template> <script> export default { name: "Swiper", data() { return { swiperList: ["slide1", "slide2", "slide3"], activeIndex: 0, timer: null, }; }, mounted() { this.init(); }, methods: { init() { this.setPagination(); this.setButton(); this.autoPlay(); }, setPagination() { const pages = this.swiperList.length; for (let i = 0; i < pages; i++) { const page = document.createElement("span"); page.className = "swiper-pagination-bullet"; page.addEventListener("click", () => { this.goToPage(i); }); this.$refs.pagination.appendChild(page); } this.updatePagination(); }, setButton() { this.$refs.prev.addEventListener("click", () => { this.goToIndex(this.activeIndex - 1); }); this.$refs.next.addEventListener("click", () => { this.goToIndex(this.activeIndex + 1); }); }, autoPlay() { this.timer = setInterval(() => { this.goToIndex(this.activeIndex + 1); }, 2000); }, goToPage(index) { this.activeIndex = index; this.updatePagination(); this.updateWrapper(); }, goToIndex(index) { const pages = this.swiperList.length; if (index < 0) { index = pages - 1; } else if (index >= pages) { index = 0; } this.activeIndex = index; this.updatePagination(); this.updateWrapper(); }, updatePagination() { const pages = this.$refs.pagination.children; for (let i = 0; i < pages.length; i++) { pages[i].classList.remove("swiper-pagination-bullet-active"); } pages[this.activeIndex].classList.add("swiper-pagination-bullet-active"); }, updateWrapper() { const width = this.$refs.swiperContainer.clientWidth; this.$refs.swiperWrapper.style.transform = `translateX(${-width * this.activeIndex}px)`; }, }, beforeDestroy() { clearInterval(this.timer); }, }; </script> <style scoped> .swiper { position: relative; width: 100%; overflow: hidden; } .swiper-container { position: relative; width: 100%; height: 100%; white-space: nowrap; } .swiper-wrapper { display: inline-block; font-size: 0; transition: transform 0.3s; } .swiper-slide { display: inline-block; width: 100%; height: 100%; font-size: 16px; text-align: center; box-sizing: border-box; padding-top: 50px; } .swiper-pagination { position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); } .swiper-pagination-bullet { display: inline-block; width: 10px; height: 10px; margin: 0 5px; border-radius: 50%; background-color: #ccc; cursor: pointer; } .swiper-pagination-bullet-active { background-color: #333; } .swiper-button-prev, .swiper-button-next { position: absolute; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; border-radius: 50%; background-color: rgba(0, 0, 0, 0.3); cursor: pointer; } .swiper-button-prev { left: 10px; } .swiper-button-next { right: 10px; } </style> ``` 这个手写的swiper实现了基本的轮播功能,并且支持自动轮播、分页和左右切换按钮。但是,这个swiper还有很多可以改进的地方,比如添加动画效果、支持响应式布局等。如果需要更加完善的swiper,可以考虑使用第三方库,如swiper、vue-awesome-swiper等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值