react封装横向滚动组件

在浏览器中封装横向滚动组件确实不是很必要,但是产品说过用户不一定知道shfit+鼠标滚轮就是横向滚动

而普通的监听没有原生的滚动丝滑,借鉴曾经看过的抖音上渡一老师的思路封装了一个横向滚动的组件

ts 复制代码
import React from 'react';
import { ConstructorParamsBase, PageInstance } from '@/abstractClass/PageInstance';

interface State {
  width: number,
  height: number,
}

export class XScrollInstance extends PageInstance<State> {
  vScrollRef = React.createRef<HTMLDivElement>();

  constructor({ forceUpdate, state }: ConstructorParamsBase<State>) {
    super();

    this.setForceUpdate(forceUpdate);
    this.setState({
      height: 0,
      width: 0,
      ...state,
    });
  }

  scrollLeft(scrollNumber: number) {
    this.vScrollRef.current.scrollTop -= scrollNumber;
    this.forceUpdate();
  }

  scrollRight(scrollNumber: number) {
    this.vScrollRef.current.scrollTop += scrollNumber;
    this.forceUpdate();
  }
}
ts 复制代码
import React, { FC, MutableRefObject, useRef } from 'react';
import {
  useCreation, useSize, useUnmount, useUpdate,
} from 'ahooks';
import { css, cx } from '@emotion/css';
import styles from './XScroll.css';
import { XScrollInstance } from './XScrollInstance';

interface Props {
  children: React.ReactNode;
  instanceRef?: MutableRefObject<XScrollInstance>,
  containerClassName?: string
}

export const XScroll: FC<Props> = ({ children, instanceRef, containerClassName }) => {
  const forceUpdate = useUpdate();
  const xScrollRef = useRef();
  const size = useSize(xScrollRef);

  const pageInstance = useCreation(() => {
    const instance = new XScrollInstance({ forceUpdate, state: {} });
    if (instanceRef) {
      instanceRef.current = instance;
    }
    return instance;
  }, []);

  pageInstance.setState({
    width: size?.width || 0,
    height: size?.height || 0,
  });

  useUnmount(() => {
    if (instanceRef) {
      instanceRef.current = null;
    }
  });

  return (
    <div
      ref={xScrollRef}
      className={cx(css`width: 100%;height: 100%;`, containerClassName)}
    >
      <div
        ref={pageInstance.vScrollRef}
        className={cx(styles.vScroll, css`
          position: relative;
          width: calc(${size?.height} * 1px);
          height: calc(${size?.width} * 1px);
          overflow: auto;
          scroll-behavior: smooth;
          transform-origin: 0 0;
          transform: translateY(calc(${size?.height} * 1px)) rotate(-90deg);
        `)}
      >
        <div
          className={cx(css`
            height: calc(${size?.height} * 1px);
            position: absolute;
            left: 100%;
            transform-origin: 0 0;
            transform: rotate(90deg);
            padding-top: 1px;
          `)}
        >
          {children}
        </div>
      </div>
    </div>
  );
};
css 复制代码
.vScroll::-webkit-scrollbar {
    width: 0;
}

用法只需用组件包裹过长dom就可以了

相关推荐
阿赛工作室12 分钟前
Vue中onBeforeUnmount不触发的解决方案
前端·javascript·vue.js
码王吴彦祖13 分钟前
顶象 AC 纯算法迁移实战:从补环境到纯算的完整拆解
java·前端·算法
小叶lr26 分钟前
jenkins打包前端样式丢失/与本地不一致问题
运维·前端·jenkins
浩星32 分钟前
electron系列1:Electron不是玩具,为什么桌面应用需要它?
前端·javascript·electron
ZC跨境爬虫1 小时前
Scrapy工作空间搭建与目录结构解析:从初始化到基础配置全流程
前端·爬虫·python·scrapy·自动化
小村儿1 小时前
连载04-最重要的Skill---一起吃透 Claude Code,告别 AI coding 迷茫
前端·后端·ai编程
_院长大人_1 小时前
Vue + ECharts 实现价格趋势分析图
前端·vue.js·echarts
IT_陈寒2 小时前
Vite的alias配置把我整不会了,原来是这个坑
前端·人工智能·后端
万物得其道者成2 小时前
Cursor 提效实战:我的前端 Prompt、审查 SKILL、MCP 接入完整方法
前端·prompt
酒鼎2 小时前
学习笔记(12-02)事件循环 - 实战案例 —⭐
前端·javascript