React 基础文档

一. React的基本使用

API

  1. ReactDOM.render(vDom, dDom) // 挂载组件,第一个参数为虚拟dom节点,第二个参数为要挂载的真实dom
  2. ReactDOM.unmountComponentAtNode(dDom) // 卸载dom下的组件
  3. React.createElement(tag, props, node) // 创建虚拟dom,第一个参数为标签名,第二个参数名为属性值,第三个参数为文本内容
    const msg = 'i like you!'
    const myId = 'atguigu'
    
    const vDom1 = React.createElement('h2', { id: myId.toLowerCase(), className: myId.toLowerCase() }, msg.toLowerCase())
    

1.1 相关js库

  1. react.js:React核心库。
  2. react-dom.js:提供操作DOM的react扩展库。
  3. babel.min.js:解析JSX语法代码转为JS代码的库。

1.2 hello,react

<!-- 准备好一个“容器” -->
<div id="test"></div>

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>

<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>

<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel" > /* 此处一定要写babel */
	// 1.创建虚拟DOM
	const VDOM = <h1>Hello,React</h1> /* 此处一定不要写引号,因为不是字符串 */
	// 2.渲染虚拟DOM到页面
	ReactDOM.render(VDOM, document.getElementById('test'))
</script>

1.3 JSX(JavaScript XML)

react 定义的一种类似于XML的JS扩展语法: JS + XML 本质是React.createElement(component, props, …children)方法的语法糖 (标签名, 属性, 文本内容)

1.3.1 作用

用来简化创建虚拟DOM

注意点:

  1. 不是字符串, 也不是HTML/XML标签
  2. 最终产生的就是一个JS对象

语法规则:

  1. 遇到 < 开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
  2. 遇到以 { 开头的代码,以JS语法解析: 标签中的js表达式必须用{ }包含
1.3.2 渲染虚拟DOM(元素)
  1. 语法: ReactDOM.render(virtualDOM, containerDOM)
  2. 作用: 将虚拟DOM元素渲染到页面中的真实容器DOM中显示
  3. 参数说明
    1)参数一: 纯js或jsx创建的虚拟dom对象
    2)参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)
<div id="test1"></div>
<div id="test2"></div>

<script src="./js/react.development.js"></script>
<script src="./js/react-dom.development.js"></script>
<script src="./js/babel.min.js"></script>

<script>
  const msg = 'i like you!'
  const myId = 'atguigu'

  const vDom1 = React.createElement('h2', { id: myId.toLowerCase(), className: myId.toLowerCase() }, msg.toLowerCase())

  ReactDOM.render(vDom1, document.getElementById('test1'))
</script>

 <script type="text/babel">
  const vDom2 = <h3 id={ myId.toUpperCase() }>{ msg.toUpperCase() }</h3>
  ReactDOM.render(vDom2, document.getElementById('test2'))
</script>

渲染结果
React 基础文档

1.3.3 遍历列表小练习
<script type="text/babel">
  const names = ['react', 'vue', 'jQuery']
  const vDom = (
    <ul>
      { names.map((item, index) => <li key={index}>{ item }</li>) }
    </ul>
  )
  ReactDOM.render(vDom, document.getElementById('test1'))
</script>

二. 组件化

2.1 简单例子

<script type="text/babel">
  /**
   * 	方式一:工厂函数组件
   */
  function MyComponent1() {
    return <h1>工厂函数组件</h1>
  }
  /**
   * 	方式二:类组件
   */
  class MyComponent2 extends React.Component {
    render() {
      return <h1>类组件</h1>
    }
  }
  ReactDOM.render(<MyComponent1 />, document.getElementById('test1'))
  ReactDOM.render(<MyComponent2 />, document.getElementById('test2'))
</script>

2.2 组件三大属性

2.2.1 state
  1. state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
  2. 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
<script type="text/babel"> 
  class Like extends React.Component {
    constructor (props) {
      super(props)
      // 初始化状态
      this.state = {
        isLikeMe: false
      }

      // 修改this指向
      this.handleClick = this.handleClick.bind(this)
    }

    // 新添加的方法内部this为undefined
    handleClick () {
      // 获取状态并取反
      const isLikeMe = !this.state.isLikeMe
      // 更新状态
      this.setState({ isLikeMe })
    }


    render() {
      const { isLikeMe } = this.state
      return <h1 onClick={ this.handleClick }>{ isLikeMe ? '你喜欢我' : '我喜欢你' }</h1>
    }

  }
  ReactDOM.render(<Like />, document.getElementById('test1'))
</script>

注意:

  1. 组件中render方法中的this为组件实例对象
  2. 组件自定义的方法中this为undefined,如何解决?
    a)强制绑定this: 通过函数对象的bind()
    b)箭头函数
  3. 状态数据,不能直接修改或更新
2.2.2 props

通过标签属性从组件外向组件内传递变化的数据

注意: 组件内部不要修改props数据

