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



最近功力大漲,哭唧唧的,又可以欣賞許多有意思的項目啦啦啦啦啦啦啦
成爲牛逼的前端開發呀呀呀,發發發發發呀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章