• 使用hooks实现的react的一个拖动小demo


    先放下作者大大的bolg地址:https://tinloof.com/blog/how-to-make-your-own-splitpane-react-component-with-0-dependencies/,
    接下来我们来一起看看具体的效果和代码是如何实现的~~
    我们看一下效果,其实就是一个可以拖动的效果,不过这个拖动的效果和我们常规的做法是不一样的哦
    这个是初始化的界面

    这个是拖动后的界面

    我们是明显可以看到界面的变化,实现的特别之处在哪里呢?我们一起看下代码。
    index.tsx是入口文件,这个地方在使用组件那里也有特别之处哦

    我们可以看到,包裹的组件那里,是以对象的形式来引用组件的,我们来仔细看看,为什么可以这样使用呢~
    在SplitPane.js中我们可以看到,我们是直接以函数对象的属性的方法来定义的,在js中万物皆对象,函数组件其实也是属于对象,
    函数组件同样也可以是对象的属性,我们定义的SplitPane函数组件,中间有用children进行占位,故可以直接在App中引用其中

    我们还需要注意的一段代码,我认为是这个demo中最精华的一句代码来

          topRef.current.style.flex = "none";
    

    为什么这么说呢?其实css在这里有一个小技巧的。

    我们可以看到初始化的时候,上面和下面两部分的距离其实是相等的,都是flex:1,这个地方处理拖动的时候,是一旦存在移动的情况,
    就直接将flex:none,是非常有技巧性,我们可以看到整个核心代码,行数不多,却同样可以实现功能

    //SplitPane.js
    import React from "react";
    
    const splitPaneContext = React.createContext();
    
    export default function SplitPane({ children, ...props }) {
      const [topHeight, setTopHeight] = React.useState(null);
      const separatorYPosition = React.useRef(null);
    
      const splitPaneRef = React.createRef();
    
      const onMouseDown = e => {
        separatorYPosition.current = e.clientY;
      };
    
      const onMouseMove = e => {
        if (!separatorYPosition.current) {
          return;
        }
    
        const newTopHeight = topHeight + e.clientY - separatorYPosition.current;
        separatorYPosition.current = e.clientY;
    
        // if (newTopHeight <= 0) {
        //   return topHeight !== 0 && setTopHeight(0);
        // }
    
        const splitPaneHeight = splitPaneRef.current.clientHeight;
    
        // if (newTopHeight >= splitPaneHeight) {
        //   return topHeight !== splitPaneHeight && setTopHeight(splitPaneHeight);
        // }
    
        setTopHeight(newTopHeight);
      };
    
      const onMouseUp = () => {
        separatorYPosition.current = null;
      };
    
      React.useEffect(() => {
        document.addEventListener("mousemove", onMouseMove);
        document.addEventListener("mouseup", onMouseUp);
    
        return () => {
          document.removeEventListener("mousemove", onMouseMove);
          document.removeEventListener("mouseup", onMouseUp);
        };
      });
    
      return (
        <div {...props} className="split-pane" ref={splitPaneRef}>
          <splitPaneContext.Provider value={{ topHeight, setTopHeight }}>
            {children[0]}
            <div className="separator" onMouseDown={onMouseDown} />
            {children[1]}
          </splitPaneContext.Provider>
        </div>
      );
    }
    
    SplitPane.Top = function SplitPaneTop(props) {
      const topRef = React.createRef();
      const { topHeight, setTopHeight } = React.useContext(splitPaneContext);
    
      React.useEffect(() => {
        if (!topHeight) {
          setTopHeight(topRef.current.clientHeight);
          topRef.current.style.flex = "none";
          return;
        }
    
        topRef.current.style.height = `${topHeight}px`;
      }, [topHeight]);
    
      return <div {...props} className="split-pane-top" ref={topRef} />;
    };
    
    SplitPane.Bottom = function SplitPaneBottom(props) {
      return <div {...props} className="split-pane-bottom" />;
    };
    
    
    
    

    最近功力大涨,哭唧唧的,又可以欣赏许多有意思的项目啦啦啦啦啦啦啦
    成为牛逼的前端开发呀呀呀,发发发发发呀

  • 相关阅读:
    Ubuntu Server中怎样卸载keepalived
    Winform中实现ZedGraph滚轮缩放后自动重新加载数据
    Winform中自定义添加ZedGraph右键实现设置所有Y轴刻度的上下限
    C#中获取多个对象list中对象共有的属性项
    Windows7中启动Mysql服务时提示:拒绝访问的一种解决方式
    八、子查询实践
    四、bootstrap-Table
    二、sql新增后返回主键|sql 使用 FOR XML PATH实现字符串拼接|sql如果存在就修改不存在就新增
    一、动词、名词、形容词汇位置
    三、TortoiseSVN 单独拉取项目某个文件
  • 原文地址:https://www.cnblogs.com/smart-girl/p/14248176.html
Copyright © 2020-2023  润新知