/ react

react

启动

create-react-app 的配置默认是封装好的,如果需要定制配置,可以执行 npm eject 来弹出默认配置,这样,你就可以自定义了。

React 简介

React 对 seo 不友好,除非你的网站不在乎百度那点流量(比如淘宝、途牛之类的),否则不要使用 react 或 vue 之类的前端框架。

React doesn't support IE8 anyway

React 的特点

  • 组件化,js 逻辑和 html 都写在 jsx 文件内
  • 单向数据流,数据一旦更新,就直接渲染整个app
  • 虚拟 DOM 树,即时渲染整个 app 也十分特别地快快快
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';

定义组件的三种方法

// 1. es5 写法
// 是 Object,有 this 作用域
const App = React.createClass({});

// 2. es6 写法
// 是 Object,有 this 作用域
class App extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (<div>App</div>);
  }
}

// 3. stateless 的写法(我们推荐的写法)
// 这是函数,不是 Object,没有 this 作用域,是 pure function。
const App = (props) => {
  function handleClick() {
    props.dispatch({ type: 'app/create' });
  }
  return <div onClick={handleClick}>${props.name}</div>
}

实际开发中在 atom 安装插件 react-es6-snippets:

  • 有状态组件使用 rcc + rbm
  • 无状态组件使用 rfunc

React 组件内的回调函数默认参数

例如:

function onBlur( a,b,c ){
  //第一个参数是 Proxy
  //第二个参数是 Event
  //第三个参数才是自定义的参数
  //按顺序,不按名称
}

forms

  • controlled components: writing an event handler for every state update
  • uncontrolled components: use a ref to get form values from the DOM

In most cases, we recommend using controlled components to implement forms. In a controlled component, form data is handled by a React component. The alternative is uncontrolled components, where form data is handled by the DOM itself.

To write an uncontrolled component, instead of writing an event handler for every state update, you can use a ref to get form values from the DOM.

常用组件列表

Introducing JSX

const element = <h1>Hello, world!</h1>;

element 的值是 html 元素么?

不是,它是 jsx,是 JavaScript 的扩展语法。

Unlike browser DOM elements, React elements are plain objects, and are cheap to create.

Rendering an React Element into the browser DOM。

React elements are immutable(不可改变的).如果想要改变,就需要重新创建。

React Only Updates What's Necessary.只改变改变的。

JSX Prevents Injection Attacks

It is safe to embed user input in JSX.

By default, React DOM escapes any values embedded in JSX before rendering them.

Components and Props

Components 类似于 JavaScript 的 functions. Components 接受输入 (called "props") 并 返回 React elements.

The simplest way to define a component is to write a JavaScript function:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

Props are Read-Only

You must never modify its own props.

Consider this sum function:

 function sum(a, b) {
  return a + b;
}

Such functions are called "pure" because they do not attempt to change their inputs, and always return the same result for the same inputs.

All React components must act like pure functions with respect to their props.

Of course, application UIs are dynamic and change over time. In the next section, we will introduce a new concept of "state". State allows React components to change their output over time in response to user actions, network responses, and anything else, without violating this rule.

State and Lifecycle Methods

State is similar to props, but it is private and fully controlled by the component.

Using State Correctly

Do Not Modify State Directly.

Instead, use setState()

State Updates May Be Asynchronous

Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

State Updates are Merged

The merging is shallow, so this.setState({comments}) leaves this.state.posts intact(完整), but completely replaces this.state.comments.

单向数据流

A component may choose to pass its state down as props to its child components.

This is commonly called a "top-down" or "unidirectional"(单向) data flow.

Any state is always owned by some specific component, and any data or UI derived from that state can only affect components "below" them in the tree.

If you imagine a component tree as a waterfall of props, each component's state is like an additional water source that joins it at an arbitrary point but also flows down.

Handling Events

Handling events with React elements is very similar to handling events on DOM elements. There are some syntactic differences:

  • React events are named using camelCase, rather than lowercase.
  • With JSX you pass a function as the event handler, rather than a string.

React 与 AJAX

