一路繁花似锦绣前程
失败的越多,成功才越有价值

导航

 

十一、AntDesign组件库

1、react中添加class-使用第三方库classnames
import React, {PureComponent} from "react";
// 安装:npm i -S classnames
import classNames from "classnames";

export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      isActive: true
    }
  }

  render() {
    const {isActive} = this.state
    return (<div>
      {/* 1、原生react中添加class方法 */}
      <h2 className={"title active"}>我是标题1</h2>
      <h2 className={"title" + (isActive ? " active" : "")}>我是标题2</h2>
      <h2 className={["title", isActive ? "active" : ""].join(" ")}>我是标题3</h2>
      {/* 2、classnames库添加class */}
      <h3 className={classNames("title", "active")}>我是标题1</h3>
      <h3 className={classNames({"title": true, "active": true})}>我是标题1</h3>
      <h3 className={classNames(["title", {"active": true}])}>我是标题1</h3>
    </div>)
  }
}
2、antdesign简介
  • src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './layout/App';
import "./styles/index.css"
import 'dayjs/locale/zh-cn';
import {ConfigProvider} from "antd"
import locale from 'antd/locale/zh_CN';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<ConfigProvider locale={locale}>
  <App/>
</ConfigProvider>);
  • src/layout/App.js
import React, {PureComponent} from "react";
// 安装:npm i -S antd
import {Button, DatePicker} from "antd"
// 安装图标:npm i -S @ant-design/icons
import {PoweroffOutlined} from "@ant-design/icons"
// 安装:npm i -S dayjs
import dayjs from "dayjs"

export default class App extends PureComponent {
  render() {
    return (<div>
      <Button type={"primary"} icon={<PoweroffOutlined/>}>按钮</Button>
      <DatePicker defaultValue={dayjs().add(10, "day")} allowClear={false}/>
    </div>)
  }
}
3、认识craco
  • package.json
{
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "react-scripts eject"
  }
}
  • craco.config.js
// 安装:npm i -D @craco/craco
module.exports = {};
4、自定义主题
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './layout/App';
import "./styles/index.css"
import 'dayjs/locale/zh-cn';
import {ConfigProvider} from "antd"
import locale from 'antd/locale/zh_CN';

const root = ReactDOM.createRoot(document.getElementById('root'));
// 自定义主题
root.render(<ConfigProvider
  locale={locale}
  theme={{
    token: {
      colorPrimary: '#1DA57A'
    }
  }}>
  <App/>
</ConfigProvider>);
5、配置别名
  • craco.config.js
const path = require("path")

module.exports = {
  webpack: {
    alias: {
      // webstorm需要配置jsconfig.json才会有路径别名提示
      "@": path.resolve(__dirname, "src")
    }
  }
};
  • jsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"
      ]
    }
  }
}
6、案例
  • src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './layout/App';
import "./styles/index.css"
import {ConfigProvider} from "antd"
import locale from 'antd/locale/zh_CN';
import dayjs from "dayjs";
import 'dayjs/locale/zh-cn';
import relativeTime from "dayjs/plugin/relativeTime"

dayjs.locale("zh-cn")
// dayjs插件
dayjs.extend(relativeTime)

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<ConfigProvider locale={locale}>
  <App/>
</ConfigProvider>);
  • src/layout/App.js
import React, {PureComponent} from "react";
import CommonInput from "@/components/CommonInput";
import CommonItem from "@/components/CommonItem";

export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      commentList: []
    }
  }

  render() {
    return (<>
      {
        this.state.commentList.map((item, index) => {
          return <CommonItem comment={item}
                             key={item.id}
                             removeItem={e => this.removeComment(index)}/>
        })
      }
      <CommonInput submitComment={this.submitComment.bind(this)}/>
    </>)
  }

  submitComment(info) {
    this.setState({
      commentList: [...this.state.commentList, info]
    })
  }

  removeComment(index) {
    const newCommentList = [...this.state.commentList]
    newCommentList.splice(index, 1)
    this.setState({
      commentList: newCommentList
    })
  }
}
  • src/components/CommonInput.js
import React, {PureComponent} from "react";
import {Input, Button} from "antd";
import dayjs from "dayjs";

export default class CommonInput extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      content: ""
    }
  }

  render() {
    return (<div>
      <Input.TextArea rows={4}
                      value={this.state.content}
                      onChange={e => this.handleChange(e)}/>
      <Button type={"primary"} onClick={e => this.addComment()}>添加评论</Button>
    </div>)
  }

  handleChange(event) {
    this.setState({
      content: event.target.value
    })
  }

  addComment() {
    if (this.state.content) {
      const commentInfo = {
        id: dayjs().valueOf(),
        avatar: "https://himg.bdimg.com/sys/portraitn/item/public.1.ad0d64c5.9sfie_WOcRvlqCxH_2MKnQ",
        nickname: "斧王",
        datetime: dayjs(),
        content: this.state.content
      }
      this.props.submitComment(commentInfo)
      this.setState({
        content: ""
      })
    }
  }
}
  • src/components/CommonItem.js
