Vue3从0到1组件开发-布局组件:Scroll滚动

994 阅读2分钟

这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战

滚到外婆桥

左右摇摆

如果说之前的轮播图还能因为其常见性,普遍性而跻身布局组件的话, 那么滚动这个也能算布局组件?

无论是从普遍性,还是其本身功能的局限性,将之作为业务组件才更符合常理的吧?

NO!NO!NO! 作为一名开发者,自然是要有着远超旁人的创新性,以及看待事物的独特角度。

接下来就看我先瞎编一段。

将之作为布局组件而非业务组件的主要原因在于,该组件本质上也是提供一个常见的“平台”,内容由开发者去定义。

而功能部分也是做的滚动到底部触发时间。将内容交给开发者之后,组件本身的部分就更符合一个布局组件所具备的素质了。

听懂掌声!

说到底,我对布局组件的理解就是:提供平台,内容交给开发时。

而业务组件更多的是根据需求对其他组件进行二次封装,或者专门去开发一个组件。

开始搞事

既然是只搭平台, 那就做好一个平台要做的事吧, 从结构开始就要做好一个平台的分内事了。

block content
div.yx-scroll(
  :style="{height: `${viewHeight}px`}"
  @mouseenter="mouseover"
  @mouseleave="mouseout"
)
  div.yx-scroll-content(
    :style="{paddingRight: `${size}px`}"
    @scroll="viewScroll"
  )
    slot
  transition(name="fade")
    div.yx-scroll-bar(
      v-show="!alwaysVisible || isShow"
      :style="{width: `${size}px`}"
      @mousedown="thumbDrag($event)"
    )
      div.yx-scroll-thumb(
        ref="thumb"
        :style="{height: `${barHeight}px`,top: `${barTop}px`,borderRadius: `${size}px` }"
      )

结构部分比较清晰,主要是监听滚动事件,回顶滚动到底部的交给逻辑部分去判断,

此外在该组件中的滚动条是自定义的,而非系统默认的,不过这个就随意了,可以自由发挥。

逻辑部分

还是老规矩,挑重点说。

先看滚动条。


const thumbDrag = (e) => {
  e.preventDefault()
  // 分别获取节点、滚动值等信息
  const el = ctx.vnode.el
  const view = el.children[0]
  const touchY = e.clientY - BarTop.value
  const element = e.target

// 计算滚动高度,以及显示滚动条的高度
  if (element.className === 'yx-scroll-bar') {
    const top = e.clientY - element.getBoundingClientRect().top
    view.scrollTop =
      view.scrollHeight * (top / element.offsetHeight) -
      element.offsetHeight / 2
  } else {
    const move = (ev) => {
      isDrag = true
      const bt =
        (ev.clientY - touchY) /
        (view.offsetHeight - thumb.value.offsetHeight)
      const top = (view.scrollHeight - view.offsetHeight) * bt
      view.scrollTop = top
    }
    document.addEventListener('mousemove', move)
    document.addEventListener('mouseup', () => {
      isDrag = false
      if (!isArea) {
        isShow.value = false
      }
      document.removeEventListener('mousemove', move)
    })
  }
}

事件监听

const emits = defineEmit(['onScroll','update:to']);

const viewScroll = () => {
  const el = ctx.vnode.el;
  const view = el.children[0];
  const catchTop = view.scrollTop / (view.scrollHeight - view.offsetHeight);
  barTop.vuew = catchTop * (view.offsetHeight - thumb.value.offsetHeight);

  emits('onScroll', catchTop);
  emits('update:to', view.scrollTop);
}

这里的catchTop计算的是当前滚动距离的百分比, 取值: 0 ~ 1, 传值给父级是方便父级如果需要的话,可以自行判断当前百分比,并完善自动加载的函数。

其他

其他的部分都是属于比较灵活的点的了,可以根据自己对组件的预期,或者是项目中的需求来改动组件,使其更贴合自己项目中的使用。