React入门教程

  1. React入口,将使用react定制的组件<app/>渲染到指定的element。

    ReactDOM.render(<App />, document.getElementById('root'));
    
  2. 可以看作是一个自定义的HTML标签(如同<button/>),在react里我们称之为组件,开发react实际上是开发组件的过程。

  3. 组件的写法

    组件有两种写法,函数式写法和class式写法。

    先看函数式写法,和普通的JavaScript函数写法唯一的区别是返回值是一些标签组合构成的组件,其中<>内的内容按照HTML规则解析,{}内的内容按照JavaScript的规则进行解析。

    import React from "react";
    export function ShowMessage() {
      let message = "this is for show some message."
      return <p>{message}</p>
    }
    

    以上组件不带有参数,下面看带参数组件的写法:

    import React from "react";
    
    export function ShowMessageWithProps(props) {
      const showMessage = () => {
        alert('Followed ' + props.user);
      };
    
      const handleClick = () => {
        setTimeout(showMessage, 3000);
      };
    
      return (
          <button onClick={handleClick}>Follow</button>
      );
    }
    

    可以看出只需要在函数参数中申明props即可在函数内部任意使用props内部携带的参数。使用方法与普通的标签使用方法相同:

    <ShowMessageWithProps user="xiaojun"/>	
    

     

    class式写法如下,继承React.Component后重载render函数。

    class Demo extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                text: props.initialValue || 'placeholder'
            };
            // 手动绑定this
            this.handleChange = this.handleChange.bind(this);
        }
        handleChange(event) {
            this.setState({
                text: event.target.value
            });
        }
        render() {
            return (
                <div>
                    <input value={this.state.text} onChange={this.handleChange}/>
                </div>
            );
        }
    }
    Demo.propTypes = {
        initialValue: React.PropTypes.string
    }
    

    纯函数组件的特点:

    • 组件不会被实例化,整体渲染性能得到提升
    • 组件不能访问this对象
    • 组件无法访问生命周期的方法
    • 无状态组件只能访问输入的props,无副作用

    纯函数组件被鼓励在大型项目中尽可能以简单的写法来分割原本庞大的组件,未来React也会这种面向无状态组件在譬如无意义的检查和内存分配领域进行一系列优化,所以只要有可能,尽量使用无状态组件

    关于函数组件和类组件的差别详细可参考React函数组件和类组件的差异

  4. 组件参数的类型检查与默认参数

    从实例代码中可以看出,只需要设置类组件中的propTypesdefaultProps对象即可实现类型检查和设置默认参数。

    import React from "react";
    import PropTypes from "prop-types";
    
    export class Dashboard extends React.Component{
        render() {
            return <p>{this.props.text}</p>
        }
    }
    
    Dashboard.propTypes= {
      text: PropTypes.string
    };
    
    Dashboard.defaultProps = {
      name: 'Stranger'
    };
    
  5. 类组件的生命周期

    组件的生命周期分为三个状态:

    • Mounting:已插入真实 DOM
    • Updating:正在被重新渲染
    • Unmounting:已移出真实 DOM

    React 根据生命周期的不同阶段提供了以下钩子函数,若需要在指定阶段执行一些定制化操作,在类组件中重载相应阶段的钩子函数即可。

    • componentWillMount()
    • componentDidMount()
    • componentWillUpdate(object nextProps, object nextState)
    • componentDidUpdate(object prevProps, object prevState)
    • componentWillUnmount()
    • componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
    • shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
  6. Hook

    回顾3中的函数式组件的写法,我们可以看到函数式组件是无状态的(依靠外部传值给组件,组件可以看成是该值的一种函数映射,无状态我理解是外部传的值与组件的状态是一一对应的关系),若我们想赋予函数组件状态该怎么办?官方为我们提供了hook特性,它可以让我们在不编写类组件的情况下使用state以及其它的React特性。

    import React, {useState} from "react";
    
    export function Counter() {
      let [count, setCount] = useState(0)
      return <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>
          Click me
        </button>
      </div>
    }
    

    useState传入state的初始值,返回一个数组。该数组的第一项是state XXX的当前值,第二项为设置该state的函数,约定为setXXX

    其它hook可参考阮一峰大神的教程: React Hooks 入门教程

    • useContext() 共享状态钩子
    • useReducer() Action钩子
    • useEffect() 副作用钩子
    • useRef()给标签创建引用
  7. Redux

    前端应用的本质是一个用来展示数据的函数,我提供什么样的store(数据),你给我展示什么样的view。点击view上的按钮能够通过dispatcher触发actionreducer根据action来计算新的store,最后更新view

Redux三大原则

  • 单一数据源

    整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。

    这让同构应用开发变得非常容易。来自服务端的 state 可以在无需编写更多代码的情况下被序列化并注入到客户端中。由于是单一的 state tree ,调试也变得非常容易。在开发中,你可以把应用的 state 保存在本地,从而加快开发速度。此外,受益于单一的 state tree ,以前难以实现的如“撤销/重做”这类功能也变得轻而易举。

  • State只读

    唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。

    这样确保了视图和网络请求都不能直接修改 state,相反它们只能表达想要修改的意图。因为所有的修改都被集中化处理,且严格按照一个接一个的顺序执行,因此不用担心竞态条件(race condition)的出现。 Action 就是普通对象而已,因此它们可以被日志打印、序列化、储存、后期调试或测试时回放出来。

  • 使用纯函数来执行修改

    为了描述 action 如何改变 state tree ,你需要编写 reducers

    Reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state。刚开始你可以只有一个 reducer,随着应用变大,你可以把它拆成多个小的 reducers,分别独立地操作 state tree 的不同部分,因为 reducer 只是函数,你可以控制它们被调用的顺序,传入附加数据,甚至编写可复用的 reducer 来处理一些通用任务,如分页器。

学习文档:Redux 中文文档

小问题:表单输入信息,按钮提交信息并显示在文本框,如何使用函数式组件的思想来设计组件?

 

表单信息和提交按钮定义到同一个组件中,点击按钮将调用组件中button的onClick函数。函数式组件是无状态的,只能够接受数据,那么如何将数据存储到中心的store呢?

探索方案一,如下代码所示直接在onClick中发送action。但是很容易看出这种方式并不是很好的设计,组件与action以及发送的数据有着强力的耦合,函数不够纯,复用性不好。

import React, {useRef} from "react";
import store from "../store";
import {CLICK} from "../actions/actions";

const InputBox = () => {
  const thisInput = useRef();
  const getInput = () => thisInput.current.value;
  const handleInput = () => store.dispatch({type: CLICK, text: getInput()})

  return <div>
    <input ref={thisInput}/>
    <button onClick={handleInput}>Click</button>
  </div>
}

export default InputBox

探索方案二,如下代码所示,在props属性中传入函数,在onClick中调用该函数,并将需要保存的值作为参数传入该函数。这样设计的好处是更加纯粹,可复用性好。

import React, {useRef} from "react"

const InputBox = (props) => {
  const thisInput = useRef();
  const getInput = () => thisInput.current.value;
  const handleInput = () => props.handleClick(getInput())

  return <div>
    <input ref={thisInput}/>
    <button onClick={handleInput}>Click</button>
  </div>
}

export default InputBox

在父组件中调用,发送消息的逻辑放在父组件中:

const handleClick = (text) => {
  store.dispatch({type: CLICK, text: text})
}

const render = () => {
  let text = store.getState().toString();
  ReactDOM.render(
    <div>
      <InputBox handleClick={handleClick}/>
      <ShowMessage text={text}/>
    </div>,
    document.getElementById('root'));
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值