react - 整理

官方

教程

Atom - React插件

Todo

组件

案例

赞文

浅薄认识

  • 数据流通过函数式编程
  • 组件化写法统一,便于二次开发和扩展

概述要点

  • ReactDOM.render页面一般只存在一处?
  • jsx需要有关闭<Welcome name="Sara" />
  • jsx包含子元素,外层引用需要添加括号(),相当于React.createElement缩写
  • ReactDOM.render中第一个参数为jsx,注意要点同第二点,需要关闭
  • react组件必须大写,原因是默认小写识别为html标签
  • event事件语法:1-using camelCase, rather than lowercase;2-With JSX you pass a function as the event handler, rather than a string.官方提供了其他两个解决方案,总体说是:js的锅我react不背
  • 函数式组件写法demo
  • keys都需要设定,否则会有warn提示,同时不建议使用index序列作为key,原因是:

    We don't recommend using indexes for keys if the items can reorder, as that would be slow. You may read an in-depth explanation about why keys are necessary if you're interested.

  • keys的设定位置:哪里遍历哪里设定。介绍地址

    For example, if you extract a ListItem component, you should keep the key on the elements in the array rather than on the root

  • element in the ListItem itself.

  • props可以设定默认值:如一个Greeting组件,可通过Greeting.defaultProps = { name: 'Stranger'};,见react官方进阶教程

  • JSX的注释{/* test */}

  • JSX:小写的字符串是 HTML 标签,大写开头的变量是 React 组件

  • html直接插入字符<div dangerouslySetInnerHTML={{__html: 'cc &copy; 2015'}} />

  • ref目前测试只能在class函数中创建,在无状态的函数中无法创建,报错信息不明确

JSX语法

If a tag is empty, you may close it immediately with />, like XML:

const element = <img src={user.avatarUrl} />;

JSX tags may contain children:

const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

注意点:驼峰

Since JSX is closer to JavaScript than HTML, React DOM uses camelCase property naming convention instead of HTML attribute names.
For example, class becomes className in JSX, and tabindex becomes tabIndex.

以下两种语法相同

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

# or
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

// Note: this structure is simplified
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world'
  }
};

测试jsx语法的html内容部分不能加引号

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

# 以下为正确
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

react组件两种写法

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

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

react生命周期理解

参考React组件开发之路

react事件系统

ajax请求

使用axios进行,可参考此例子

dangerouslySetInnerHTML使用

function createMarkup() {
  return {__html: 'First &middot; Second'};
}

function MyComponent() {
  return <div dangerouslySetInnerHTML={createMarkup()} />;
}

# 或
<div dangerouslySetInnerHTML={{__html: 'cc &copy; 2015'}} />

react使用扩展运算符spread operator

使用扩展运算符可以用于传递多个参数

var obj = {
        name: "jason",
        num : 28
      }

      function Welcome(props) {  
        return  <h1> {props.name} {props.num}</h1>  
      }

      ReactDOM.render(
        <Welcome {...obj}/>, //  对象传递数据
        document.getElementById('root')
      );
  }

react 中 JSX children

function Item(props) {
  return <li>{props.message}</li>;
}

function TodoList() {
  const todos = ['finish doc', 'submit pr', 'nag dan to review'];
  return (
    <ul>
      {todos.map((message) => <Item key={message} message={message} />)}
    </ul>
  );
}

ReactDOM.render(...)

react API:Children使用

组件中使用Children:

'use strict';

import React, { Component } from 'react';

// 定义一个组件,通过React.Children 拿到组件里面的子元素
class ListComponent extends Component {
  render(){
    return <ul>
      {
        React.Children.map( this.props.children, function(c){
          return <li>{c}</li>;
        })
      }
    </ul>
  }
}

class UseChildrenComponent extends Component {
  render(){
    return (
      <ListComponent>
        <a href="#">Facebook</a>
        <a href="#">Google</a>
        <a href="#">SpaceX</a>
      </ListComponent>
    )
  }
}

export default UseChildrenComponent;

es6变量结构赋值

项目中有以下情况:

  • prop传入为import进来的数组或对象
  • 需要完整赋值 在父组件使用:
# 父组件(nav数据是个数组)
import {nav,} from './data';
...
render ({
        <div style={{marginTop:'-90px'}}>
          <Nav nav={nav}/>
        </div>})

# 在子组件中需要遍历nav这个数组,以下为解构赋值:
let {nav} = props
nav.map((item,index)=>{return(...)})

如果按照es6的扩展运算符呢?

#父组件
import {nav,} from './data';
...
render ({
        <div style={{marginTop:'-90px'}}>
          <Nav {...nav}/>
        </div>})

# 子组件获取到props为传入对象nav本身,进行遍历
let nav = props
for(let i in nav){
    return ({
    {nav[i].url}    
    })
}

扩展:如类对象需要转为数组,可使用Object.keys('nav'),其他方法,见Converting a JS object to an array

React-Router-DOM路由向子组件传递props

刚开始默认使用常规的传值方法:

<Route path="/:id*" HOMELINK={this.props.HOMELINK} component={Article}/>

结果显示HOMELINK为undefined,传值失败.
目前收到的解决方案:
1. 通过...props传递
React react-router-dom pass props to component

<Route path="/:id*" component={(props) => <Article {...props} HOMELINK={HOMELINK}/>}  />

2.利用render
方法见与官方文档

优点是一次注册,之后使用就同普通的组件。不用每次都写晦涩的代码片段
# 注册自定义route
const MyRoute = ({ component: Component, ...rest }) => (
      <Route {...rest} render={props => (
          <Component {...props}/>
      )}/>
    )
# 使用
<MyRoute path="/:id*" HOMELINK={HOMELINK} component={Article} />

3.通过cloneELement方法实现继承

route规则





针对此问题的讨论

* [How to pass props to components when you use <Route components={{}} /> attribute ?](https://github.com/ReactTraining/react-router/issues/4105)

# react父子组件更新
通常父组件数据更新后(如componentDidMout后ajax请求),子组件也会重新更新渲染.如子组件和此部分数据没有关系,需要在子组件中通过`shouldComponentUpdate`来阻止无谓更新。
代码见`nav-mobile`:

shouldComponentUpdate(nextProps, nextState) {
if(nextState.isShow === false && nextState.click === false) {
return false
}
return true;
}

@2017-05-26 10:46