使用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" />;
};



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

原文地址:https://www.cnblogs.com/smart-girl/p/14248176.html