头像
wscats
    阅读 41 分钟
    中文
    25
    头图

    Webpack

    • demo
    1. Lint

    2. push

        • Pages: git pages
    3. Story Book

    create-react-app

    $ npm install -g create-react-app
    $ create-react-app your-app 注意命名方式
    
    Creating a new React app in /dir/your-app.
    
    Installing packages. This might take a couple of minutes. 安装过程较慢,可以推荐学员使用yarn
    Installing react, react-dom, and react-scripts... 
    $ npx create-react-app your-app    也可以实现相同的效果
    Success! Created your-app at /dir/your-app
    Inside that directory, you can run several commands:
    
      npm start
        Starts the development server.
    
      npm run build
        Bundles the app into static files for production.
    
      npm test
        Starts the test runner.
    
      npm run eject
        Removes this tool and copies build dependencies, configuration files
        and scripts into the app directory. If you do this, you can’t go back!
    
    We suggest that you begin by typing:
    
      cd your-app
      npm start
    
    Happy hacking!
    ├── README.md                            使用方法的文档
    ├── node_modules                    所有的依赖安装的目录
    ├── package-lock.json            锁定安装时的包的版本号,保证团队的依赖能保证一致。
    ├── package.json                    
    ├── public                                静态公共目录
    └── src                                        开发用的源代码目录
    React Fiber:
    // 从 react 的包当中引入了 React。只要你要写 React.js 组件就必须引入React, 因为react里有一种语法叫JSX,稍后会讲到JSX,要写JSX,就必须引入React
    import React from 'react'
    // ReactDOM 可以帮助我们把 React 组件渲染到页面上去,没有其它的作用了。它是从 react-dom 中引入的,而不是从 react 引入。
    import ReactDOM from 'react-dom'
    
    // ReactDOM里有一个render方法,功能就是把组件渲染并且构造 DOM 树,然后插入到页面上某个特定的元素上
    ReactDOM.render(
    // 这里就比较奇怪了,它并不是一个字符串,看起来像是纯 HTML 代码写在 JavaScript 代码里面。语法错误吗?这并不是合法的 JavaScript 代码, “在 JavaScript 写的标签的”语法叫 JSX- JavaScript XML。
      <h1>欢迎进入React的世界</h1>,
    // 渲染到哪里
      document.getElementById('root')
    )
    import React from 'react'
    import ReactDOM from 'react-dom'
    // 这里感觉又不习惯了?这是在用JSX定义一下react元素
    const app = <h1>欢迎进入React的世界</h1>
    ReactDOM.render(
      app,
      document.getElementById('root')
    )
    import React from 'react'
    import ReactDOM from 'react-dom'
    
    // 特别注意这里的写法,如果要在JSX里写js表达式(只能是表达式,不能流程控制),就需要加 {},包括注释也是一样,并且可以多层嵌套
    const app = (props) => <h1>欢迎进入{props.name}的世界</h1>
    
    ReactDOM.render(
      app({
        name: 'react'
      }),
      document.getElementById('root')
    )
    import React from 'react'
    import ReactDOM from 'react-dom'
    
    const App = (props) => <h1>欢迎进入{props.name}的世界</h1>
    
    ReactDOM.render(
      // React组件的调用方式
      <App name="react" />,
      document.getElementById('root')
    )
    import React from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends React.Component {
      render () {
        return (
          // 注意这里得用this.props.name, 必须用this.props
          <h1>欢迎进入{this.props.name}的世界</h1>
          )
      }
    }
    ReactDOM.render(
      <App name="react" />,
      document.getElementById('root')
    )
    • import React from 'react'
      import ReactDOM from 'react-dom'
      
      class App extends React.Component {
        render () {
          return (
                <h1>欢迎进入{this.props.name}的世界</h1>
            )
        }
      }
      
      const app = new App({
        name: 'react'
      }).render()
      
      ReactDOM.render(
        app,
        document.getElementById('root')
      )
    React.createClass({
      render () {
        return (
          <div>{this.props.xxx}</div>
          )
      }
    })
    // 从 react 的包当中引入了 React 和 React.js 的组件父类 Component
    // 还引入了一个React.js里的一种特殊的组件 Fragment
    import React, { Component, Fragment } from 'react'
    import ReactDOM from 'react-dom'
    
    class Title extends Component {
      render () {
        return (
          <h1>欢迎进入React的世界</h1>
          )
      }
    }
    class Content extends Component {
      render () {
        return (
          <p>React.js是一个构建UI的库</p>
          )
      }
    }
    /** 由于每个React组件只能有一个根节点,所以要渲染多个组件的时候,需要在最外层包一个容器,如果使用div, 会生成多余的一层dom
    class App extends Component {
      render () {
        return (
            <div>
                <Title />
            <Content />
          </div>
          )
      }
    }
    **/
    // 如果不想生成多余的一层dom可以使用React提供的Fragment组件在最外层进行包裹
    class App extends Component {
      render () {
        return (
          <Fragment>
              <Title />
            <Content />
          </Fragment>
          )
      }
    }
    ReactDOM.render(
      <App/>,
      document.getElementById('root')
    )
    <div class='app' id='appRoot'>
      <h1 class='title'>欢迎进入React的世界</h1>
      <p>
        React.js 是一个帮助你构建页面 UI 的库
      </p>
    </div>
    {
      tag: 'div',
      attrs: { className: 'app', id: 'appRoot'},
      children: [
        {
          tag: 'h1',
          attrs: { className: 'title' },
          children: ['欢迎进入React的世界']
        },
        {
          tag: 'p',
          attrs: null,
          children: ['React.js 是一个构建页面 UI 的库']
        }
      ]
    }
    import React from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends React.Component {
      render () {
        return (
          <div className='app' id='appRoot'>
            <h1 className='title'>欢迎进入React的世界</h1>
            <p>
              React.js 是一个构建页面 UI 的库
            </p>
          </div>
        )
      }
    }
    
    ReactDOM.render(
        <App />,
      document.getElementById('root')
    )
    import React from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends React.Component {
      render () {
        return (
          React.createElement(
            "div",
            {
              className: 'app',
              id: 'appRoot'
            },
            React.createElement(
              "h1",
              { className: 'title' },
              "欢迎进入React的世界"
            ),
            React.createElement(
              "p",
              null,
              "React.js 是一个构建页面 UI 的库"
            )
          )
        )
      }
    }
    
    ReactDOM.render(
        React.createElement(App),
      document.getElementById('root')
    )
    React.createElement(
      type,
      [props],
      [...children]
    )
    // 注意这里的两个括号,第一个表示我们在要JSX里插入JS了,第二个是对象的括号
     <p style={{color:'red', fontSize:'14px'}}>Hello world</p>
    <p className="hello" style = {this.style}>Hello world</p>
    • css-in-js

    TodoList

    /your-project

    • src

      • components

        • YourComponentOne

          • index.js/YourComponentOne.js
        • YourComponentTwo

          • index.js/YourComponentTwo.js
    import React, { Component, Fragment } from 'react'
    import ReactDOM from 'react-dom'
    
    class Title extends Component {
      render () {
        return (
              <h1>欢迎进入{this.props.name}的世界</h1>
          )
      }
    }
    
    const Content = (props) => {
      return (
        <p>{props.name}是一个构建UI的库</p>
      )
    }
    
    class App extends Component {
      render () {
        return (
              <Fragment>
              <Title name="React" />
            <Content name="React.js" />
          </Fragment>
          )
      }
    }
    
    ReactDOM.render(
        <App/>,
      document.getElementById('root')
    )
    import React, { Component, Fragment } from 'react'
    import ReactDOM from 'react-dom'
    
    class Title extends Component {
      // 使用类创建的组件,直接在这里写static方法,创建defaultProps
      static defaultProps = {
        name: 'React'
      }
      render () {
        return (
              <h1>欢迎进入{this.props.name}的世界</h1>
          )
      }
    }
    
    const Content = (props) => {
      return (
        <p>{props.name}是一个构建UI的库</p>
      )
    }
    
    // 使用箭头函数创建的组件,需要在这个组件上直接写defaultProps属性
    Content.defaultProps = {
      name: 'React.js'
    }
    
    class App extends Component {
      render () {
        return (
              <Fragment>
            {/* 由于设置了defaultProps, 不传props也能正常运行,如果传递了就会覆盖defaultProps的值 */}
              <Title />
            <Content />
          </Fragment>
          )
      }
    }
    
    ReactDOM.render(
        <App/>,
      document.getElementById('root')
    )

    props.children

    import React, { Component, Fragment } from 'react'
    import ReactDOM from 'react-dom'
    
    class Title extends Component {
      render () {
        return (
              <h1>欢迎进入{this.props.children}的世界</h1>
          )
      }
    }
    
    const Content = (props) => {
      return (
        <p>{props.children}</p>
      )
    }
    
    class App extends Component {
      render () {
        return (
              <Fragment>
              <Title>React</Title>
            <Content><i>React.js</i>是一个构建UI的库</Content>
          </Fragment>
          )
      }
    }
    
    ReactDOM.render(
        <App/>,
      document.getElementById('root')
    )
    $ npm i prop-types -S
    import React, { Component } from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends Component {
      state = {
        name: 'React',
        isLiked: false
      }
      render () {
        return (
          <div>
            <h1>欢迎来到{this.state.name}的世界</h1>
            <button>
              {
                this.state.isLiked ? '❤️取消' : '🖤收藏'
              }
            </button>
          </div>
          )
      }
    }
    ReactDOM.render(
        <App/>,
      document.getElementById('root')
    )
    import React, { Component } from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends Component {
      constructor() {
        super()
        this.state = {
          name: 'React',
          isLiked: false
        }
      }
      render () {
        return (
              <div>
            <h1>欢迎来到{this.state.name}的世界</h1>
            <button>
              {
                this.state.isLiked ? '❤️取消' : '🖤收藏'
              }
            </button>
          </div>
          )
      }
    }
    ReactDOM.render(
      <App/>,
      document.getElementById('root')
    )

    setState

    import React, { Component } from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends Component {
      constructor() {
        super()
        this.state = {
          name: 'React',
          isLiked: false
        }
      }
      handleBtnClick = () => {
        this.setState({
          isLiked: !this.state.isLiked
        })
      }
      render () {
        return (
          <div>
            <h1>欢迎来到{this.state.name}的世界</h1>
            <button onClick={this.handleBtnClick}>
              {
                this.state.isLiked ? '❤️取消' : '🖤收藏'
              }
            </button>
          </div>
          )
      }
    }
    ReactDOM.render(
        <App/>,
      document.getElementById('root')
    )
    • this.setState({
        isLiked: !this.state.isLiked
      })
    • this.setState((prevState, props) => {
        return {
          isLiked: !prevState.isLiked
        }
      })
    this.setState((prevState, props) => {
      return {
        isLiked: !prevState.isLiked
      }
    }, () => {
      console.log('回调里的',this.state.isLiked)
    })
    console.log('setState外部的',this.state.isLiked)
    {
      condition ? '❤️取消' : '🖤收藏'
    }
    // 数据
    const people = [{
      id: 1,
      name: 'Leo',
      age: 35
    }, {
      id: 2,
      name: 'XiaoMing',
      age: 16
    }]
    // 渲染列表
    {
      people.map(person => {
        return (
          <dl key={person.id}>
            <dt>{person.name}</dt>
            <dd>age: {person.age}</dd>
          </dl>
        )
      })
    }
    • dangerouslySetHTML
    content = "<p>React.js是一个构建UI的库</p>"
    import React, { Component } from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends Component {
      constructor() {
        super()
        this.state = {
          content : "<p>React.js是一个构建UI的库</p>"
        }
      }
      render () {
        return (
              <div
            // 注意这里是两个下下划线 __html
            dangerouslySetInnerHTML={{__html: this.state.content}}
          />
          )
      }
    }
    ReactDOM.render(
        <App/>,
      document.getElementById('root')
    )
    import React, { Component } from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends Component {
      constructor() {
        super()
        this.state = {
          xing: '',
          ming: ''
        }
      }
      handleInputChange = (e) => {
        this.setState({
          [e.target.name]: e.target.value
        })
      }
      render () {
        const {
          xing,
          ming
        } = this.state
        return (
              <div>
            <label>
              <span>姓:</span>
              <input
                type="text"
                name="xing"
                value={xing}
                onChange={this.handleInputChange}
              />
            </label>
            <label>
              <span>名:</span>
              <input
                type="text"
                name="ming"
                value={ming}
                onChange={this.handleInputChange}
              />
            </label>
            <p>欢迎您: {xing}{ming}</p>
          </div>
          )
      }
    }
    ReactDOM.render(
        <App/>,
      document.getElementById('root')
    )

    1. constructor 
    2. static getDerivedStateFromProps()
    3. componentWillMount() / UNSAFE_componentWillMount() 
    4. render() 
    5. componentDidMount()

    1. componentWillReceiveProps() / UNSAFE_componentWillReceiveProps() 
    2. static getDerivedStateFromProps()
    3. shouldComponentUpdate() 
    4. componentWillUpdate() / UNSAFE_componentWillUpdate() 
    5. render() 
    6. getSnapshotBeforeUpdate() 
    7. componentDidUpdate()

    1. componentWillUnmount()
    1. componentDidCatch()
    1.constructor(props)
    constructor(props) {
      super(props);
      this.state = {
        isLiked: props.isLiked
      };
    }
    2.static getDerivedStateFromProps(nextProps, prevState)
    3. componentWillMount() / UNSAFE_componentWillMount()
    4.render()
    5. componentDidMount
    6.componentWillReceiveProps()/UNSAFE_componentWillReceiveProps(nextProps)
    7.shouldComponentUpdate(nextProps, nextState)
    8.UNSAFE_componentWillUpdate(nextProps, nextState)
    9.getSnapshotBeforeUpdate()
    10.componentDidUpdate(prevProps, prevState, snapshot)
    11.componentWillUnmount()
    12.componentDidCatch(error, info)

    PureComponent

    import React, { PureComponent } from 'react'
    
    class YourComponent extends PureComponent {
      ……
    }

    ref

    import React, { Component, createRef } from 'react'
    import ReactDOM from 'react-dom'
    
    class App extends Component {
      constructor() {
        super()
        // 创建inputRef
        this.inputRef=createRef()
      }
      componentDidMount () {
        console.log(this.inputRef.current) // <input type="text">
      }
      render () {
        return (
              <div>
            {/* 关联ref和dom */}
            <input type="text" ref={this.inputRef} />
          </div>
          )
      }
    }
    ReactDOM.render(
        <App/>,
      document.getElementById('root')
    )

    React Hooks

    • State Hook
    // useState是react包提供的一个方法
    import React, { useState } from "react";
    import ReactDOM from "react-dom";
    
    const Counter = () => {
      // useState 这个方法可以为我们的函数组件拥有自己的state,它接收一个用于初始 state 的值,返回一对变量。这里我们把计数器的初始值设置为0, 方法都是以set开始
      const [count, setCount] = useState(0);
      return (
        <div>
          <p>你点击了{count}次</p>
          <button onClick={() => setCount(count + 1)}>点击</button>
        </div>
      );
    };
    
    const rootElement = document.getElementById("root");
    
    ReactDOM.render(<Counter />, rootElement);
    • Effect Hook
    // useState是react包提供的一个方法
    import React, { useState, useEffect } from "react";
    import ReactDOM from "react-dom";
    
    const Counter = () => {
      // useState 这个方法可以为我们的函数组件拥有自己的state,它接收一个用于初始 state 的值,返回一对变量。这里我们把计数器的初始值设置为0, 方法都是以set开始
      const [count, setCount] = useState(0);
      // 类似于componentDidMount或者componentDidUpdate:
      useEffect(() => {
        // 更改网页的标题,还可以做其它的监听
        document.title = `你点击了${count}次`;
      });
      return (
        <div>
          <p>你点击了{count}次</p>
          <button onClick={() => setCount(count + 1)}>点击</button>
        </div>
      );
    };
    
    const rootElement = document.getElementById("root");
    
    ReactDOM.render(<Counter />, rootElement);
    // counterContext.js
    import React, { Component, createContext } from 'react'
    
    const {
      Provider,
      Consumer: CountConsumer
    } = createContext()
    
    class CountProvider extends Component {
      constructor () {
        super()
        this.state = {
          count: 1
        }
      }
      increaseCount = () => {
        this.setState({
          count: this.state.count + 1
        })
      }
      decreaseCount = () => {
        this.setState({
          count: this.state.count - 1
        })
      }
      render() {
        return (
          <Provider value={{
            count: this.state.count,
            increaseCount: this.increaseCount,
            decreaseCount: this.decreaseCount
          }}
          >
            {this.props.children}
          </Provider>
        )
      }
    }
    
    export {
      CountProvider,
      CountConsumer
    }
    // 定义CountButton组件
    const CountButton = (props) => {
      return (
        <CountConsumer>
          // consumer的children必须是一个方法
          {
            ({ increaseCount, decreaseCount }) => {
              const { type } = props
              const handleClick = type === 'increase' ? increaseCount : decreaseCount
              const btnText = type === 'increase' ? '+' : '-'
              return <button onClick={handleClick}>{btnText}</button>
            }
          }
        </CountConsumer>
      )
    }
    // 定义count组件,用于显示数量
    const Count = (prop) => {
      return (
        <CountConsumer>
          {
            ({ count }) => {
              return <span>{count}</span>
            }
          }
        </CountConsumer>
      )
    }
    // 组合
    class App extends Component {
      render () {
        return (
              <CountProvider>
            <CountButton type='decrease' />
            <Count />
            <CountButton type='increase' />
          </CountProvider>
          )
      }
    }
    const NewComponent = higherOrderComponent(YourComponent)
    // withCopyright.js 定义一个高阶组件
    import React, { Component, Fragment } from 'react'
    
    const withCopyright = (WrappedComponent) => {
      return class NewComponent extends Component {
        render() {
          return (
            <Fragment>
              <WrappedComponent />
              <div>&copy;版权所有 千锋教育 2019 </div>
            </Fragment>
          )
        }
      }
    }
    export default withCopyright
    // 使用方式
    import withCopyright from './withCopyright'
    
    class App extends Component {
      render () {
        return (
              <div>
            <h1>Awesome React</h1>
            <p>React.js是一个构建用户界面的库</p>
          </div>
          )
      }
    }
    const CopyrightApp = withCopyright(App)

    image-20190420010944626

    image-20190420012010718

    Flux

    image-20190420012450223

    Redux

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Redux principle 01</title>
    </head>
    <body>
      <h1>redux principle</h1>
      <div class="counter">
        <span class="btn" onclick="dispatch({type: 'COUNT_DECREMENT', number: 10})">-</span>
        <span class="count" id="count"></span>
        <span class="btn" id="add" onclick="dispatch({type: 'COUNT_INCREMENT', number: 10})">+</span>
      </div>
      <script>
        // 定义一个计数器的状态
        const countState = {
          count: 10
        }
    
        // 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态
        const changeState = (action) => {
          switch(action.type) {
            // 处理减
            case 'COUNT_DECREMENT':
              countState.count -= action.number
              break;
            // 处理加        
            case 'COUNT_INCREMENT':
              countState.count += action.number
              break;
            default:
              break;
          }
        }
    
        // 定义一个方法用于渲染计数器的dom
        const renderCount = (state) => {
          const countDom = document.querySelector('#count')
          countDom.innerHTML = state.count
        }
      
        // 首次渲染数据
        renderCount(countState)
    
        // 定义一个dispatch的方法,接收到动作之后,自动调用
        const dispatch = (action) => {
          changeState(action)
          renderCount(countState)
        }
    
      </script>
    </body>
    </html>
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Redux principle 02</title>
    </head>
    <body>
      <h1>redux principle</h1>
      <div class="counter">
        <span class="btn" onclick="store.dispatch({type: 'COUNT_DECREMENT', number: 10})">-</span>
        <span class="count" id="count"></span>
        <span class="btn" id="add" onclick="store.dispatch({type: 'COUNT_INCREMENT', number: 10})">+</span>
      </div>
      <script>
        // 定义一个方法,用于集中管理state和dispatch
        const createStore = (state, changeState) => {
          // getState用于获取状态
          const getState = () => state
          
          // 定义一个监听器,用于管理一些方法
          const listeners = []
          const subscribe = (listener) => listeners.push(listener)
    
           // 定义一个dispatch方法,让每次有action传入的时候返回render执行之后的结果
          const dispatch = (action) => {
            // 调用changeState来处理数据
            changeState(state, action)
            // 让监听器里的所以方法运行
            listeners.forEach(listener => listener())
          }
          return {
            getState,
            dispatch,
            subscribe
          }
        }
        // 定义一个计数器的状态
        const countState = {
          count: 10
        }
        // 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态
        const changeState = (state, action) => {
          switch(action.type) {
            // 处理减
            case 'COUNT_DECREMENT':
              state.count -= action.number
              break;
            // 处理加        
            case 'COUNT_INCREMENT':
              state.count += action.number
              break;
            default:
              break;
          }
        }
    
        // 创建一个store
        const store = createStore(countState, changeState)
        // 定义一个方法用于渲染计数器的dom
        const renderCount = () => {
          const countDom = document.querySelector('#count')
          countDom.innerHTML = store.getState().count
        }
        // 初次渲染数据
        renderCount()
        // 监听,只要有dispatch,这个方法就会自动运行
        store.subscribe(renderCount)
      </script>
    </body>
    </html>
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Redux principle 03</title>
    </head>
    <body>
      <h1>redux principle</h1>
      <div class="counter">
        <span class="btn" onclick="store.dispatch({type: 'COUNT_DECREMENT', number: 10})">-</span>
        <span class="count" id="count"></span>
        <span class="btn" id="add" onclick="store.dispatch({type: 'COUNT_INCREMENT', number: 10})">+</span>
      </div>
      <script>
        // 定义一个方法,用于集中管理state和dispatch
        const createStore = (state, changeState) => {
          // getState用于获取状态
          const getState = () => state
          
          // 定义一个监听器,用于管理一些方法
          const listeners = []
          const subscribe = (listener) => listeners.push(listener)
    
          // 定义一个dispatch方法,让每次有action传入的时候返回render执行之后的结果
          const dispatch = (action) => {
            // 调用changeState来处理数据
            state = changeState(state, action)
            // 让监听器里的所有方法运行
            listeners.forEach(listener => listener())
          }
          return {
            getState,
            dispatch,
            subscribe
          }
        }
        // 定义一个计数器的状态
        const countState = {
          count: 10
        }
        // 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态
        const changeState = (state, action) => {
          switch(action.type) {
            // 处理减
            case 'COUNT_DECREMENT':
              return {
                ...state,
                count: state.count - action.number
              }
            // 处理加        
            case 'COUNT_INCREMENT':
              return {
                ...state,
                count: state.count + action.number
              }
            default:
              return state
          }
        }
    
        // 创建一个store
        const store = createStore(countState, changeState)
        // 定义一个方法用于渲染计数器的dom
        const renderCount = () => {
          const countDom = document.querySelector('#count')
          countDom.innerHTML = store.getState().count
        }
        // 初次渲染数据
        renderCount()
        // 监听,只要有dispatch,这个方法就会自动运行
        store.subscribe(renderCount)
      </script>
    </body>
    </html>
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Redux principle 04</title>
    </head>
    <body>
      <h1>redux principle</h1>
      <div class="counter">
        <span class="btn" onclick="store.dispatch({type: 'COUNT_DECREMENT', number: 10})">-</span>
        <span class="count" id="count"></span>
        <span class="btn" id="add" onclick="store.dispatch({type: 'COUNT_INCREMENT', number: 10})">+</span>
      </div>
      <script>
        // 定义一个方法,用于集中管理state和dispatch, changeState改名了,专业的叫法是reducer
        const createStore = (reducer) => {
          // 定义一个初始的state
          let state = null
          // getState用于获取状态
          const getState = () => state
          
          // 定义一个监听器,用于管理一些方法
          const listeners = []
          const subscribe = (listener) => listeners.push(listener)
    
          // 定义一个dispatch方法,让每次有action传入的时候返回reducer执行之后的结果
          const dispatch = (action) => {
            // 调用reducer来处理数据
            state = reducer(state, action)
            // 让监听器里的所有方法运行
            listeners.forEach(listener => listener())
          }
          //  初始化state
          dispatch({})
          return {
            getState,
            dispatch,
            subscribe
          }
        }
        // 定义一个计数器的状态
        const countState = {
          count: 10
        }
        // 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态
        const changeState = (state, action) => {
          // 如果state是null, 就返回countState
          if (!state) return countState
          switch(action.type) {
            // 处理减
            case 'COUNT_DECREMENT':
              return {
                ...state,
                count: state.count - action.number
              }
            // 处理加        
            case 'COUNT_INCREMENT':
              return {
                ...state,
                count: state.count + action.number
              }
            default:
              return state
          }
        }
    
        // 创建一个store
        const store = createStore(changeState)
        // 定义一个方法用于渲染计数器的dom
        const renderCount = () => {
          const countDom = document.querySelector('#count')
          countDom.innerHTML = store.getState().count
        }
        // 初次渲染数据
        renderCount()
        // 监听,只要有dispatch,renderCount就会自动运行
        store.subscribe(renderCount)
      </script>
    </body>
    </html>

    image-20190420013410981

    // State 是一个对象
    function reducer(state = defaultState, action) {
      return Object.assign({}, state, { thingToChange });
      // 或者
      return { ...state, ...newState };
    }
    
    // State 是一个数组
    function reducer(state = defaultState, action) {
      return [...state, newItem];
    }
    • Redux-saga
    • Redux-effects
    • Redux-side-effects
    • Redux-loop
    • Redux-observable
    • Redux-promise
    • Redux-promises
    • Redux-simple-promise
    • Redux-promise-middleware
    props
    1. Provider
    2. connect

      connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)(component)

    React Router

    Description
    react-router
    react-router-dom
    react-router-native
    react-router-config

    Immutable.js

    const state = {
      str: '千锋教育',
      obj: {
        y: 1
      },
      arr: [1, 2, 3]
    }
    const newState = state
    
    console.log(newState === state) // true
    const state = {
      str: '千锋教育',
      obj: {
        y: 1
      },
      arr: [1, 2, 3]
    }
    const newState = state
    
    newState.str = '千锋教育H5学院'
    
    console.log(state.str, newState.str)
    const state = {
      str: '千锋教育',
      obj: {
        y: 1
      },
      arr: [1, 2, 3]
    }
    const newState = Object.assign({}, state)
    
    newState.str = '千锋教育H5学院'
    
    console.log(state.str, newState.str)
    const state = {
      str: '千锋教育',
      obj: {
        y: 1
      },
      arr: [1, 2, 3]
    }
    const newState = Object.assign({}, state)
    
    newState.obj.y = 2
    newState.arr.push(4)
    
    console.log(state, newState)
    import { cloneDeep } from 'lodash'
    
    const state = {
      str: '千锋教育',
      obj: {
        y: 1
      },
      arr: [1, 2, 3]
    }
    const newState = cloneDeep(state)
    
    newState.obj.y = 2
    newState.arr.push(4)
    
    console.log(state, newState)

    react

    Map

    import { Map } from 'immutable'
    
    const map = Map({
      a: 1,
      b: 2,
      c: 3
    })
    
    const newMap = map.set('b', 20) // immutable数据每次都是生成新的再重新调用set进行修改,所以需要 重新赋值给一个新的变量
    
    console.log(map, newMap) // immutable.Map不是原生的对象
    console.log(map.b, newMap.b) // immutable.Map不是原生的对象, 所以是undefined
    console.log(map.get('b'), newMap.get('b')) // 要取值,需要调用get(key)方法,可以看到,两个值不一样
    
    const obj = {
      a: 1,
      b: 2,
      c: 3
    }
    
    console.log(Map.isMap(map), Map.isMap(obj)) // true false, 使用Map.isMap来判断是否是一个immutable.Map类型

    List

    import { List } from 'immutable'
    
    const list = List([1, 2, 3, 4])
    const newList = list.push(5)
    console.log(list, newList)
    console.log(list[4], newList[4]) // undefined undefined
    console.log(list.get(4), newList.get(4)) // undefined 5
    console.log(list.size, newList.size) // 4 5
    
    const arr = [1, 2, 3, 4]
    
    console.log(List.isList(list), List.isList(arr)) // true false

    equals & is

    import { Map, is } from 'immutable'
    
    const map = Map({
      a: 1,
      b: 2,
      c: 3
    })
    
    const anotherMap = Map({
      a: 1,
      b: 2,
      c: 3
    })
    
    console.log(map == anotherMap) // false
    console.log(map === anotherMap) // false
    console.log(map.equals(anotherMap)) // 使用equals进行比较 true
    console.log(is(map, anotherMap)) // 使用is进行比较 true
    import { List } from 'immutable'
    
    const list = List([1, 2, 3, 4])
    const list1 = list.push(5)
    const list2 = list1.unshift(0)
    const list3 = list.concat(list1, list2)
    const list4 = list.map(v => v * 2)
    
    console.log(list.size, list1.size, list2.size, list3.size, list4.toJS()) // 4 5 6 15, [2, 4, 6, 8]
    import { Map } from 'immutable'
    
    const alpha = Map({
      a: 1,
      b: 2,
      c: 3
    })
    const objKeys = alpha.map((v, k) => k)
    console.log(objKeys.join()) // a, b, c
    
    
    const map1 = Map({
      a: 1,
      b: 2
    })
    const map2 = Map({
      c: 3,
      d: 4
    })
    const obj = {
      d: 400,
      e: 50
    }
    
    const mergedMap = map1.merge(map2, obj)
    
    console.log(mergedMap.toObject())
    console.log(mergedMap.toJS())
    const { fromJS } = require('immutable');
    const nested = fromJS({ a: { b: { c: [ 3, 4, 5 ] } } });
    
    const nested2 = nested.mergeDeep({ a: { b: { d: 6 } } });
    // Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 6 } } }
    
    console.log(nested2.getIn([ 'a', 'b', 'd' ])); // 6
    
    const nested3 = nested2.updateIn([ 'a', 'b', 'd' ], value => value + 1);
    console.log(nested3);
    // Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 7 } } }
    
    const nested4 = nested3.updateIn([ 'a', 'b', 'c' ], list => list.push(6));
    // Map { a: Map { b: Map { c: List [ 3, 4, 5, 6 ], d: 7 } } }
    // 使用redux-immutable提供的combineReducers方法替换redux里的combineReducers
    import {combineReducers} from 'redux-immutable'
    import reducerOne from './reducerOne'
    import reducerTwo from './reducerTwo'
     
    const rootReducer = combineReducers({
        reducerOne,
        reducerTwo
    });
     
    export default rootReducer;
    import { Map } from 'immutable'
    
    import ActionTypes from '../actions'
    
    const initialState = Map({
      count: 0
    })
    
    export default (state = initialState, action) => {
      switch (action.type) {
        case ActionTypes.INCREAMENT:
          return state.set('count', state.get('count') + 1) // 使用set或setIn来更改值, get或者getIn来取值
        case ActionTypes.DECREAMENT:
          return state.set('count', state.get('count') - 1)
        default:
          return state
      }
    }
    const mapStateToProps = state => ({
      count: state.getIn(['counter', 'count']) // 永远不要在mapStateToProps里使用`toJS`方法,因为它永远返回一个新的对象
    })

    Mobx

    MobX unidirectional flow


    wscats
    7.1k 声望13k 粉丝

    分享和总结不易,求关注一下⭐️