Leecason

vuePress-theme-reco Leecason    2018 - 2020
Leecason Leecason

Choose mode

  • dark
  • auto
  • light
主页
分类
  • CSS
  • FrontEnd
  • GraphQL
  • JavaScript
  • TypeScript
  • Vue
  • Webpack
  • 其它
  • 数据结构与算法
  • 浏览器相关
标签
时间线
GitHub
author-avatar

Leecason

80

Article

61

Tag

主页
分类
  • CSS
  • FrontEnd
  • GraphQL
  • JavaScript
  • TypeScript
  • Vue
  • Webpack
  • 其它
  • 数据结构与算法
  • 浏览器相关
标签
时间线
GitHub

「译」 VueDose Tip 25 - 使用 CSS Scroll Snap 和 Vue.js 的最现代的轮播组件

vuePress-theme-reco Leecason    2018 - 2020

「译」 VueDose Tip 25 - 使用 CSS Scroll Snap 和 Vue.js 的最现代的轮播组件

Leecason 2020-01-31 Vue 2VueDose文章翻译

上周我和我挚爱的朋友 Laura Bonmati 去了 Codemotion Madrid。这是西班牙最大的极客交流会之一。

我们最喜欢的演讲之一是 Sonia Ruiz 的 “CSS 的最新功能”,该 Tip 来自我从她的演讲中获得的一些灵感,因此让我们在 twitter 上为她点赞吧!

在她展示的功能中,令我感到惊喜的是 scroll-snap,并且用它来构建轮播非常容易,所以我想...让它成为一个组件!

首先,创建一个具有以下结构的 Carousel.vue 组件:

<template>
  <div class="carousel-wrapper">
    <div class="carousel" :style="{ width, height }">
      <slot/>
    </div>
  </div>
</template>

<script>
export default {
  props: ["width", "height"]
};
</script>

<style scoped>
.carousel {
  display: flex;
  overflow: scroll;
  scroll-snap-type: x mandatory;
}

.carousel > * {
  flex: 1 0 100%;
  scroll-snap-align: start;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

这里最重要的部分是使用 scroll-snap-type。我们迫使滚动吸附在沿 x 轴的 .carousel 元素内的每一项。

然后,你需要使轮播中的每个项目都占据容器的全部空间。你可以使用 flex: 1 0 100% 并用 scroll-snap-align: start 定义每项的对齐。

请注意,我传递了 width 和 height 属性,因此你可以轻松地从组件外部设置轮播尺寸。

顺便提一下,如果不知道 <slot/> 如何工作,可以查看在 Vue.js 中使用作用域插槽和Vue 2.6 中的新指令 v-slot,并进一步了解它们(包括作用域插槽)。

这样,你就拥有了一个轮播组件,该组件可以使用鼠标平滑的滚动。

让我们添加一些功能吧?如果要手动更改当前轮播页,该怎么办?

正如你可能已经想到的那样,轮播根据滚动条“滚动”,因此你必须改变滚动的位置。

实际上,每个滚动定位都是轮播图的宽度乘以轮播图位置的乘积。

让我们添加几个按钮,使我们可以在轮播图中来回移动,以便我们可以浏览每个轮播图:

<template>
  <div class="carousel-wrapper">
    <div class="carousel" :style="{ width, height }">
      <slot/>
    </div>
    <button @click="changeSlide(-1)">Prev Slide</button>
    <button @click="changeSlide(1)">Next Slide</button>
  </div>
</template>

<script>
export default {
  props: ["width", "height"],
  methods: {
    changeSlide(delta) {
      const carousel = this.$el.querySelector(".carousel");
      const width = carousel.offsetWidth;
      carousel.scrollTo(carousel.scrollLeft + width * delta, 0);
    }
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

这些按钮调用 changeSlide,传递你想要改变的轮播的位置参数。

该方法使用当前轮播页的宽度,并通过检查当前滚动位置并添加应改变像素来计算滚动位置。计算公式是 carousel.scrollLeft + width * delta。

如果你尝试使用该组件,可以看到它会按照预期工作,但是滚动并不流畅。相反的,它是立即改变轮播页的。

幸运的是,最现代 CSS 来了!

你可以在轮播元素上使用 scroll-behavior: smooth 属性,滚动将再次变得平滑!

.carousel {
  display: flex;
  overflow: scroll;
  scroll-behavior: smooth;
  scroll-snap-type: x mandatory;
}
1
2
3
4
5
6

最后,使用组件的方法非常简单:

<template>
  <Carousel width="400px" height="250px">
    <div class="blue">Blue</div>
    <div class="green">Green</div>
    <div class="red">Red</div>
  </Carousel>
</template>
1
2
3
4
5
6
7

你认识到构建此组件有多么容易了吗?现代 CSS 真是太好了!

我敢肯定,你现在正在考虑改善它的很多方法:每隔 X 秒自动切换,循环滚动,切换到指定的轮播页...请告诉我你的想法并将其展示给我!我很高兴看到你的实现!

当前,请记住,此组件使用了非常新的 CSS 属性,因此仅在最新的浏览器中受支持。

但是你必须构建轮播的未来!

# CodeSandbox

# 原文链接