import React, {PureComponent} from "react";
// 安装(使用过高版本会报错,与antd版本一致):npm i @ant-design/compatible
import {Comment} from "@ant-design/compatible"
import {Avatar, Tooltip} from "antd"
import {DeleteOutlined} from "@ant-design/icons";

export default class CommonItem extends PureComponent {
  render() {
    const {nickname, avatar, content, datetime} = this.props.comment
    return (<div>
      <Comment
        author={<a href="/#">{nickname}</a>}
        avatar={<Avatar src={avatar} alt={nickname}/>}
        content={<p>{content}</p>}
        datetime={<Tooltip title={datetime.format("YYYY-MM-DD")}>
          <span>{datetime.fromNow()}</span>
        </Tooltip>}
        actions={[
          <span onClick={e => this.removeItem()}><DeleteOutlined/>删除</span>
        ]}
      />
    </div>)
  }

  removeItem() {
    this.props.removeItem()
  }
}

十二、axios库的使用

1、axios的基本使用
import React, {PureComponent} from "react";
import axios from "axios"

export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      products: []
    }
  }

  /**
   * 1、axios:ajax i/o system
   * 2、安装:npm i -S axios
   * 3、请求测试网站:https://httpbin.org
   * 4、使用方式:
   *     - axios(config)
   *     - axios.request(config):其它方式都是调用此种方式
   *     - axios.get(url[, config]):查
   *     - axios.delete(url[, config]):删
   *     - axios.head(url[, config])
   *     - axios.post(url[, data[, config]]):增
   *     - axios.put(url[, data[, config]]):改
   *     - axios.patch(url[, data[, config]])
   */
  async componentDidMount() {
    // 默认get请求
    axios({
      url: "https://httpbin.org/get",
      params: {name: "冰龙", age: 18}
    }).then(res => {
      // 处理数据
      // this.setState({
      //   products: [...this.state.products, ...res]
      // })
    }).catch(console.log)

    const request1 = axios({
      url: "https://httpbin.org/post",
      data: {name: "神谕者", age: 19},
      method: "post"
    })

    const request2 = axios.get("https://httpbin.org/get", {
      params: {name: "白牛", age: 20}
    })

    try {
      const result = await axios.post("https://httpbin.org/post", {name: "火枪", age: 21})
      console.log(result)
    } catch (err) {
      console.log(err)
    }

    // Promise.all()
    axios.all([request1, request2]).then(([res1, res2]) => {
      console.log(res1, res2)
    })
    const p1 = new Promise(resolve => {
      setTimeout(() => {
        resolve("奇美拉")
      }, 1000)
    })
    const p2 = new Promise(resolve => {
      setTimeout(() => {
        resolve("狮鹫")
      }, 3000)
    })
    Promise.all([p1, p2]).then(res => {
      console.log(res)
    })
  }

  render() {
    return (<>
      APP
    </>)
  }
}
2、axios的配置信息
// 1、请求配置选项
// 2、响应结构信息
// 3、全局默认配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
/**
 * 4、自定义实例默认配置:
 *     - 优先是请求的config参数配置:instance({baseURL: "111"})
 *     - 其次是实例的default中的配置:instance.defaults.baseURL = "222"
 *     - 再是创建实例时的配置:const instance = axios.create({baseURL: "333"})
 *     - 最后全局的配置:axios.defaults.baseURL = "444"
 */
const instance = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000
});
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
3、axios拦截器
  • src/layout/App.js
import React, {PureComponent} from "react";
import request from "@/utils/request"

export default class App extends PureComponent {
  componentDidMount() {
    request({
      url: "/get",
      params: {name: "小小", age: 18}
    }).then(console.log)
  }

  render() {
    return (<></>)
  }
}
  • src/utils/request.js
import axios from "axios"

const config = {
  development: {
    baseURL: "https://httpbin.org",
    timeout: 5000
  },
  production: {
    baseURL: "https://httpbin.org",
    timeout: 5000
  }
}
const instance = axios.create(config[process.env.NODE_ENV])

instance.interceptors.request.use(config => {
  // 1、发送网络请求时,在界面中间位置显示Loading的组件
  // 2、某一些请求要求用户必须携带token,如果没有携带,那么直接跳转到登录页面(router)
  // 3、params/data序列化的操作
  console.log("请求被拦截")
  return config
}, err => {
})

instance.interceptors.response.use(res => {
  return res.data
}, err => {
  if (err && err.response) {
    switch (err.response.status) {
      case 400:
        console.log("请求错误")
        break;
      case 401:
        console.log("未授权访问")
        break;
      default:
        console.log("其它错误信息")
    }
  }
  return err
})

export default instance

十三、react过渡动画

1、react-transition-group使用(CSSTransition)
  • src/layout/App.js
import React, {PureComponent} from "react";
// 安装:npm i -S react-transition-group
import {CSSTransition} from "react-transition-group";
import "@/styles/animation.css"

