antd的可伸縮列用hooks重構後難用的坑

自己不知道怎麼改,看見了老哥的文章,絕了,正好解決orz
https://blog.csdn.net/qq_34398777/article/details/106303169

問題

遇到的問題是官方可伸縮列拖動的時候太卡,究其原因是實時更新列寬,拖動的時候直接更新所有列寬,當列較多的時候更新的數據響應也會比較多,但做法是官方的延申

{
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "antd": "^4.2.2",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-resizable": "^1.10.1",
  }
}
import React, { useState } from 'react'
import { Resizable } from 'react-resizable'

import classnames from 'classnames'

const ResizeableTitle = (props) => {
  const { onResize, width, ...restProps } = props

  // 添加偏移量
  const [offset, setOffset] = useState(0)

  if (!width) {
    return <th {...restProps} />
  }

  return (
    <Resizable
      // 寬度重新計算結果,表頭應當加上偏移量,這樣拖拽結束的時候能夠計算結果;
      // 當然在停止事件再計算應當一樣,我沒試過(笑)
      width={width + offset}
      height={0}
      handle={
        <span
          // 有偏移量顯示豎線
          className={classnames(['react-resizable-handle', offset && 'active'])}
          // 拖拽層偏移
          style={{ transform: `translateX(${offset}px)` }}
          onClick={(e) => {
            // 取消冒泡,不取消貌似容易觸發排序事件
            e.stopPropagation()
            e.preventDefault()
          }}
        />
      }
      // 拖拽事件實時更新
      onResize={(e, { size }) => {
        // 這裏只更新偏移量,數據列表其實並沒有伸縮
        setOffset(size.width - width)
      }}
      // 拖拽結束更新
      onResizeStop={(...argu) => {
        // 拖拽結束以後偏移量歸零
        setOffset(0)
        // 這裏是props傳進來的事件,在外部是列數據中的onHeaderCell方法提供的事件,請自行研究官方提供的案例
        onResize(...argu)
      }}
      draggableOpts={{ enableUserSelectHack: false }}
    >
      <th {...restProps} />
    </Resizable>
  )
}

export const tableComponent = {
  header: {
    cell: ResizeableTitle,
  },
}
.react-resizable {
  position: relative;
  background-clip: padding-box;
}

.react-resizable-handle {
  position: absolute;
  width: 10px;
  height: 100%;
  bottom: 0;
  right: -5px;
  cursor: col-resize;
  z-index: 1;
}

/** 這裏是偏移的時候顯示的豎線,只有表頭有豎線;
如果需要聯通表格請自行修改高度,1000倍表頭高度,然後超出表格隱藏什麼的(自行研究) */
.react-resizable-handle.active::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  border-left: solid 1px black;
}

然後把自己的東西按照他的改了

