react 学习笔记


环境搭建
  • 创建脚手架 工具
npx create-react-app my-app
cd my-app
npm start

问题
1 缺少 this.state 报错

每个constructor 必须赋值 this.state

2 对传值的 state 的进行类型检测

https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html#gatsby-focus-wrapper

3 props render states 的更新
  • 当组件的state 或 props 变化时, render函数就会被重新执行
  • 父组件的render 执行时,子组件的render 也将重新执行(因为父组件render时 有组件)
4 ref 用法
import React, { Component, Fragment} from 'react';

class Todolist extends Component {

    constructor(props) {
        super(props);
        this.state = {
            inputValue: ''
        }
    }
    render () {
        return (
            <Fragment>
                <div>
                    <input type="text" onChange={this.handleChange}
                        ref={(input) => { this.input = input}}/>
                </div>
            </Fragment>
        )
    }
    handleChange (event) {
        this.setState({inputValue: this.input.value})
        // 注:this.setstate 是异步的,再用ref时,最好卸载 this.setstate的回调里
        //this.setState({}, () => {
           // console.log('sdsssssss')
       // })
    }
}

export default Todolist

__

https://www.jianshu.com/p/41deb68b26ed

5 生命周期函数
    // 组件被更新之前调用, turn false 终止下面函数执行,return true才继续render函数
    shouldComponentUpdate() { }
   // 组件更新之前,shouldComponentUpdate 之后执行(必须返回true才执行)
    componentWillUpdate() { }

    // 页面挂载之前执行, 只执行一次
    componentWillMount() {}
    //  页面挂载执行,执行多次  state 改变render 执行
    render() {}
    // 页面挂载之后执行, 只执行一次
    componentDidMount() {}

   // 组件更新之后,shouldComponentUpdate 之后执行(必须返回true才执行),componentWillUpdate 之后, render函数之后,
    componentDidUpdate() { }

   // 从父组件接受了参数,并且父组件的render 函数 `重新` 被执行了就会被执行
    componentWillReceiveProps() { }

   // 组件即将被注销时,执行
    componentWillUnmount() { }
生命周期函数
  • 请求接口 可以放在 componentDidMount componentWillMount 或 constructor , 不过建议放在 componentDidMount 中
6 优化子组件
  • 如果父组件数据发生变化,不管对子组件是否有影响,子组件都会重新渲染
  • 可以通过 shouldComponentUpdate 进行优化
import React, { Component} from 'react';

class TodolistItem extends Component {

    constructor(props) {
        super(props);
        this.state = {}
    }

    render () {
        console.log(',,,,')
        return (
            <li onClick={this.handleClick}>
                {this.props.content}
            </li>
        )
    }

    // props 参数发生变化才更新dom
    shouldComponentUpdate (nextProps, nextState) {
        // nextProps 将要传的 props  nextState 将要更改的 states
        return nextProps.content !== this.props.content ? true : false
    }
}
};
7 过度属性
npm install react-transition-group --save
import React, { Component, Fragment} from 'react';
import './app.css'
import { CSSTransition } from 'react-transition-group';

class App extends Component {

  constructor (props) {
    super(props);
    this.state= {
      show: true
    }

    this.toggleFunc = this.toggleFunc.bind(this); // 函数中要用 this.setstate, 要更改指针
  }

  render () {
    return (
      <Fragment>
        {/* <div className={this.state.show ? 'show' : 'hide'}>hello world</div> */}
        <CSSTransition
          in={this.state.show}
          timeout={1000}
          classNames="fade"
          unmountOnExit 
          onEnter={(el) => {el.style.color = 'red'}}
        >
          <div>hello world</div>
        </CSSTransition>
        <button onClick={this.toggleFunc}>toggle</button>
      </Fragment>
    )
  }

  toggleFunc () {
    this.setState({
      show: this.state.show ? false : true
    })
  }
}

export default App;

/* 进场前一刻的动画 */
.fade-enter, .fade-appear {
    opacity: 0;
}
/* 进场后到动画执行完的过程之间的动画 */
.fade-enter-active, .fade-appear-active {
    opacity: 1;
    transition: opacity 1s ease-in;
}
/* 动画执行完程样式 */
.fade-enter-done {
    opacity: 1;
}
/* 出场前一刻的动画 */
.fade-exit {
    opacity: 1;
}
/* 出场到动画执行完的过程之间的动画 */
.fade-exit-active {
    opacity: 0;
    transition: opacity 1s ease-in;
}
/* 出画执行完程样式 */
.fade-exit-done {
    opacity: 0;
}

