美文网首页Frontend前端
一、React基础知识再出发(一)

一、React基础知识再出发(一)

作者: 雪燃归来 | 来源:发表于2020-06-19 09:29 被阅读0次

           由于在工作中,经常使用vue,对react并不是很熟练,本篇将通过对比vue的方式来学习react。


    react特点

    1、Fragment非占位元素标签组件

    import { Fragment } from 'react'
    
    class TodoList extends Component{
        render(){
            return (
                <Fragment>
                    <div>
                        <input />
                        <button>提交</button>
                    </div>
                    <ul>
                        <li>学英语</li>
                        <li>Learning React</li>
                    </ul>
                </Fragment>
            )
        }
    }
    

    2、React中构造函数会最新被执行,可以在构造函数中定义状态state

    constructor(props){
         super(props)
         this.state = {
              inputValue: '',
              list: []
         }
    }
    

    3、绑定值跟vue相似,但语法稍有差别

    <input value={this.state.inputValue}/>         
    

    4、实现双向数据绑定跟vue相似,vue中使用指令v-model,v-model在vue中是:value@input事件的语法糖.

    vue代码

    <input type="text" 
       value="price" 
       @input="price=$event.target.value">
    

    react代码

    <input 
         value={this.state.inputValue}
          onChange={this.handleInputChange.bind(this)}
    />
    
    handleInputChange(e){
         this.setState({
              inputValue: e.target.value
         })
    }
    

           不同之处在于,vue中监听的是input事件,而react中监听的是onChange事件,注意,react中事件名一定要写成onChange, 不能写成原生的onchange。另外在给input绑定事件handleInputChange的时候,一定要通过bind(this)方式指定其执行的作用域。

    5、react中的for循环。

           react中没有像vue中的指令v-for, 只能通过编写常规的js代码实现循环的逻辑。

    <ul>
        {
            this.state.list.map((item, index) => {
                 return <li key={index}>{item}</li>
            })
        }
    </ul>
    

           此处要注意的一点,就是我们使用了index值作为key值,这种方法是我们不推荐使用的,因为动态变化的indexkey值的时候,会影响到diff算法的过程。具体你可以查看我之前写过的文章《虚拟DOM(Virtual DOM)中动态更新视图的diff算法》

    6、改变state中数据源中的数组数据

           跟vue中给数据源中push数据方式不同,react中并不能直接修改state中的值(存在immutable的原因,相关知识你可以查看https://www.jianshu.com/p/825b7b4c401d
    )。所以,我们先将数据拷贝出来,然后通过this.setState方法修改数据

    <button onClick={this.handleBtnClick.bind(this)}>提交</button>
    handleBtnClick(){
        this.setState({
            list: [...this.state.list, this.state.inputValue],
            inputValue: ''
        })
    }
    

    7、删除数据的操作

    <ul>
       {
           this.state.list.map((item, index) => {
                return <li key={index} onClick={this.handleDelete.bind(this, index)}>{item}</li>
            })
       }
    </ul>
    
    handleDelete(index){
       const list = [...this.state.list]
       list.splice(index, 1)
       this.setState({
           list
       })
     }
    

    8、react中的注释

    单行注释

    {/*这是单行注释*/}
    

    多行注释

    {
      // 这里写多行注释
    }
    

    9、jsx语法中的注意事项

           (1)、定义样式的时候要用className,而不是class

    import './index.css'
    <input 
          className="input"
          value={this.state.inputValue}
          onChange={this.handleInputChange.bind(this)}/>
    

           (2)、label标签中的for属性要用htmlFor代替。

    <div>
        <label htmlFor="insertArea">输入内容</label>
        <input 
              className="input"
              id="insertArea"
                        ...
           />
        ...
    </div>
    

           (3)、使用了dangerouslySetInnerHTML进行模版编译输出。当然这是一个危险的操作,可能会存在XSS风险。在vue中,我们是通过指令v-html实现的。

    <ul>
        {
           this.state.list.map((item, index) => {
                return <li 
                       key={index} 
                       onClick={this.handleDelete.bind(this, index)}
                       dangerouslySetInnerHTML={{__html:item}}>
                    </li>
             })
         }
    </ul>
    

    10、react中父子组件的数据通信

           在vue中,父子组件的通信是通过props和$emit通信的。在react中,原理相似,但稍微有一点差别。react中,父组件通过props向子组件传递state和方法(用于操作父组件state中的数据),子组件接收到这些方法后,通过调用这些方法,实现对父组件数据的改变。
    父组件TodoList

    import TodoItem from './TodoItem'
    <ul>
         {
             this.state.list.map((item, index) => {
                  return <TodoItem 
                          key={index}
                          content={item}
                          index={index}
                          deleteItem={this.handleDelete.bind(this)}/>
            })
         }
    </ul>
    

    子组件TodoItem

    import React, { Component } from 'react'
    
    class TodoItem extends Component{
        render(){
            return (<li onClick={this.handleClick.bind(this)}>
                    {this.props.content}
            </li>)
        }
        handleClick(){
            this.props.deleteItem(this.props.index)
        }
    }
    
    export default TodoItem
    

           此处要注意一点,父组件在将方法传递给子组件的时候,需要通过bind(this)指定其作用域,否则会存在this指针错误的情况。

    11、react编码的优化方案

           (1)、在构造器中统一处理函数的this绑定问题。

    constructor(props){
            super(props)
           ...
            this.handleInputChange = this.handleInputChange.bind(this)
            this.handleBtnClick = this.handleBtnClick.bind(this)
            this.handleDelete = this.handleDelete.bind(this)
    }
    
    <div>
          <label htmlFor="insertArea">输入内容</label>
          <input 
                ...
                value={this.state.inputValue}
                 onChange={this.handleInputChange}/>
          <button onClick={this.handleBtnClick}>提交</button>
    </div>
    

           (2)、修正this.setState方法的正确使用姿势
    之前的使用方式

    handleDelete(index){
       const list = [...this.state.list]
       list.splice(index, 1)
       this.setState({
            list
        })
    }
    

    修正后的使用方式

    handleDelete(index){
            this.setState((prevState) => {
                const list = [...prevState.list]
                list.splice(index, 1)
                return { list }
            })
    }
    

           此处主要强调参数prevState的使用。
           (3)、业务组件和视图组件的解耦
    解耦前

    <ul>
         {
             this.state.list.map((item, index) => {
                  return <TodoItem 
                          key={index}
                          content={item}
                          index={index}
                          deleteItem={this.handleDelete.bind(this)}/>
            })
         }
    </ul>
    

    解耦后

    <ul>
       {
           this.getItem()
        }
    </ul>
    
    getItem(){
            return (
                this.state.list.map((item, index) => {
                    return <TodoItem 
                        key={index}
                        content={item}
                        index={index}
                        deleteItem={this.handleDelete}/>
                })
            ) 
        }
    

    相关文章

      网友评论

        本文标题:一、React基础知识再出发(一)

        本文链接:https://www.haomeiwen.com/subject/ytbmxktx.html