React的Portal,fragment,严格模式,动画实现(react-transition-group)

269 阅读2分钟

React的Portal

image.png

image.png

Modal组件案例

image.png

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta name="description" content="Web site created using create-react-app" />
    <title>React App</title>
    <style>
      #modal {
        position: fixed;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
      }
    </style>
  </head>
  <body>
    <div id="root"></div>

    <!-- portal使用 -->
    <div id="zm"></div>

    <!-- Modal组件案例 -->
    <div id="modal"></div>
  </body>
</html>
import { PureComponent } from "react";
import { createPortal } from "react-dom";
export class Modal extends PureComponent {
  render() {
    return createPortal(this.props.children, document.getElementById("modal"));
  }
}
export default Modal;
import React, { PureComponent } from "react";
import { createPortal } from "react-dom";
import Modal from "./Modal";
export class App extends PureComponent {
  render() {
    return (
      <div className="app">
        <h1>App h1</h1>
        {createPortal(<h2>App h2</h2>, document.querySelector("#zm"))}
        <div>
          modal:
          <Modal>
            <h1>children modal</h1>
            <p>content</p>
            <i>modal i</i>
          </Modal>
        </div>
      </div>
    );
  }
}
export default App;

image.png

React的fragment

image.png

import React, { Fragment, PureComponent } from "react";
export class App extends PureComponent {
  constructor() {
    super();
    this.state = {
      ikuns: [
        { id: 1, name: "zm", age: 19 },
        { id: 2, name: "dhs", age: 20 },
        { id: 3, name: "ww", age: 21 },
      ],
    };
  }
  render() {
    const { ikuns } = this.state;
    return (
      <>
        <h2>I am App title</h2>
        <p>I am App content,hahaha</p>
        <hr />
        {ikuns.map((item) => {
          return (
            <Fragment key={item.id}>
              <h2>{item.name}</h2>
              <p>{item.age}</p>
            </Fragment>
          );
        })}
      </>
    );
  }
}
export default App;

React的严格模式

image.png

严格模式检查的是什么?

image.png

React的动画实现

coderwhy老师博客链接

react-transition-group介绍

npm i react-transition-group --save

image.png

CSSTransition

常见属性

image.png

image.png

import React, { PureComponent, createRef } from "react";
import { CSSTransition } from "react-transition-group";
import "./style.css";

export class App extends PureComponent {
  constructor() {
    super();
    this.state = {
      isShow: false,
    };
    this.sectionRef = createRef();
  }
  render() {
    const { isShow } = this.state;
    return (
      <div>
        <h2>CSSTransition动画</h2>
        <button onClick={(e) => this.setState({ isShow: !isShow })}>change</button>
        {/* {isShow && <h2>zm</h2>} */}
        <CSSTransition
          in={isShow}
          classNames="zm"
          timeout={2000}
          nodeRef={this.sectionRef}
          unmountOnExit={true}
          appear
          onEnter={(e) => console.log("开始进入动画")}
          onEntering={(e) => console.log("执行进入动画")}
          onEntered={(e) => console.log("执行进入结束")}
          onExit={(e) => console.log("开始离开动画")}
          onExiting={(e) => console.log("执行离开动画")}
          onExited={(e) => console.log("执行离开结束")}
        >
          <div className="section" ref={this.sectionRef}>
            <h2>zm</h2>
            <p>this is content</p>
          </div>
        </CSSTransition>
      </div>
    );
  }
}
export default App;
/* 进入动画 */
.zm-enter {
  opacity: 0;
}

.zm-enter-active {
  opacity: 1;
  transition: opacity 2s ease;
}

/* 离开动画 */
.zm-exit {
  opacity: 1;
}
.zm-exit-active {
  opacity: 0;
  transition: opacity 2s ease;
}

SwitchTransition

image.png

import React, { PureComponent } from "react";
import { SwitchTransition, CSSTransition } from "react-transition-group";
import "./style.css";

export class App extends PureComponent {
  constructor() {
    super();
    this.state = {
      isLogin: true,
    };
  }
  render() {
    const { isLogin } = this.state;
    return (
      <div>
        <SwitchTransition mode="out-in">
          <CSSTransition key={isLogin ? "exit" : "login"} classNames="login" timeout={1000}>
            <button onClick={(e) => this.setState({ isLogin: !isLogin })}>{isLogin ? "退出" : "登录"}</button>
          </CSSTransition>
        </SwitchTransition>
      </div>
    );
  }
}
export default App;
.login-enter {
  transform: translateX(100px);
  opacity: 0;
}

.login-enter-active {
  transform: translateX(0);
  opacity: 1;
  transition: all 1s ease;
}

.login-exit {
  transform: translateX(0);
  opacity: 1;
}

.login-exit-active {
  transform: translateX(-100px);
  opacity: 0;
  transition: all 1s ease;
}

TransitionGroup

import React, { PureComponent } from "react";
import { TransitionGroup, CSSTransition } from "react-transition-group";
import "./style.css";
export class App extends PureComponent {
  constructor() {
    super();
    this.state = {
      books: [
        { id: 1, name: "js高级程序设计", price: 100 },
        { id: 2, name: "js重难点", price: 10 },
        { id: 3, name: "Vue设计与实现", price: 20 },
      ],
    };
  }
  add() {
    const book = { id: new Date().getTime(), name: "book_name", price: 999 };
    const books = [...this.state.books];
    books.push(book);
    this.setState({ books });
  }
  delFn(index) {
    const books = [...this.state.books];
    books.splice(index, 1);
    this.setState({
      books,
    });
  }
  render() {
    const { books } = this.state;
    return (
      <div>
        <h2>书籍列表</h2>
        <TransitionGroup component="ul">
          {books.map((item, index) => {
            return (
              <CSSTransition key={item.id} classNames="book" timeout={1000}>
                <li>
                  <span>
                    {item.name}-{item.price}
                  </span>
                  <button onClick={(e) => this.delFn(index)}>del</button>
                </li>
              </CSSTransition>
            );
          })}
        </TransitionGroup>
        <button onClick={(e) => this.add()}>add book</button>
      </div>
    );
  }
}
export default App;
.book-enter {
  transform: translateX(100px);
  opacity: 0;
}

.book-enter-active {
  transform: translateX(0);
  opacity: 1;
  transition: all 1s ease;
}

.book-exit {
  transform: translateX(0);
  opacity: 1;
}

.book-exit-active {
  transform: translateX(-100px);
  opacity: 0;
  transition: all 1s ease;
}