参考

8 redux
npm install --save redux
文件目录
  • index.js
import { createStore } from 'redux';
import reducer  from './reducer.js'

const store = createStore(reducer);

export default store;
  • reducer.js

const defaultState = {
    inputValue: '111',
    list: [1221,232]
}

// state 当前的state 数据, action 是 dispatch 触发过来的一个对象
// reducer 可以拷贝state  不能更改state
export default (state = defaultState, action) => {
    // console.log(state, action)
    if (action.type === CHANGE_INPUT_VALVUE) {
        const newState = JSON.parse(JSON.stringify(state))
        newState.inputValue = action.value
        return newState
    } 
    if (action.type === ADD_INPUT_VALVUE) {
        const newState = JSON.parse(JSON.stringify(state))
        newState.list.push(action.value)
        newState.inputValue = ''
        return newState
    }
    if (action.type === DELETE_INPUT_VALVUE) {
        const newState = JSON.parse(JSON.stringify(state))
        newState.list.splice(action.value, 1)
        return newState
    }
    return state
}
  • actionType.js
// todolist
export const CHANGE_INPUT_VALVUE = 'CHANGE_INPUT_VALVUE'
export const ADD_INPUT_VALVUE = 'ADD_INPUT_VALVUE'
export const DELETE_INPUT_VALVUE = 'DELETE_INPUT_VALVUE'
  • actionCreater.js
import { CHANGE_INPUT_VALVUE, ADD_INPUT_VALVUE, DELETE_INPUT_VALVUE} from './actionType.js'

export const inputChange = (value) => {
    return {
        type: CHANGE_INPUT_VALVUE,
        value: value
    }
}

export const inputAdd = (value) => {
    return {
        type: ADD_INPUT_VALVUE,
        value: value
    }
}

export const inputDelete = (value) => {
    return {
        type: DELETE_INPUT_VALVUE,
        value: value
    }
}
  • 获取redux 中的数据
import store from './store'
store.getState() // 获取数据
  • 更改数据
import store from './store'
import { inputChange, inputAdd, inputDelete } from './store/actionCreater.js'

// 创建action
const action = inputChange(event.target.value)
// 通过 store.dispatch 方法去修改 redux 中的数据
store.dispatch(action)
  • 实现redux 数据更新 自动刷新页面
import store from './store'
import React, { Component } from 'react';

class xxx extends Component {
    constructor(props) {
        super(props);
        this.state = store.getState()
        this.handleChange = this.handleChange.bind(this); // 函数中要用 this.setstate, 要更改指针

        store.subscribe(this.dataChange) // store.subscribe 订阅 当store中数据发生变化时,就会执行指定的函数
    }

    render () { return (...) }

    dataChange () { 
        this.setState(store.getState()) 
    }
}

export default xxx

9 react 无状态组件

无状态组件就是只有render 函数的ui组件

  • 相比较于 ui 组件 性能高(因为本质上是函数)
// import React, { Component } from 'react';
import React from 'react';
import { List, Input, Button } from 'antd';

// 无状态组件 就是个函数
const TodoListUi = (props) => {
    return (
        <div>
                <div>
                    <Input placeholder="输入内容" 
                        value={props.inputValue} 
                        onChange={props.handleChange}
                        style={{width: '300px'}}
                    />
                    <Button onClick={props.addDate} type="primary">提交</Button>
                </div>
                <List size="small"
                    bordered
                    style={{width: '300px'}}
                    dataSource={props.list}
                    // 函数传值时, onClick={() => {this.props.handleDelete(index)}} 绑定里一个函数来执行 this.props.handleDelete(index) 函数
                    renderItem={(item, index) => <List.Item onClick={() => {props.handleDelete(index)}}>{item}</List.Item>}
                />
            </div>
    )
}

//生成的是react ui组件 包括生命周期函数 construction render 等等
// class TodoListUi extends Component {
//     render () {
//         return (
//             <div>
//                 <div>
//                     <Input placeholder="输入内容" 
//                         value={this.props.inputValue} 
//                         onChange={this.props.handleChange}
//                         style={{width: '300px'}}
//                     />
//                     <Button onClick={this.props.addDate} type="primary">提交</Button>
//                 </div>
//                 <List size="small"
//                     bordered
//                     style={{width: '300px'}}
//                     dataSource={this.props.list}
//                     // 函数传值时, onClick={() => {this.props.handleDelete(index)}} 绑定里一个函数来执行 this.props.handleDelete(index) 函数
//                     renderItem={(item, index) => <List.Item onClick={() => {this.props.handleDelete(index)}}>{item}</List.Item>}
//                 />
//             </div>
//         )
//     }
// }

