React学习(二)

学习过程当中本身弄得小项目javascript

在线预览html

整理过程当中遇到了好用的前端js库:前端

immutable(持久化数据结构、结构共享):vue

NPM 地址java

Immutable 详解及 React 中实践 · Issue #3 · camsong/blogreact

classnames(支持对className的逻辑操做):git

NPM地址github

 

1.React 安装ajax

使用Facebook提供的 create-react-app 脚手架工具构建react项目npm

create-react-app 是来自于 Facebook,经过该命令咱们无需配置就能快速构建 React 开发环境。

create-react-app 自动建立的项目是基于 Webpack + ES6 。

配置 npm 的registry 下载package更快

$ npm config set registry https://registry.npm.taobao.org

 配置后可经过下面方式来验证是否成功

$ npm config get registry

 create-react-app构建启动项目

$ cnpm install -g create-react-app
$ create-react-app my-app
$ cd my-app/
$ npm start

附:create-react-app github地址

2.JSX语法    

一种 JavaScript 的语法扩展。 推荐在 React 中使用 JSX 来描述用户界面

能够任意地在 JSX 当中使用 JavaScript 表达式,在 JSX 当中的表达式要包含在大括号里。

React DOM 在渲染以前默认会 过滤 全部传入的值。它能够确保你的应用不会被注入攻击。全部的内容在渲染以前都被转换成了字符串。这样能够有效地防止 XSS(跨站脚本) 攻击。

若是你已经有了个 props 对象,而且想在 JSX 中传递它,你可使用 ... 做为扩展操做符(Spread syntax)来传递整个属性对象。下面两个组件是等效的:

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'};
  return <Greeting {...props} />;
}

 

警告:
    由于 JSX 的特性更接近 JavaScript 而不是 HTML , 因此 React DOM 使用 camelCase 小驼峰命名 来定义属性的名称,而不是使用 HTML 的属性名称。
    例如,class 变成了 className,而 tabindex 则对应着 tabIndex。
3.state & props & render

state:

构造函数是惟一可以初始化 this.state 的地方

修改state经过this.setState({comment: 'Hello'})

状态更新多是异步的,要是修改state的变量依赖自己,须要经过setState的callback解决:

  incrementCount() {
    const me = this;
    me.setState((prevState) => {
      return { count: prevState.count + 1 }
    });
    //ERROR
    // me.setState({
    //   count : me.state.count + 1
    // });
  }

  incrementTwo() {
    const me = this;
    me.incrementCount();
    me.incrementCount();
  }

 props:

 不管是使用函数或是类来声明一个组件,它决不能修改它本身的props

{props.children}获取包含的子组件列表

render:

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

组件的返回值只能有一个根元素。这也是咱们要用一个<div>来包裹全部<h1/><h2/>元素的缘由。

布尔值、Null 和 Undefined 被忽略渲染时会被忽略

<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>

4.keys

React提供key属性,来提升元素变动以后从新渲染的效率

Keys能够在DOM中的某些元素被增长或删除的时候帮助React识别哪些元素发生了变化。所以你应当给数组中的每个元素赋予一个肯定的标识。

一个元素的key最好是这个元素在列表中拥有的一个独一无二的字符串。一般,咱们使用来自数据的id做为元素的key

若是列表能够从新排序,咱们不建议使用索引来进行排序,由于这会致使渲染变得很慢

不能经过props.key获取key的值。

举个例子:

<li>a</li>
<li>b</li>

 改变后:

<li>c</li>
<li>a</li>
<li>b</li>

肉眼很容易看出来在第一行加了一个 c ,但React并不知道,而是一行一行的比较(a 与 c),因此须要在每一个 li 都一个 key ,利于React辨别,从而提供效率


5.form 表单使用

html:
<textarea>
  Hello there, this is some text in a text area
</textarea>

jsx:
<textarea value={this.state.value} onChange={this.handleChange} />


html:
<select>
  <option value="grapefruit">Grapefruit</option>
  <option value="lime">Lime</option>
  <option selected value="coconut">Coconut</option>
  <option value="mango">Mango</option>
