2 React

作者: ChenME | 来源:发表于2019-12-07 17:11 被阅读0次

    1. 安装脚手架工具;

    npm install -g create-react-app
    

    2. 通过 react 脚手架工具床架一个项目;

    create-react-app hello_world
    

    3. 启动项目;

    cd hello_world
    npm start
    

    4. 父组件 App.js

    import React, { Component, Fragment } from 'react';
    import { CSSTransition } from 'react-transition-group';
    
    import TodoItem from './TodoItem';
    import './style.css';
    
    class App extends Component {
      constructor(props) {
        super(props);
    
        this.onItemDel = this.onItemDel.bind(this);
        this.onSubmitEvent = this.onSubmitEvent.bind(this);
        this.onInputChangedEvent = this.onInputChangedEvent.bind(this);
        this.toggleAnim = this.toggleAnim.bind(this);
    
        this.state = {
          inputValue: "",
          list: [],
          isShow: true,
        }
      }
    
      render() {
        return (
          <Fragment>
            <div>
              {/* htmlFor:在 JSX 中为 input 框添加 focus */}
              <label htmlFor="insertWords">请输入内容</label>
              <input id="insertWords" className="input" value={this.state.inputValue} onChange={this.onInputChangedEvent} />
              <button onClick={this.onSubmitEvent}>提交</button>
            </div>
            <ul> {this.getItem()} </ul>
    
            <div>
              <label className={this.state.isShow ? "item-show" : "item-hide"}>动画效果</label>
              <button onClick={this.toggleAnim}>切换动画</button>
            </div>
    
    
            <div>
              <CSSTransition
                classNames='fade'
                in={this.state.isShow}
                timeout={2000}
                appear={true}
                unmountOnExit>
                <label >动画效果2</label>
              </CSSTransition>
              <button onClick={this.toggleAnim}>切换动画2</button>
            </div>
          </Fragment>
        );
      }
    
      componentDidMount() {
        // axios.get("/123/123").then(() => { alert("succ") }).catch(() => { alert("err") });
      }
    
      toggleAnim() {
        this.setState(() => ({ isShow: !this.state.isShow }))
      }
    
      /**
       * 输入发生改变
       * @param {obj} e 
       */
      onInputChangedEvent(e) {
        const value = e.target.value;
        this.setState(() => ({ inputValue: value }));
      }
    
      /**
       * 提交按钮
       */
      onSubmitEvent() {
        this.setState((prevState) => ({
          list: [...prevState.list, prevState.inputValue],
          inputValue: "",
        }));
      }
    
      /**
       * 获取列表项的内容
       */
      getItem() {
        return this.state.list.map((item, index) => {
          // delItem  将点击方法传递给子组件
          return <TodoItem key={item} content={item} index={index} delItem={this.onItemDel} />
        })
      }
      /**
       * 删除列表项
       * @param {int} index 
       */
      onItemDel(index) {
        this.setState((prevState) => {
          const list = [...prevState.list]
          list.splice(index, 1)
          return { list }
        })
      }
    }
    
    export default App;
    

    5. 子组件 TodoItem.js

    import React, { Component } from "react";
    import PropTypes from 'prop-types';
    
    class TodoItem extends Component {
    
        constructor(props) {
            super(props);
            this.onItemDel = this.onItemDel.bind(this);
        }
    
        render() {
            console.log('render')
            const { test, content } = this.props;
            return <li onClick={this.onItemDel}>{test} - {content}</li>
    
            // dangerouslySetInnerHTML:不将 HTML 标签转义成字符串输出出来
            // return <li  onClick={this.onItemDel} dangerouslySetInnerHTML={{ __html: content }}></li>
        }
    
        onItemDel() {
            // 调用父组件的方法
            const { delItem, index } = this.props;
            delItem(index);
        }
    
        shouldComponentUpdate(nextProps, nextState) {
            return nextProps.content !== this.props.content;
        }
    }
    
    // 类型校验
    TodoItem.propTypes = {
        test: PropTypes.string.isRequired, // isRequired 表示是必传参数
        content: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // content 既可以是 String,也可以是 number
        index: PropTypes.number,
        onItemDel: PropTypes.func,
    }
    
    // 默认值
    TodoItem.defaultProps = {
        test: 'This is default value!'
    }
    
    export default TodoItem;
    

    6. style.css

    .fade-enter,
    .fade-appear {
        opacity: 0;
    }
    
    .fade-enter-active,
    .fade-appear-active {
        opacity: 1;
        transition: opacity 2s ease-in;
    }
    
    .fade-enter-done,
    .fade-appear-done {
        opacity: 1;
    }
    
    .fade-exit {
        opacity: 1;
    }
    
    .fade-exit-active {
        opacity: 0;
        transition: opacity 2s ease-in;
    }
    
    .fade-exit-done {
        opacity: 1;
    }
    
    
    
    .item-show {
        animation: item-show 2s ease-in forwards;
    }
    
    .item-hide {
        animation: item-hide 2s ease-in forwards;
    }
    
    @keyframes item-show {
        0% {
            opacity: 0;
            color: #ff639b;
        }
    
        50% {
            opacity: 0.5;
            color: #3fd677;
        }
    
        100% {
            opacity: 1;
            color: #3564ff;
        }
    }
    
    @keyframes item-hide {
        0% {
            opacity: 1;
            color: #3564ff;
        }
    
        50% {
            opacity: 0.5;
            color: #3fd677;
        }
    
        100% {
            opacity: 0;
            color: #ff639b;
        }
    }
    

    相关文章

      网友评论

          本文标题:2 React

          本文链接:https://www.haomeiwen.com/subject/vbvugctx.html