export default TodoListUi
10 redux-thunk 处理异步数据
文件目录
  • store/index.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer  from './reducer.js'

const store = createStore(reducer, applyMiddleware(thunk));

export default store;
  • store/actionCreater.js 添加
...
export const getTodoList = () => {
    // 添加 redux-thunk 后, 返回的函数自动就带 dispatch 了
    return (dispatch) => {
        setTimeout(() => {
            dispatch(initTodoList([1,2,3,4,5,6]))
        }, 1000);
    }
}
...
  • store/reducer.js 添加
...
if (action.type === INIT_TODOLIST) {
        const newState = JSON.parse(JSON.stringify(state))
        newState.list = action.value
        return newState
    }
...
  • store/actionType.js 添加
...
export const INIT_TODOLIST = 'INIT_TODOLIST'
...
  • 组件使用
...
componentDidMount () {
        store.dispatch(getTodoList())
    }
...

https://github.com/reduxjs/redux-thunk


11 搭建react 项目
  • 创建 react 项目
 npm create-react-app my-app

https://reactjs.bootcss.com/docs/create-a-new-react-app.html

  • 插件
npm install styled-components

https://www.npmjs.com/package/styled-components

作为公共样式使用

文件目录

style.js

import { createGlobalStyle } from 'styled-components'

export const GlobalStyled = createGlobalStyle`
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
    display: block;
}
body {
    line-height: 1;
    background: green;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}
`

app.js

import React, { Component } from 'react';
import { GlobalStyled } from './style.js'

class App extends Component {
    render() {
        return (
            <div className={'fontSize'}>
                {/* 样式引入 */}
                <GlobalStyled/>
                hello world
            </div>
        )
    }
}

export default App
作为组件使用
文件

index.js

import React, { Component } from 'react';
import {
    HeaderContent,
    Logo,
    Nav
} from './style';

class Header extends Component {
    render () {
        return (
            <HeaderContent>
                <Logo/>
                <Nav/>
            </HeaderContent>
        )
    }
}

export default Header;

style.js

import styled from 'styled-components';
import logo from '../../static/logo.png'

export const HeaderContent = styled.div`
    position: relative;
    height: 58px;
    width: 100%;
    border-bottom: 1px solid #f0f0f0;
`

export const Logo = styled.div`
    position: absolute;
    height: 100%;
    width: 100px;
    float: left;
    background: url(${logo});
    background-size: contain;
`

export const Nav = styled.div`
    height: 100%;
    width: 960px;
    margin: 0 auto;
    background: red;
`
  • react react-redux 安装使用
npm install redux react-redux --save-dev

app.js文件 (入口文件)

...
import {Provider} from 'react-redux'
import store from './store'

class App extends Component {
    render() {
        return (
            <Provider store={store}>
                入口文件
            </Provider>
        )
    }
}

export default App

store 文件结构

文件结构

index.js

import { createStore } from 'redux';
import reducer  from './reducers/index.js'

const store = createStore(reducer);

export default store;

actionType.js

export const FOUCESTATE = 'FOUCESTATE'
export const BLURSTATE = 'BLURSTATE'

actionCreater.js

import { FOUCESTATE, BLURSTATE } from './actionType.js'

export const fouceInput = () => {
    return {
        type: FOUCESTATE
    }
}

export const blurInput = () => {
    return {
        type: BLURSTATE
    }
}

reducers/headerReducer.js

import { FOUCESTATE, BLURSTATE } from '../actionType.js'

const defaultState = {
    fouce: false
}

// state 当前的state 数据, action 是 dispatch 触发过来的一个对象
// reducer 可以拷贝state  不能更改state
export default (state = defaultState, action) => {
    // console.log(state, action)
    if (action.type === FOUCESTATE) {
        return {
            fouce: true
        }
    } 
    if (action.type === BLURSTATE) {
        return {
            fouce: false
        }
    }
    return state
}

reducers/index.js

import { combineReducers } from 'redux'
import headerReducer from './headerReducer.js'

export default combineReducers({
    header: headerReducer
})

组件使用