</select>

jsx:
<select value={this.state.value} onChange={this.handleChange}> 
	<option value="grapefruit">Grapefruit</option> 
	<option value="lime">Lime</option> 
	<option value="coconut">Coconut</option> 
	<option value="mango">Mango</option> 
</select>

6.propTypes 属性约束 & 设置默认属性值

属性约束:

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};

具体有哪些验证器:参考官网

属性默认值:

能够经过配置 defaultProps 为 props定义默认值:

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

// 为属性指定默认值:
Greeting.defaultProps = {
  name: 'Stranger'
};

// 渲染 "Hello, Stranger":
ReactDOM.render(
  <Greeting />,
  document.getElementById('example')
);
提示:
    类型检查发生在 defaultProps 赋值以后,因此类型检查也会应用在 defaultProps 上面。

7.refs

Refs 提供了一种访问在 render 方法中建立的 DOM 节点或 React 元素的方式

什么时候使用 Refs
下面是几个适合使用 refs 的状况:
    处理焦点、文本选择或媒体控制。
    触发强制动画。
    集成第三方 DOM 库

若是能够经过声明式实现,则尽可能避免使用 refs。
例如,不要在 Dialog 组件上直接暴露 open() 和 close() 方法,最好传递 isOpen 属性。

经典案例:

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }

  focus() {
    // 直接使用原生 API 使 text 输入框得到焦点
    this.textInput.focus();
  }

  render() {
    // 使用 `ref` 的回调将 text 输入框的 DOM 节点存储到 React
    // 实例上(好比 this.textInput)
    return (
      <div>
        <input
          type="text"
          ref={(input) => { this.textInput = input; }} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focus}
        />
      </div>
    );
  }
}

React 组件在加载时将 DOM 元素传入 ref 的回调函数,在卸载时则会传入 nullref 回调会在componentDidMountcomponentDidUpdate 这些生命周期回调以前执行。

注意:
若是 ref 回调之内联函数的方式定义,在更新期间它会被调用两次,第一次参数是 null ,以后参数是 DOM 元素。这是由于在每次渲染中都会建立一个新的函数实例。
所以,React 须要清理旧的 ref 而且设置新的。经过将 ref 的回调函数定义成类的绑定函数的方式能够避免上述问题,可是大多数状况下可有可无。

8.Fragments

React 中一个常见模式是为一个组件返回多个元素。Fragments 可让你聚合一个子元素列表,而且不在DOM中增长额外节点

class Columns extends React.Component {
  render() {
    return (
      <React.Fragment>
        <td>Hello</td>
        <td>World</td>
      </React.Fragment>
    );
  }
}

9.Error Boundaries错误边界

部分 UI 的异常不该该破坏了整个应用。为了解决 React 用户的这一问题,React 16 引入了一种称为 “错误边界” 的新概念。

若是一个类组件定义了一个名为 componentDidCatch(error, info): 的新方法,则其成为一个错误边界

错误边界没法捕获以下错误:
    1.事件处理 (了解更多)
    2.异步代码 (例如 setTimeout 或 requestAnimationFrame 回调函数)
    3.服务端渲染
    4.错误边界自身抛出来的错误 (而不是其子组件)        

经典案例

10.组件生命周期

图解

组件的生命周期可分红三个状态:
    Mounting:已插入真实 DOM
    Updating:正在被从新渲染
    Unmounting:已移出真实 DOM

生命周期的方法有:

componentWillMount 在渲染前调用,在客户端也在服务端
componentDidMount 在第一次渲染后调用,只在客户端。以后组件已经生成了对应的DOM结构,能够经过this.getDOMNode()来进行访问。 若是你想和其余JavaScript框架一块儿使用,能够在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操做(防止异部操做阻塞UI)
componentWillReceiveProps 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用
shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
能够在你确认不须要更新组件时使用
componentWillUpdate 在组件接收到新的props或者state但尚未render时被调用。在初始化时不会被调用
componentDidUpdate 在组件完成更新后当即调用。在初始化时不会被调用
componentWillUnmount 在组件从 DOM 中移除的时候马上被调用