const ResizeableTitle = (props) => {
  const { onResize, width, ...restProps } = props;
  const [offset, setOffset] = useState(0);
  if (!width) {
    return <th {...restProps} />;
  }
  return (
    <Resizable
      // 寬度重新計算結果   ,表頭應當加上偏移量,這樣拖拽結束的時候能夠計算結果;
      // 當然在停止事件再計算應當一樣,我沒試過(笑)
      width={width + offset}
      height={0}
      handle={
        <span
          className={"react-resizable-handle" + (offset == 0 ? " " : " active")}
          style={{ transform: `translateX(${offset}px)` }}
          onClick={(e) => {
            // 取消冒泡,不取消貌似容易觸發排序事件
            e.stopPropagation();
            e.preventDefault();
          }}
        />
      }
      // 拖拽事件實時更新
      onResize={(e, { size }) => {
        // 這裏只更新偏移量,數據列表其實並沒有伸縮
        setOffset(size.width - width);
      }}
      // 拖拽結束更新
      onResizeStop={(...argu) => {
        // 拖拽結束以後偏移量歸零
        setOffset(0);
        // 這裏是props傳進來的事件,在外部是列數據中的onHeaderCell方法提供的事件,請自行研究官方提供的案例
        onResize(...argu);
      }}
      draggableOpts={{ enableUserSelectHack: false }}
    >
      <th {...restProps} />
    </Resizable>
  );
};
function ArticleList(props) {
  const [isLoading, setIsLoading] = useState(false);
  const [articleList, setArticleList] = useState([{}]);
  const [Columns, setColumns] = useState([{}]);
  const modelStatusRef = useRef(null);
  const getList = () => {
    setIsLoading(true);
    axios({
      method: "get",
      url: servicePath.getArticleList,
      withCredentials: true,
    }).then(async (res) => {
      //console.log(res);
      setIsLoading(false);
      let list = await res.data.list.map((a) => {
        let b = a.addtime;
        b = moment(+b).format("YYYY-MM-DD"); //把時間戳format成需要的格式
        a._addtime = b; //保留原始時間戳爲addtime,轉換後的爲_addtime
        return a;
      });
      setArticleList(list);
      //console.log(res.data.list)
    });
  };
  const delArticle = (id) => {
    confirm({
      title: `確定刪除(id:${id})?`,
      content: "ok--刪除",
      onOk() {
        console.log(servicePath.deleteArticle + `${id}`);
        axios({
          method: "get",
          url: servicePath.deleteArticle + id,
          withCredentials: true,
        }).then((res) => {
          //console.log(res)
          message.success("刪除成功");
          getList();
        });
      },
      onCancel() {
        message.info("取消刪除");
      },
    });
  };
  const changeArticle = (id) => {
    props.history.push(`/adminIndex/changeArticle/${id}`);
  };
  const getListBytitle = (title) => {
    setIsLoading(true);
    axios({
      method: "get",
      url: servicePath.getArticleListBytitle + title,
      withCredentials: true,
    }).then(async (res) => {
      //console.log(res);
      setIsLoading(false);
      let list = await res.data.list.map((a) => {
        let b = a.addtime;
        b = moment(+b).format("YYYY-MM-DD"); //把時間戳format成需要的格式
        a._addtime = b; //保留原始時間戳爲addtime,轉換後的爲_addtime
        return a;
      });
      setArticleList(list);
      //console.log(res.data.list)
    });
  };
  useEffect(() => {
    getList();
    let columns = [
      {
        title: "標題",
        dataIndex: "title",
        width: 300,
      },
      {
        title: "類型",
        dataIndex: "typename",
        width: 100,
      },
      {
        title: "發佈時間",
        dataIndex: "_addtime",
        width: 150,
        sorter: (a, b) => a.addtime - b.addtime,
      },
      {
        title: "瀏覽量",
        dataIndex: "viewcount",
        width: 100,
        sorter: (a, b) => a.viewcount - b.viewcount,
      },
      {
        title: "操作",
        key: "action",
        render: (item) => (
          <Col span={24}>
            <Button
              type='link'
              onClick={() => {
                console.log(item);
                changeArticle(item.id);
              }}
            >
              修改
            </Button>
            <Button
              type='link'
              onClick={() => {
                delArticle(item.id);
              }}
            >
              刪除
            </Button>
          </Col>
        ),
      },
    ];
    columns = columns.map((col, index) => ({
      ...col,
      onHeaderCell: (column) => ({
        width: column.width,
        onResize: handleResize(index),
      }),
    }));
    setColumns(columns);
  }, []);
  useEffect(() => {
    // 每次 更新 把值 複製給 modelStatusRef
    modelStatusRef.current = Columns;
  }, [Columns]); // 依賴的值 等modelStatus 改變了 纔出發裏面的值
  const handleResize = (index) => (e, { size }) => {
    //console.log(modelStatusRef.current)
    console.log(size);
    const nextColumns = [...modelStatusRef.current];
    nextColumns[index] = {
      ...nextColumns[index],
      width: size.width,
    };
    setColumns(nextColumns);
    console.log(Columns, nextColumns);
  };
  const components = {
    header: {
      cell: ResizeableTitle,
    },
  };
  return (
    <div>
      <Search
        placeholder='search article'
        onSearch={(value) => {
          getListBytitle(value);
        }}
        style={{ width: 200 }}
      />
      <Button
        style={{ float: "right" }}
        type='dashed'
        onClick={() => {
          props.history.push("/adminIndex/addArticle");
        }}
      >
        +
      </Button>
      <Table
        bordered
        components={components}
        columns={Columns}
        dataSource={articleList}
        pagination={{ pageSize: 5 }}
        loading={isLoading}
      />
    </div>
  );
}

image-20200614185112483

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