React核心入门

2019-10-28  本文已影响0人  key君

安装官方脚手架:

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;

上一篇下一篇

猜你喜欢

热点阅读