美文网首页
React核心入门

React核心入门

作者: key君 | 来源:发表于2019-10-28 20:38 被阅读0次

    安装官方脚手架:

    sudo npm install -g create-react-app

    创建项目:

    npx create-react-app lesson1

    进入项目目录:

    cd lesson1

    启动项目:

    npm start

    暴露配置项

    npm run eject

    安装sass(模块化)

    npm install sass -D

    React负责逻辑控制,数据->VDOM
    ReactDom渲染实际DOM,VDOM->DOM
    React使用JSX来描述UI
    入口文件定义在webpack.config.js

    先学一下JSX的语法

    入口JS文件:
    src/index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import logo from './logo.svg';
    import "./index.css";
    import styles from './index2.module.scss';
    const name = 'xiaoming';
    function formatName(user){
        return user.firstName + " " + user.lastName;
    }
    const jsx = (
        <div className={styles.app}>
            jsx
            <p>{name}</p>
            <p>{formatName({firstName:'xiao',lastName:'ming'})}</p>
            {
                name? name: '登录'
            }
            <ul>
                {
                    [0,1,2].map(item => {
                        return <li key={item}>
                            {item}
                        </li>
                    })
                }
            </ul>
            <img className={styles.logo} src={logo}/>
        </div>
    )
    //jsx里面用了React babel loader会把jsx的语法转成vdom render转化真实dom插入节点
    ReactDOM.render(jsx, document.getElementById('root'));
    

    src/index.css

    body {
      margin: 0;
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
        "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
        sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }
    
    code {
      font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
        monospace;
    }
    
    .logo{
      width: 100px;
    }
    

    src/index2.module.scss

    .app{
        .logo{
            width: 10px;
        }
    }
    

    创建src/pages/ClassComponent.js组件

    setState同步的三种方法
    1.传入箭头函数,拿参数nextState里面的属性
    2.setTimeout,setTimeout在react里面是同步的
    3.原生事件操作,也是同步的

    import React,{ Component } from 'react';
    
    export default class ClassComponent extends Component {
        constructor(props){
            super(props);
            this.state = {
                date: new Date(),
                counter: 0
            };
        }
        //组件挂载后执行
        componentDidMount(){
            this.timer = setInterval(() => {
                //每一次setState都会执行render
                this.setState({
                    date: new Date()
                });
            },1000);
            //方法三 原生事件
            document.getElementById("test").addEventListener('click',()=>{
                this.setState({
                    counter: this.state.counter + 1
                });
            })
        }
        //组件卸载之前完成
        componentWillUnmount(){
            if(this.timer){
                clearInterval(this.timer);
            }
        }
    
        setCounter = ()=>{
            //setState是异步的 实现同步有几种办法?
            //方法一 传函数 拿到一个nextState参数
            // this.setState(nextState => {
            //     return {
            //         counter: nextState.counter + 1
            //     };
            // });
            // this.setState(nextState => {
            //     return {
            //         counter: nextState.counter + 2
            //     };
            // });
    
            // 方法二 setTimeout
            // setTimeout(()=>{
            //     this.setState({
            //         counter: this.state.counter + 1
            //     });
            // },0);
            
            
    
            // this.setState({
            //     counter: this.state.counter + 1
            // },
            // () => {
            //     //callback可以马上拿到更新后的值
            // })
        }
        render(){
            const name = 'xiaoming';
            const {date,counter} = this.state;
            return (
                <div>
                    <h1>ClassComponent</h1>
                    <p>{name}</p>
                    <div>{date.toLocaleTimeString()}</div>
                    <div id="test" onClick={this.setCounter}>{counter}</div>
                </div>
            )
        }
    };
    
    

    在App.js引入

    import React from 'react';
    import ClassComponent from './pages/ClassComponent';
    
    function App() {
      return (
        <div className="App">
          <ClassComponent />
        </div>
      );
    }
    
    export default App;
    
    

    在index.js引入

    ReactDOM.render(<App/>, document.getElementById('root'));
    
    函数代替组件

    src/pages/FuncComponent.js

    import React,{useState,useEffect} from 'react';
    
    export default function FuncComponent() {
      const [date,setDate] = useState(new Date());
      const [counter,setCounter] = useState(0);
      useEffect(() => {
          //组件装载和更新都会走 可以控制依赖
        const timer = setInterval(() => {
            setDate(new Date());
        },1000)
        //回调就是卸载
        return () => clearInterval(timer);
      },[]);//第二个参数是依赖数组 空数组是没有依赖 只执行一次,[date]依赖date date更新就会执行
      return (
          <div>
              <h1>FuncComponent</h1>
              <p>{date.toLocaleTimeString()}</p>
          </div>
      )
    };
    
    

    app.js引入

    import React from 'react';
    import FuncComponent from './pages/FuncComponent';
    function App() {
      return (
        <div className="App">
            <FuncComponent />
        </div>
      );
    }
    
    export default App;
    
    
    事件处理

    src/pages/EventHandle.js

    import React, { Component } from 'react'
    
    export default class EventHandle extends Component {
        constructor(props){
            super(props);
            this.state = {
                name: ""//显示值
            };
            //非箭头函数绑定this
            this.submit = this.submit.bind(this);
        }
        submit(){
            //打印输入框的值
            console.log(this.refs["input"].value);   
            console.log(this.state.name);
            //props传值
            this.props.tellme('呵呵哈哈哈');
        };
        //箭头函数不用绑定this
        //单向数据流 没有双向绑定
        setChange = event => {
            //更新值
            this.setState({
                name: event.target.value
            })
        };
        render() {
            const {name} = this.state;
            //props接受传值
            const {store} = this.props;
            console.log(store.user);
            
            return (
                <div>
                    <h1>EventHandle</h1>
                    <input value={name} onChange={this.setChange} ref="input"/>
                    <button onClick={this.submit}>login</button>
                </div>
            )
        }
    }
    
    
    

    app.js引入

    import React from 'react';
    // import ClassComponent from './pages/ClassComponent';
    import FuncComponent from './pages/FuncComponent';
    import EventHandle from './pages/EventHandle';
    
    const store = {
      user: 'tom'
    }
    
    function tellme(msg){
      console.log(msg);
      
    }
    
    function App() {
      return (
        <div className="App">
          {/* <ClassComponent /> */}
          {/* <FuncComponent /> */}
          <EventHandle store={store} tellme={tellme}/>
        </div>
      );
    }
    
    export default App;
    
    
    React的生命周期

    V16.3之前的生命周期
    constructor() 初始化
    componentWillMount() 将要挂载
    render() 挂载(执行多次)
    componentDidMount() 挂载完成
    组件运行时
    state改变
    shouldComponentUpdate() 性能优化点 返回true走更新组件 返回false走(不刷新页面 值会更新)
    componentWillUpdate() 组件将要更新
    render()
    componentDidUpdate() 组件更新完毕
    componentWillUnmount() 组件卸载

    父组件重新render()改变props
    componentWillReceiveProps()
    shouldComponentUpdate()...

    创建src/pages/LifeCycle.js
    import React, { Component } from 'react'
    
    //第一次创建顺序:constructor componentWillMount render componentDidMount v16.3
    //第一次创建顺序:constructor getDerivedStateFromProps render componentDidMount v16.4以后
    //更新值的时候顺序:shouldComponentUpdate  componentWillUpdate render componentWillReceiveProps(componentWillUnmount) componentDidUpdate v16.3
    //更新值的时候顺序:shouldComponentUpdate  getSnapshotBeforeUpdate render  componentDidUpdate v16.4以后
    //加UNSAFE_ v17版本可能会废弃
    export default class LifeCycle extends Component {
        constructor(props){
            super(props);
            this.state = {
                counter: 0//显示值
            };
            console.log('constructor');
        }
        //跟之前的componentWillMount类似
        static getDerivedStateFromProps(props,state){
            console.log('getDerivedStateFromProps');
            //返回null 不对state作改变 逢5重置0
            return state.counter !== 5? null: {counter: 0};
        }
        //更新之前 componentWillUpdate类似 值更改触发
        getSnapshotBeforeUpdate(prevProps,prevState){
            // prevState.counter 拿到上一次的值
            console.log('getSnapshotBeforeUpdate');
            return null;
        }
    
        // UNSAFE_componentWillMount(){
        //     console.log('componentWillMount');
        // }
    
        componentDidMount(){
            console.log('componentDidMount');
        }
    
        
    
        // UNSAFE_componentWillUpdate(){
        //     console.log('componentWillUpdate');
        // }
    
        componentDidUpdate(){
            console.log('componentDidUpdate');
        }
    
        shouldComponentUpdate(nextProps,nextState){
            //nextState.counter就是本次更新的值
            console.log('shouldComponentUpdate');
            //不等于3就刷新界面
            return nextState.counter !== 3;
        }
        setCounter = () =>{
            // console.log('点击时间');
            this.setState({
                counter: this.state.counter + 1,
            });
        };
        render() {
            console.log('render');
            
            const {counter} = this.state;
            return (
                <div>
                    <h1></h1>
                    <p onClick={this.setCounter}>{counter}</p>
                    {counter !=2 && <Foo counter={counter}/>}
                </div>
            )
        }
    }
    
    
    class Foo extends Component{
        // UNSAFE_componentWillReceiveProps(props,state){
        //     console.log('componentWillReceiveProps');
            
        // }
    
        componentWillUnmount(){
            console.log('componentWillUnmount');
            
        }
    
        render(){
            const {counter} = this.props;
            // console.log(counter);
            
            return (
                <div>
                    <h1>Foo</h1>
                    <p>{counter}</p>
                </div>
            )
        }
    }
    

    App.js引入

    import React from 'react';
    // import ClassComponent from './pages/ClassComponent';
    // import FuncComponent from './pages/FuncComponent';
    // import EventHandle from './pages/EventHandle';
    import LifeCycle from './pages/LifeCycle';
    
    // const store = {
    //   user: 'tom'
    // }
    
    // function tellme(msg){
    //   console.log(msg);
      
    // }
    
    function App() {
      return (
        <div className="App">
          {/* <ClassComponent /> */}
          {/* <FuncComponent /> */}
          {/* <EventHandle store={store} tellme={tellme}/> */}
          <LifeCycle/>
        </div>
      );
    }
    
    export default App;
    
    

    相关文章

      网友评论

          本文标题:React核心入门

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