react

Posted on By zhoulj

what is react

  • 构建用户界面的javascript库(非框架), 轻量级
  • 构建UI, mvc中v
  • 虚拟dom, 提升页面渲染速度, 变化部分局部更新
  • jsx模板语言, 具有javascript全部功能, 是js扩展(非引入新概念指令、控制器)
  • 组件化, 增强代码复用、组件独立测试
  • 单向数据流, 比数据绑定更简单(非双向绑定:数据来源混乱)

相关:

  • http://www.runoob.com/react/react-tutorial.html
  • https://facebook.github.io/react/docs/installation.html
  • http://www.ruanyifeng.com/blog/2015/03/react.html

ReactDOM.render()

模板转化html语言, 插入指定的dom

ReactDOM.render(
    <h1>Hello, world!</h1>,
    document.getElementById('example')
);

React JSX

  • Babel编译jsx->React.createElement(),不使用jsx也可以全通过js React,但是代码不简洁, 意思上是等价
react元素创建,两种方式等价-->元素区别组件
const getHelloWord = <h1>Hello, world!</h1>

const element = React.createElement(
  'h1',
  'Hello, world!'
);
  • 遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析
  • 渲染之前,转义jsx值, 避免xss攻击
  • javaScript表达式: jsx中使用js表达式, 包裹{}
    function formatName(user) {
    return user.firstName + ' ' + user.lastName;
    }
    function getGreeting(user) {
    return <h1>Hello, {formatName(user)}</h1>;-->{}
    }
    
  • jsx[用html元素]行内不能使用if、if else 语句
     if: &代替
     const getGreeting(isOpen) = <div>{isOpen && true}</div>
    
     if else:-->三元运算代替
     const getGreeting(isOpen) = <div>{isOpen ? true : false}</div>
    
  • 内联样式
    const myStyle = {
      fontSize: 100,--->元素数字后自动添加px, 驼峰转化
      color: '#FF0000'
    };
    const getGreeting() { return <div style={myStyle}></div>}
    
  • 数组元素->数组所有成员添加模板中
    const arr = [<h1>arr1</h1>, <h2>arr2</h2>]
    const getGreeting() { return <div>{arr}</div>}
    

React 组件

  • react元素 vs 组件命名:
    • 元素以小写字母开头, 组件以大写字母开头
    • 元素引用直接 元素名(所以无法传递props), 组件<element props
  • 元素创建的3中方式
    • 函数方式
    • es6 class
    • React.createClass
      function HelloWord(props) {-->props传递
        <div>{props.name}</div>
      }
      
      class HelloWolrd extends React.Component {
        render(){
            return <div>{this.props.name}</div>
        }
      }
      
      var HelloWolrd = React.createClass({
      render: function() {
      return <h1>Hello {this.props.name}</h1>;
      }
      });
      

      调用: ```

    ```

React props

  • this.props.children: 表示组件的所有子节点
    • 没有子节点undefined
    • 有一个子节点,数据类型是 object
    • 有多个子节点,数据类型就是 array
React.Children.map(this.props.children, function (child) {
   return <li>{child}</li>;-->React.Children获取所有子节点, React.Children.map遍历子节点
})

React state

  • 就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI
  • state vs props
    • props不再改变的特性,而this.state 是会随着用户互动而产生变化的特性
    • props父组件传递, state组件内部状态
  • this.state属性读取, this.setState({})变更state
    handleClick() {
        this.setState({'isOpen': !this.state.isOpen})
    }
    class Hello extends react.Component{
        render(){
            const isOpen = this.state.isOpen;
            return <a onClick=this.handleClick()>{isOpen ? true: false}</>
        }
    }
    

列表遍历、和列表key(类似js map)

List元素:
 const listItems = numbers.map((number, index) =>
    <li>{number}</li>
 );
List组件:html标签外
function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number, index) =>
    <li key={唯一的标记, 非遍历中的index索引}>{number}</li>
  );
  return (
    <ul>{listItems}</ul>
  );
}
List组件:html内标签外, {}包裹, 两种方式等价
function NumberList(props) {
  const numbers = props.numbers;
  return (
     <ul>
       {numbers.map((number) =>
          <li>{number}</li>
        )}
     </ul>
  );
}
  • 遍历添加key: 唯一标记这条记录,虚拟dom比较索引,加载查找速度
    • 不要使用map->index作为key
    • 不用组件中, 定义相关的key, 无影响
    • NumberList->ListItem->li多层组件, key添加到ListItem非遍历li上
    • key不存在props传递中, 如果需要传递唯一标识,可以id替换

Forms

react form elements例如input、textarea、select跟html中区别

  • html: 用户输入界面, 界面值变更。
  • react: 需要onChange事件的回调函数,通过 event.target.value 读取用户输入的值,设置setState() 界面值变更
     handleChange: function(event) {
      this.setState({value: event.target.value});
     },
    render: function () {
      var value = this.state.value;
      return (
        <div>
          <input type="text" value={value} onChange={this.handleChange} />
          <p>{value}</p>
        </div>
      );
    }
    

组件组合和继承

建议组合增强复用性, 非继承

继承三种方式

  • 对子节点类型不明确–>只有一个子组件props.children
function FancyBorder(props) {
  return (
    <div>
      {props.children}
    </div>
  );
}
调用:
<FancyBorder>
  <div></div>--->这个位置除了普通元素, 也可以是组件
<FancyBorder>  
  • 多个子组件类型不明确–>两个props
function FancyBorder(props) {
  return (
    <div>
      {props.left}
    </div>
    <div>
      {props.right}
    </div>
  );
}
调用:
<FancyBorder>
  left={<A />}
  right={<B />}--->这个位置除了普通元素, 也可以是组件
<FancyBorder> 
  • A组件是B组件一个特例
function Dialog(props) {
  return (
    <FancyBorder>
      <h1>
        {props.title}
      </h1>
      <p>
        {props.message}
      </p>
    </FancyBorder>
  );
}

function WelcomeDialog() {
  return (
    <Dialog
      title="Welcome"
      message="test" />
  );
}