React入门

虚拟dom、jsx

  • 从 JSX 到页面到底经过了什么样的过程:

React入门

  1. JSX 是 JavaScript 语言的一种语法扩展,长得像 HTML,但并不是 HTML。
  2. React.js 可以用 JSX 来描述你的组件长什么样的。
  3. JSX 在编译的时候会变成相应的 JavaScript 对象描述。
  4. react-dom 负责把这个用来描述 UI 信息的 JavaScript 对象变成 DOM 元素,并且渲染到页面上。

虚拟dom:

  1. state异步合并:改变 state 数据时,由于 setState 是一个异步函数,当你一次调用多个 setState 时,React 并不会生成多次虚拟 DOM 而是将多次 setState 合并,然后生成一次虚拟 DOM 进行比对

  2. js对比渲染:新的虚拟 DOM 与原来的虚拟 DOM 进行比对时,它会进行同层比较,即相同的节点层进行比较,如果不同则直接将原始虚拟 DOM 中该节点层及以下的节点全部删除,重新生成新的虚拟 DOM 节点,而不会继续向下比对

  3. 循环需要加key:你在 JSX 模板中遍历 state 中某个数据时,为什么不加 key 值浏览器会报错,这是因为你不再遍历的每条数据加上 key 值,更改 state 中那条数据的值,生成虚拟 DOM 后,React 就不知道原始遍历的数据和这次更新后遍历的数据一一对应的关系,就会再次重新渲染,而加上 key 值,它则能迅速比对出有差异的部分进行部分的更新。

  4. 为什么不建议用 index 作为 key 值:因为当你插入 / 删除中间的数据时,从改变的那个数据开始,后续每个数据的 index 值就会变,从而就导致了每个数据的 key 值相应变化了,这样依旧会引起大规模渲染,这就是其中的原因

// 普通的代码
<div class='box' id='content'>
  <div class='title'>Hello</div>
  <button>Click</button>
</div>

// 代码对应转化出来的js
// HTML 的信息和 JavaScript 所包含的结构和信息其实是一样的,我们可以用 JavaScript 对象来描述所有能用 HTML 表示的 UI 信息
{
  tag: 'div',
  attrs: { className: 'box', id: 'content'},
  children: [
    {
      tag: 'div',
      arrts: { className: 'title' },
      children: ['Hello']
    },
    {
      tag: 'button',
      attrs: null,
      children: ['Click']
    }
  ]
}


// 编译后的代码
// React.createElement 会构建一个 JavaScript 对象来描述你 HTML 结构的信息,包括标签名、属性、还有子元素等。
class Header extends Component {
  render () {
    return (
     React.createElement(
               'div',
               { 'class': 'box', id: 'content' },
               React.createElement(
                  'div',
                  { 'class': 'title' },
                  'Hello'
               ),
               React.createElement(
                  'button',
                  null,
                  'Click'
            )
        )
    )
  }
}

render(不要在render里setState)

  1. 一个组件类必须要实现一个 render 方法。
  2. 这个 render 方法必须要返回一个 JSX 元素。
  3. 必须要用一个外层的 JSX 元素把所有内容包裹起来。
// 错误
render () {
  return (
    <div>第一个</div>
    <div>第二个</div>
  )
}

// 正确
render () {
  return (
    <div>
      <div>第一个</div>
      <div>第二个</div>
    </div>
  )
}

// 定义常量
render () {
  const className = 'header';
  const isGoodWord = true;
  return (
    <div className={className}>
      <h1>React 小书</h1>
       {isGoodWord
          ? <strong> is good</strong>
          : <span> is not good</span>
        }
    </div>
  )
}

生命周期

class Header extends Component {
  constructor () {
    super()
    // 最早渲染
    console.log('construct')
  }
  // 组件挂载开始之前,也就是在组件调用 render 方法之前调用。
  componentWillMount () {
    console.log('component will mount')
  }
  // 组件挂载完成以后,也就是 DOM 元素已经插入页面后调用。
  componentDidMount () {
    console.log('component did mount')
  }
  render () {
    console.log('render')
    return (
      <div>
        <h1 className='title'>React 小书</h1>
      </div>
    )
  }
}
// 控制台输出
construct
component will mount
render
component did mount


// 性能优化
// 你可以通过这个方法控制组件是否重新渲染。如果返回 false 组件就不会重新渲染。
shouldComponentUpdate(nextProps, nextState){
     // 值没有发生过变化,不需要重新触发render
     if(nextState.Number == this.state.Number){
        return false
     }
}

// 组件收到新的 props 之前调用
componentWillReceiveProps(nextProps){
   
}

componentWillUpdate():组件开始重新渲染之前调用。

componentDidUpdate():组件重新渲染并且把更改变更到真实的 DOM 以后调用。


// 组件对应的 DOM 元素从页面中删除之前调用。常用于离开页面清除定时器
componentWillUnmount(){
  console.log('component will unmount')
}

dom操作之ref

以前我们通过手动 DOM 操作进行页面更新(例如借助 jQuery),而在 React.js 当中可以直接通过 setState 的方式重新渲染组件,渲染的时候可以把新的 props 传递给子组件,从而达到页面更新的效果。

// 我们给 input 元素加了一个 ref 属性,这个属性值是一个函数。
// 当 input元素在页面上挂载完成以后,React.js就会调用这个函数,
// 并且把这个挂载以后的 DOM 节点传给这个函数。
// 在函数中我们把这个 DOM元素设置为组件实例的一个属性,
// 这样以后我们就可以通过 this.input 获取到这个 DOM 元素
class AutoFocusInput extends Component {
  componentDidMount () {
    this.input.focus()
  }

  render () {
    return (
      <input ref={(input) => this.input = input} />
    )
  }
}

组件

  • class组件
import React from 'react'

import ReactDOM from 'react-dom'

class App extends React.Component{
    render(){
        return(
        //此处的this指的就是App组件,自定义在App上的属性就在this的props上
            console.log(this),
            <h1>Hello {this.props.name}React!</h1>
        )
    }
}

less语法

// 设置行内样式
// 之前html的写法
<h1 style='font-size: 12px; color: red;'>React.js 小书</h1>
// react的写法,参数驼峰
<h1 style={{fontSize: '12px', color: 'red'}}>React.js 小书</h1>
  • 数据流(props、state)
  1. props
  2. state
    使用方式:1 初始化state 2 setState修改state
  • 注意:使用 setState() 方法修改状态,状态改变后,React会重新渲染组件
  • 注意:不要直接修改state属性的值,这样不会重新渲染组件!!!
  • 事件

父子组件传值

案例讲解

  • 定义一个自定义组件
  • 组件封装
  • 父子组件传值