import React, { Component } from 'react';
import {CSSTransition} from 'react-transition-group'
import { connect } from 'react-redux'
import { fouceInput, blurInput } from '../../store/actionCreater.js'
import {
    HeaderContent,
    Logo,
    Nav,
    NavItem,
    NavInput,
    Addtion,
    Button,
    SearchIcon
} from './style';

class Header extends Component {

    render () {
        return (
            <HeaderContent>
                <Logo/>
                <Nav>
                    <NavItem className='left active'>首页</NavItem>
                    <NavItem className='left'>下载APP</NavItem>
                    <SearchIcon>
                        <CSSTransition
                            in={this.props.fouce}
                            timeout={200}
                            classNames="slider"
                        >
                            <NavInput placeholder="搜索"
                                onFocus={this.props.fouceState}
                                onBlur ={this.props.blurState}
                                className={this.props.fouce ?  'fouce' : ''}
                            ></NavInput>
                        </CSSTransition>
                        <span 
                            className={this.props.fouce ? 'iconfont left active' : 'iconfont left'}
                        >
                            &#xe62c;
                        </span>
                    </SearchIcon>
                    <NavItem className='right gray'>
                        <span className="iconfont">&#xe636;</span>
                    </NavItem>
                    <NavItem className='right gray'>登录</NavItem>
                </Nav>
                <Addtion>
                    <Button>注册</Button>
                    <Button className='active'>
                        <span className="iconfont">&#xe63a;</span>写文章</Button>
                </Addtion>
            </HeaderContent>
        )
    }

}

const mapStateToProps = (state) => {
    return {
        fouce: state.header.fouce
    }
}
const mapDispatchToProps = (dispatch) => {
    return {
        fouceState () {
            dispatch(fouceInput())
        },
        blurState () { 
            dispatch(blurInput())
        }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Header);
  • immutable 安装
npm install immutable
npm install redux-immutable

store/reducers/headerReducer.js文件修改

import { FOUCESTATE, BLURSTATE } from '../actionType.js'
import { fromJS } from 'immutable'

const defaultState = fromJS({
    fouce: false
})

export default (state = defaultState, action) => {
    if (action.type === FOUCESTATE) {
        // state.set('fouce', true)  是返回了一个新的对象,并不是修改原来的对象
        return state.set('fouce', true)
    } 
    if (action.type === BLURSTATE) {
        return state.set('fouce', false)
    }
    return state
}

store/reducers/index.js文件修改

import { combineReducers } from 'redux-immutable'
import headerReducer from './headerReducer.js'

export default combineReducers({
    header: headerReducer
})

组件使用

...

const mapStateToProps = (state) => {
    return {
        fouce: state.get('header').get('fouce')
    }
}
...

export default connect(mapStateToProps, mapDispatchToProps)(Header);

immutable 到底干啥了

https://github.com/immutable-js/immutable-js

  • 添加路由
npm install react-router-dom --save-dev

app.js

...
import { BrowserRouter, Route } from 'react-router-dom'
import Detail from './pages/detail'
import Home from './pages/home'
...
 
class App extends Component {
    render() {
        return (
            <Provider store={store}>
                <div className={'fontSize'}>
                     ....
                    <Header/>
                    <BrowserRouter>
                        <div>
                            <Route path='/' exact component={Home}></Route>
                            <Route path='/detail' exact component={Detail}></Route>
                           //带参数路由
                             <Route path='/detail/:id' exact component={Detail}></Route>
                        </div>
                    </BrowserRouter>
                </div>
            </Provider>
        )
    }
}
export default App

link 使用

import { Link } from 'react-router-dom';

class Lists extends PureComponent {

    render () {
        return (
               <Link key={item.get('id')} to='/detail'>
               <Link key={item.get('id')} to={'/detail/'+ item.get('id')}>
                    ....
               </Link>
        )
    }
}

获取路由参数

this.props.match.params // 动态路由获取参数

js操作跳转路由

  • react 事件监听
class Home extends Component {
    ...
    componentDidMount () { // 监听事件
        this.bindEvents()
    }

    componentWillUnmount () { // 记得移除
        window.removeEventListener('scroll', this.props.changeFlag)
    }

    bindEvents () {
        window.addEventListener('scroll', this.changeFlag)
    }
    changeFlag (e) {
        console.log(e)
    }
    ...
}

  • react 组件 PureComponent

https://www.jianshu.com/p/690444f9f2dc

https://github.com/benzcar/jianshu-RN

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容