React核心入门

安装官方脚手架:

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;

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容

  • React简介 (1)简介 React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaSc...
    鱼鱼吃猫猫阅读 1,609评论 1 6
  • 起步 安装官方脚手架: npm install -g create-react-app 创建项目: create-...
    Twoold阅读 1,177评论 0 0
  • 40、React 什么是React?React 是一个用于构建用户界面的框架(采用的是MVC模式):集中处理VIE...
    萌妹撒阅读 1,001评论 0 1
  • React 教程 React 是一个用于构建用户界面的 JAVASCRIPT 库。React主要用于构建UI,很多...
    StevenHu_Sir阅读 4,799评论 0 1
  • 近来React.js变得越来越流行,本文就来谈一谈React.js的入门实践,通过分析一些常用的概念,以及提供一些...
    年轻人多学点阅读 1,760评论 0 8