export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      show: true
    }
  }

  /**
   * 1、官网:https://reactcommunity.org/react-transition-group/
   * 2、CSSTransition执行过程中,有三个状态:appear、enter、exit
   *     - 开始状态:对应的类是-appear、-enter、-exit
   *     - 执行动画:对应的类是-appear-active、-enter-active、-exit-active
   *     - 执行结束:对应的类是-appear-done、-enter-done、-exit-done
   *     - in从false到true执行enter,in从true到false执行exit
   * 3、unmountOnExit:exit动画结束时卸载节点
   * 4、挂载节点时(不是false到true)执行appear动画
   * 5、钩子函数
   */
  render() {
    return (<>
      <button onClick={e => {
        this.setState({show: !this.state.show})
      }}>按钮
      </button>
      <CSSTransition in={this.state.show}
                     timeout={1000}
                     classNames={"card"}
                     unmountOnExit={true}
                     appear
                     onEnter={el => console.log("开始进入")}
                     onEntering={el => console.log("正在进入")}
                     onEntered={el => console.log("进入完成")}
                     onExit={el => console.log("开始退出")}
                     onExiting={el => console.log("正在退出")}
                     onExited={el => console.log("退出完成")}>
        <div>巨牙海民</div>
      </CSSTransition>
    </>)
  }
}
  • src/styles/animation.css
.card-enter, .card-appear {
  opacity: 0;
}

.card-enter-active, .card-appear-active {
  opacity: 1;
  transition: all 1s;
}

.card-enter-done, .card-appear-done {
  opacity: 1;
}

.card-exit {
  opacity: 1;
}

.card-exit-active {
  opacity: 0;
  transition: all 1s;
}

.card-exit-done {
  opacity: 0;
}
2、react-transition-group使用(SwitchTransition)
  • src/layout/App.js
import React, {PureComponent} from "react";
import {CSSTransition, SwitchTransition} from "react-transition-group";
import "@/styles/animation.css"

export default class App extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      isOn: true
    }
  }

  /**
   * 1、SwitchTransition可以完成两个组件之间切换的炫酷动画
   *     - 比如我们有一个按钮需要在on和off之间切换,我们希望看到on先从左侧退出,off再从右侧进入
   *     - 这个动画在vue中被称之为vue transition modes
   *     - react-transition-group中使用SwitchTransition来实现该动画
   * 2、SwitchTransition中主要有一个属性:mode,有两个值
   *     - in-out:表示新组件先进入,旧组件再移除
   *     - out-in:表示就组件先移除,新组件再进入
   */
  render() {
    return (<>
      <SwitchTransition mode="out-in">
        <CSSTransition key={this.state.isOn ? "on" : "off"}
                       classNames="btn"
                       timeout={1000}>
          <button onClick={e => {
            this.setState({isOn: !this.state.isOn})
          }}>{this.state.isOn ? "on" : "off"}
          </button>
        </CSSTransition>
      </SwitchTransition>
    </>)
  }
}
  • src/styles/animation.css
.btn-enter {
  opacity: 0;
  transform: translateX(100%);
}

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

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

.btn-exit-active {
  opacity: 0;
  transform: translateX(-100%);
  transition: all 1s;
}
3、react-transition-group使用(TransitionGroup)
  • src/layout/App.js
import React, {PureComponent} from "react";
import {CSSTransition, TransitionGroup} from "react-transition-group";
import "@/styles/animation.css"

export default class App extends PureComponent {
  constructor(props) {
    super(props);
    const now = Date.now()
    this.state = {
      names: [
        {id: now + 1, name: "复仇之魂"},
        {id: now + 2, name: "双头龙"},
        {id: now + 3, name: "发条"}
      ]
    }
  }

  render() {
    return (<>
      <button onClick={e => this.addName()}>添加</button>
      <TransitionGroup>
        {
          this.state.names.map(item => {
            return (<CSSTransition key={item.id}
                                   timeout={1000}
                                   classNames="item">
              <div>
                {item.name}
                <button onClick={e => this.removeItem(item)}>删除</button>
              </div>
            </CSSTransition>)
          })
        }
      </TransitionGroup>
    </>)
  }

  addName() {
    this.setState({
      names: [...this.state.names, {id: Date.now(), name: "全能骑士"}]
    })
  }

  removeItem(row) {
    this.setState({
      names: this.state.names.filter(item => item.id !== row.id)
    })
  }
}
  • src/styles/animation.css
.item-enter {
  opacity: 0;
}

.item-enter-active {
  opacity: 1;
  transition: all 1s;
}

.item-enter-done {
  opacity: 1;
  color: red;
}

.item-exit {
  opacity: 1;
}

.item-exit-active {
  opacity: 0;
  transition: all 1s;
}

.item-exit-done {
  opacity: 0;
}
posted on 2022-11-30 23:12  一路繁花似锦绣前程  阅读(33)  评论(0编辑  收藏  举报