编码操作:

  1. 内部读取某个属性值

    this.props.name
    
  2. 对props中的属性值进行类型限制和必要性限制
    第一种方式(React v15.5 开始已弃用):

    Person.propTypes = {
      name: React.PropTypes.string.isRequired,
      age: React.PropTypes.number
    }
    

    第二种方式(新):使用prop-types库进限制(需要引入prop-types库)

     Person.propTypes = {
       name: PropTypes.string.isRequired, // 必填,string 类型
       age: PropTypes.number. 
    }
    

    详细参考

  3. 默认 Prop 值

     Person.defaultProps = {
       age: 18,
       sex:'男'
     }
    

工厂函数构建

<script type="text/babel">
  function Person(props) {
    return (
      <ul>
        <li>姓名:{ props.name }</li>
        <li>年龄:{ props.age }</li>
        <li>性别:{ props.sex }</li>
      </ul>
    )
  }
  
  const p1 = {
    name: '张三'
  }

  // 默认值
  Person.defaultProps = {
    age: 18,
    sex: '男'
  }

  // 限制类型
  Person.propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number
  }
  
  ReactDOM.render(<Person name={ p1.name } />, document.getElementById('test1'))
</script>

组件类构建

<script type="text/babel">
  class Person extends React.Component {
    render() {
      return (
        <ul>
          <li>姓名:{this.props.name}</li>
          <li>年龄:{this.props.age}</li>
          <li>性别:{this.props.sex}</li>
        </ul>
      )
    }
  }

  const p1 = {
    name: '李四',
    age: 20
  }

  // 默认值
  Person.defaultProps = {
    age: 18,
    sex: '男'
  }

  // 限制类型
  Person.propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number
  }

  ReactDOM.render(<Person { ...p1 } />, document.getElementById('test1'))
</script>
2.2.3 refs

组件内的标签可以定义ref属性来标识自己

  1. 字符串形式的ref
    <input ref="input1" />
    
    // 通过 refs 获取dom
    const input1 = this.refs.input1
    
  2. 回调形式的ref
    <input ref={ c => this.input1 = c } />
    
    // 通过 this.xxx 获取dom
    console.log(this.input1.value)
    
  3. createRef 创建 ref 容器(新版本)
    class CustomTextInput extends React.Component {
      constructor(props) {
        super(props)
        // 创建一个 ref 来存储 textInput 的 DOM 元素
        this.textInput = React.createRef()
        this.focusTextInput = this.focusTextInput.bind(this)
      }
    
      focusTextInput() {
        // 注意:我们通过 "current" 来访问 DOM 节点
        this.textInput.current.focus()
      }
    
      render() {
        // 告诉 React 我们想把 <input> ref 关联到
        // 构造器里创建的 `textInput` 上
        return (
          <div>
            <input type="text" ref={ this.textInput } />  
            <input type="button" onClick={ this.focusTextInput }  />
          </div>
        )
      }
    }
    
2.2.4 组件化简单demo
<script type="text/babel">
  class App extends React.Component {
    constructor(props){
      super(props)
      this.state = {
        todos: ['吃饭', '睡觉', '打豆豆']
      }

      this.addTodo = this.addTodo.bind(this)
    }

    addTodo(res) {
      const { todos } = this.state
      todos.unshift(res)
      this.setState({ todos })
    }

    render() {
      const { todos } = this.state
      return (
        <div>
          <Add count={ todos.length } addTodo={ this.addTodo } />
          <List todos={ todos } />
        </div>
      )
    }
  }

  class Add extends React.Component {
    constructor(props){
      super(props)
      this.input = React.createRef()
      this.add = this.add.bind(this)
    }

    add () {
      const inputValue = this.input.current.value.trim()
      if (inputValue) {
        this.props.addTodo(inputValue)
        this.input.current.value = ''
      }
    }

    render() {
      return (
        <div>
          <input type="text" ref={ this.input } />
          <button onClick={ this.add }>#{ this.props.count + 1 }</button>
        </div>
      )
    }
  }

  Add.propTypes = {
    count: PropTypes.number.isRequired,
    addTodo: PropTypes.func.isRequired
  }

  class List extends React.Component {
    constructor(props){
      super(props)
      
    }
    render() {
      const { todos } = this.props
      return (
        <ul>
          { todos.map((item, index) => <li key={ index }>{ item }</li>) }
        </ul>
      )
    }
  }

  List.propTypes = {
    todos: PropTypes.array.isRequired,
  }
  
  ReactDOM.render(<App />, document.getElementById('test1'))
</script>

三. 生命周期

  1. 初始化阶段: 由ReactDOM.render()触发—初次渲染
    1.constructor()
    2.componentWillMount() // 组件挂载完成前
    3.render() // 初始化渲染或更新渲染调用
    4.componentDidMount() // 组件挂载完成后,开启监听, 发送ajax请求
  2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
    1.componentWillUpdate() // 数据更新前
    2.componentDidUpdate() // 数据更新后
  3. 销毁阶段: 由**ReactDOM.unmountComponentAtNode()**触发
    1.componentWillUnmount() // 组件销毁前,做一些收尾工作, 如: 清理定时器
上一篇:初学react 环境搭建


下一篇:双击安装Apk,可选目标设备的小脚本