forceUpdate:
component.forceUpdate(callback)
默认状况,当你的组件或状态发生改变,你的组件将会重渲。若你的render()方法依赖其余数据,你能够经过调用forceUpdate()来告诉React组件须要重渲。
调用forceUpdate()将会致使组件的 render()方法被调用,并忽略shouldComponentUpdate()。这将会触发每个子组件的生命周期方法,涵盖,每一个子组件的shouldComponentUpdate() 方法。若当标签改变,React仅会更新DOM。
一般你应该尝试避免全部forceUpdate() 的用法并仅在render()函数里从this.props和this.state读取数据。


11.ajax使用

React 组件的数据能够经过 componentDidMount 方法中的 Ajax 来获取,当从服务端获取数据时能够将数据存储在 state 中,再用 this.setState 方法从新渲染 UI。

当使用异步加载数据时,在组件卸载前使用 componentWillUnmount 来取消未完成的请求。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      items: []
    };
  }

  componentDidMount() {
    fetch("https://api.example.com/items")
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            items: result.items
          });
        },
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
  }

  render() {
    const { error, isLoaded, items } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <ul>
          {items.map(item => (
            <li key={item.name}>
              {item.name} {item.price}
            </li>
          ))}
        </ul>
      );
    }
  }
}

12.React UI库推荐

Element:一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库

https://eleme.github.io/element-react/#/zh-CN/quick-start 

 

Ant Desgin:一个服务于企业级产品的设计体系,基于『肯定』和『天然』的设计价值观和模块化的解决方案,让设计者专一于更好的用户体验

https://ant.design/docs/react/introduce-cn 

 

UXCore:为企业后台而生

http://uxco.re/


13.react router  & react redux介绍

react router4.x :

官方文档:https://reacttraining.com/react-router/

官方文档提供了不少 examples ,文档也比较清楚,能够直接查看文档学习。

react redux:

官方文档:http://www.redux.org.cn/

核心思想:

  1.单一数据源:

    整个项目只有一个state树。

  2.state只读:

    只能经过触发action 修改state。

  3.使用纯函数执行修改:

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

重要概念:

  Action:

    描述要干什么事情。准备须要的一些数据(一个简单对象)

 {
  type: ADD_TODO, text: 'Build my first Redux app' }

   Reducer:

    到底要怎么干。处理state,并返回新的state

function todoApp(state = initialState, action) {
	  switch (action.type) {
		case ADD_TODO:
		  return Object.assign({}, state, {
			todos: [
			  ...state.todos,
			  {
				text: action.text,
				completed: false
			  }
			]
		  })
		default:
		  return state
	  }
}

   Store:

  找到人正式干活。派发事件

store.dispatch(addTodo('Learn about actions'))

  展现组件:

    仅仅基于React,描述怎么展现,数据都从props里面获取

  容器组件:

    描述如何获取数据,状态更新,逻辑处理。基于react-redux

重要API:

 createStore:http://www.redux.org.cn/docs/api/createStore.html

 combineReducers:http://www.redux.org.cn/docs/api/combineReducers.html

   applyMiddleware:http://www.redux.org.cn/docs/api/applyMiddleware.html

react-redux文档 :http://www.redux.org.cn/docs/react-redux/api.html

综合案例参见官网TODOS:https://github.com/reduxjs/redux/tree/master/examples/todos

效果图:

 

14.拓展

react动画:

https://reactcommunity.org/react-transition-group/

react单元测试

React测试必须使用官方的测试工具库,可是它用起来不够方便,因此有人作了封装,推出了一些第三方库,其中Airbnb公司的Enzyme最容易上手。

官方也推荐使用  Enzyme 它在相同的功能上提供了一个更棒的高级 API。

Enzyme是官方测试工具库的封装,它模拟了jQuery的API,很是直观,易于使用和学习。

它提供三种测试方法:
        shallow
        render
        mount

 

 

推荐阅读:http://www.aliued.com/?p=4095

相关文章
相关标签/搜索