React只负责处理View这一层,它本身不涉及网络请求/AJAX,所以这里我们需求考虑两个问题:

  • 第一,用什么技术从服务端获取数据;
  • 第二,获取到的数据应该放在react组件的什么位置。

For every presentational component that needs data from the server, create a container component that sends AJAX requests to get that data, and provides it to the child component via props.

constructor(props) {
  super(props);
  this.state = {
    posts: [],
    comments: []
  };
}

componentDidMount() {
  fetchPosts().then(response => {
   this.setState({
     posts: response.posts
   });
  });

  fetchComments().then(response => {
   this.setState({
     comments: response.comments
   });
  });
}

如果只是为了使用jQuery的Ajax方法就引入整个jQuery库,既是一种浪费又加大了整个应用的体积。那我们还有什么其他的选择吗?事实上是有很多的:fetch()、fetch polyfill、axios...其中最需要我们关注的是window.fetch(),它是一个简洁、标准化的javascript的Ajax API。在Chrome和Firefox中已经可以使用,如果需要兼容其他浏览器,可以使用fetch polyfill。

表单数据

value 和 onChange 是必不可少的。或者在 submit 中使用 refs 获取表单中各个项的值。

问题

react 如何操作真是 DOM 节点?

  1. 添加 ref 属性 name:<input type="text" ref="name" />
  2. 获取真实 DOM 节点:this.refs.name
import ReactDOM from 'react-dom';

// Find the text field via the React ref
const text = ReactDOM.findDOMNode(this.refs.name).value.trim();
// Clear form
ReactDOM.findDOMNode(this.refs.name).value = '';

// 但是一般用法和文档有区别,并不使用 ReactDOM.findDOMNode()
const myText = this.refs.name.value;

渲染页面

浏览器渲染

import {render} from 'react-dom';

render 方法接受 2 个参数 render([react element], [DOM node])

服务器渲染

import {renderToString} from 'react-dom/server'
import {renderToStaticMarkup} from 'react-dom/server'

而 renderToString 与 renderToStaticMarkup 只接受一个参数
renderToString(react element)
renderToStaticMarkup(react element)

概述

React 的每个组件就是一个函数

  • prop 是入参,接收父组件传入的数据。
  • state 是函数内部的变量,state 存储用户界面的临时数据
  • 输出是 html、css、javascrit 的混合内容

context

context

React 的四个概念

  • 属性
  • 状态
  • 事件
  • 生命周期

react 组件生命周期

实例化

首次实例化

  • getDefaultProps , 设置默认属性
  • getInitialState ,可以访问组件的 props
  • componentWillMount ,可以修改组件的 state
  • render
  • componentDidMount ,可以通过this.getDOMNode()访问到真实的DOM元素,也可请求Ajax

实例化完成后的更新

  • getInitialState
  • componentWillMount
  • render
  • componentDidMount

存在期(组件已经存在时的状态改变)

  • componentWillReceiveProps ,组件接收到新的props时会被执行,此时可以更改组件的state
  • shouldComponentUpdate
  • componentWillUpdate ,接收到新的propsstate后执行;不允许更新 state(死循环)
  • render
  • componentDidUpdate ,此时可以访问到新的DOM元素

销毁期

  • componentWillUnmount ,可以进行清理工作,例如在componentDidMount中创建的定时器或事件监听器。

props && state

  • 使用 props 在整个组件树种传递数据和配置
  • 避免在组件内部修改 this.props 或调用 this.setProps,请把 props 看作是只读的
  • 使用 props 来做事件处理器,与子组件通信
  • 使用 state 存储简单的视图状态,例如下拉框是否可见这样的状态
  • 使用 this.setState 来设置状态,而不要使用 this.state 直接修改状态

组件数据源

通常是通过 Ajax 请求从服务器获取,可以使用 componentDidMount 方法设置 Ajax 请求,
等到请求成功,再用 this.setState 方法重新渲染 UI

componentDidMount 使用示例

componentDidMount: function() {
  $.get(this.props.source, function(result) {
    var lastGist = result[0];
    if (this.isMounted()) {
      this.setState({
        username: lastGist.owner.login,
        lastGistUrl: lastGist.html_url
      });
    }
  }.bind(this));
}