簡體   English   中英

如何使用 React Material UI 的過渡組件動畫將項目添加到列表?

[英]How can I use React Material UI's transition components to animate adding an item to a list?

我有這個 class。

class Demo extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      items: []
    };

    this.add = this.add.bind(this);
    this.clear = this.clear.bind(this);
  }

  add() {
    this.setState(prev => {
      const n = prev.items.length;
      return {
        items: [<li key={n}>Hello, World {n}!</li>, ...prev.items]
      };
    });
  }

  clear() {
    this.setState({ items: [] });
  }

  render() {
    return (
      <div>
        <div>
          <button onClick={this.add}>Add</button>
          <button onClick={this.clear}>Clear</button>
        </div>

        {/* This is wrong, not sure what to do though... */}
        <Collapse in={this.state.items.length > 0}>
          <ul>{this.state.items}</ul>
        </Collapse>
      </div>
    );
  }
}

沙盒鏈接: https://codesandbox.io/s/material-demo-ggv04?file=/Demo.js

我正在努力做到這一點,以便每次單擊“添加”按鈕時,一個新項目會在列表頂部以動畫方式存在,並且現有項目會被下推。 不知道如何進行。

額外資源

我更新了你的沙盒代碼來實現你想要的,但我不認為 MaterialUI 是最好的庫(我可能會錯過更好的方法)。

挑戰在於,當您添加新項目時,DOM 中尚不存在該項目。 並且大多數 animation 庫/組件要求元素位於 DOM 中,它們只是“隱藏”和“顯示”它並帶有過渡時間。

我遇到了類似的情況,經過一些研究,我發現可以處理 animation 的更好的庫是Framer Motion (您可以查看他們的 安裝動畫文檔)

無論如何,這里是新代碼沙箱的鏈接,所以你可以看看。 我所做的更改:

刪除了隨機密鑰

In the map function that creates your list using the <Collapse /> component, there was a function to get a random integer and assign that as a key to your component. React 需要有一致的鍵才能正確地進行偽裝,因此刪除該隨機數可以解決您的“切換”按鈕沒有正確動畫的問題。 (如果您的項目列表沒有唯一 ID,只需使用map function 的索引,這不是一個好的解決方案,但仍然比隨機數好)。

<Collapse key={i} timeout={this.state.collapseTimeout} in={this.state.open}>
    {it}
</Collapse>

添加了一個新的 function 來控制切換

這里的方法是:在列表中添加項目,在元素進入 DOM 后,關閉<Collapse /> ,稍等片刻,然后再次打開它(這樣你就可以直觀地看到動畫)。 為了做到這一點,我們需要一個新的“切換” function 可以顯式設置折疊的值。

toggleValue(value) {
  this.setState(() => {
    return {
      open: value
    };
  });
}

為崩潰添加了可變超時

最后一個問題是,在添加新項目時關閉<Collapse />會觸發 animation 將其關閉。 這里的解決方案是動態改變崩潰的超時時間,所以你看不到。

setCollapseTimeout(value) {
  this.setState(() => {
    return {
      collapseTimeout: value
    };
  });
}

將元素添加到列表時,等待觸發 animation同樣,要解決尚未在 DOM 中的元素的問題,我們需要使用setTimeout或其他東西來等待切換<Collapse /> 這是在您的add() function 中添加的。

add() {
  this.toggleValue(false);
  this.setCollapseTimeout(0);
  this.setState(prev => {
    const n = prev.items.length;
    return {
      items: [<li key={n}>Hello, World {n}!</li>, ...prev.items]
    };
  });
  setTimeout(() => {
    this.setCollapseTimeout(300);
    this.toggleValue(true);
  }, 100);
}

同樣,這是一個讓 MaterialUI 中的<Collapse />與尚未在 DOM 中的元素一起工作的 hacky 解決方案。 但是,如前所述,還有其他更好的庫。

祝你好運:)

早些時候在這里結束,然后回來創建一個沙箱,希望能展示一種適用於這種情況的簡單方法。 material-ui文檔在這方面有點(很多)輕松,我正在與非常相似的情況作斗爭,但我嘗試了react-transition-group中的TransitionGroup ,交叉手指,它似乎有效。

帶有 TransitionGroup 的分叉 CodeSandbox

要點是你

  1. <TransitionGroup>組件中包裝你想要過渡的所有組件
  2. TransitionGroup中,為要渲染的數據輸入“條件”(邏輯或循環輸出)
  3. 用您選擇的過渡組件包裹您要過渡的各個組件 - 在本例中為<Collapse>

例如,在其最簡單的設置中,“項目”是來自任一道具的唯一數字數組,state 或 redux 商店

<TransitionGroup>
  {items.map(item => (
      <Collapse key={item}>
          I am item {item}
      </Collapse>
  ))}
</TransitionGroup>

通過這個設置,我發現我不需要在TransitionGroupCollapse上放置任何道具,並且TransitionGroup處理了循環渲染中的所有安裝和卸載。 Material UI 不會產生最輕的 HTML output,但我想這一切都是即時渲染的,所以也許這會讓它變得更好(除非你有數千個元素,然后事情開始拖累)。

您甚至可以進一步 go 並將整個事物包裝在另一個TransitionGroup中,以涵蓋您想要刪除整個事物而不轉換所有單個項目的情況 - 在這種情況下,我將其切換為<Slide> 我絕對確定這行不通,但它似乎不在乎。 您也可以嘗試語義化並使用“組件”屬性,而不是包裝在另一個元素中,例如

<TransitionGroup>
  {items.length > 0 && (
    <Slide>
      <TransitionGroup component="ul">
        {items.map((item) => (
          <Collapse component="li" key={item}>I am item {item}</Collapse>
        ))}
      </TransitionGroup>
    </Slide>
  )}
</TransitionGroup>

我通過以下方式更改了沙箱

  • 包含來自react-transition-group TransitionGroup
  • 更改了“添加”邏輯,以便組件不屬於“項目”數組 - 該數組僅包含渲染組件所需的數據
  • 我添加了一個簡單的“計數”並將其推送到數組中,以便為項目提供唯一索引(最初使用的是Math.random ,但我想要一個“更漂亮”的輸出)。 通常,您的項目可能來自已設置唯一 ID 的數據庫。
  • 根據數組中的數據在循環中渲染組件(這可以在單獨的 function 中完成,但要點是組件沒有存儲在數組中)
  • 添加了“刪除” function 以顯示單個項目的刪除
  • 將整個組包裹在第二個<TransitionGroup>中,以表明卸載可以發生在組級別
  • 放入一些簡單的樣式以更好地了解效果。 您可以在這里使用 Material UI 組件,但只是想保持簡單。

希望這對將來的某人有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM