React高级(五)

一. 调试工具的安装及使用

React在浏览器端是有一个调试工具的,这就是React developer tools,它会比console.log()方便很多。

1.1 React developer tools的三种状态

React developer tools有三种颜色,三种颜色代表三种状态:

  1. 灰色:说明页面不是由React编写的,不可使用该插件。
  2. 黑色: 说明页面是用React编写的,并且处于生产(production)环境当中。
  3. 红色: 说明页面是用React编写的,并且处于调试开发环境当中。
1.2 React developer tools使用

打开浏览器,然后按F12,打开开发者工具,然后在面板中你会找到这个安装的插件了。

在这里你可以清晰的看到React的结构,让自己写的代码更加清晰,你还可以看到组件间的数据传递,再也不用写console.log来测试程序了。

二. PropTypes校验传递值

在父组件向子组件传递数据时,使用了属性的方式,也就是props,但“小姐姐服务菜单”的案例并没有任何的限制。这在工作中是完全不允许的,因为大型项目,如果你不校验,后期会变的异常混乱,业务逻辑也没办法保证。

2.1 PropTypes的简单应用

我们在Xiaojiejie.js组件里传递了4个值,有字符串,有数字,有方法,这些都是可以使用PropTypes限制的。在使用前需要先引入PropTypes

import PropTypes from 'prop-types'

引入后,就可以在组件的下方进行引用了,需要注意的是子组件的最下面(不是类里边),写入下面的代码:


import React, { Component } from 'react'; //imrc
import PropTypes from 'prop-types'

class XiaojiejieItem  extends Component { //cc
   
   constructor(props){
       super(props)
       this.handleClick=this.handleClick.bind(this)
   }
   
    render() { 
        return ( 
            <div onClick={this.handleClick}>
                {this.props.content}
            </div>
        );
    }

    handleClick(){
        
        this.props.deleteItem(this.props.index)
    }
    
}
 //--------------类型校验代码--------start
XiaojiejieItem.propTypes={
    content:PropTypes.string,
    deleteItem:PropTypes.func,
    index:PropTypes.number
}
 //--------------类型校验代码--------end
export default XiaojiejieItem;

这时候你在浏览器中查看效果,是什么都看不出来的,你需要修改一个错误的校验。比如我们把index改为必须是字符串。

index:PorpTypes.string

这时候浏览器的console里就会报错了,报错信息如下:

Warning: Failed prop type: Invalid prop `index` of type `number` supplied to `XiaojiejieItem`, expected `string`.
    in XiaojiejieItem (at Xiaojiejie.js:28)
    in Xiaojiejie (at src/index.js:5)

意思就是要求传递字符串,而我们却传递了数字过去,所以给了警告。

2.2 必传值的校验

比如现在我们加入一个avname的属性,并放入JSX中,就算不传递这个值也不会报错的。代码如下:

render() { 
    return ( 
        <div onClick={this.handleClick}>
            {this.props.avname}为你做- {this.props.content}
        </div>
    );
}

这时候代码是不会报错的,我们传不传无所谓。比如我们现在传一个属性过来。

<ul>
    {
        this.state.list.map((item,index)=>{
            return (
                <XiaojiejieItem 
                key={index+item}  
                content={item}
                index={index}
                avname='波多野结衣'
                deleteItem={this.deleteItem.bind(this)}
                />
            )
        })
    }
</ul>  

这时候页面显示正常了,但是怎样避免必须传递avname这个属性值?如果不传递就报错,这就需要使用isRequired关键字了,它表示必须进行传递,如果不传递就报错。

avname:PropTypes.string.isRequired
2.3 使用默认值defaultProps

有些人是非常腼腆的,他是不好意思选择的,所以有时候是需要有一个默认的人为她服务的。defalutProps就可以实现默认值的功能,比如现在把avname的默认值设置成"松岛枫" ,然后把avname的属性删除掉。

XiaojiejieItem.defaultProps = {
    avname:'松岛枫'
}

其实检测的类型非常多,你最好去官方文档看一下,能得到比较全面的了解。

上述整体代码如下:
import React from 'react';
import PropTypes from 'prop-types'
import {Fragment} from 'react'
class XiaojiejieItem extends React.Component {
    constructor(props) {
        super(props)
        this.handleClick = this.handleClick.bind(this)

    }
    render() { 
        return (
            <Fragment>
                <div>{this.props.avname}</div>
                <li onClick={this.handleClick}>{this.props.content}</li>
            </Fragment>
            
        );
    }
    handleClick() {
        console.log(this.props.index)
        this.props.delItem(this.props.index)
    }
}
XiaojiejieItem.propTypes = {
    content: PropTypes.string.isRequired,
    index: PropTypes.number,
    delItem: PropTypes.func
}
XiaojiejieItem.defaultProps = {
    avname: '哈哈哈'
}
export default XiaojiejieItem

三. ref的使用方法

在编写组件中的方法时,经常会遇到语义化很模糊的代码,这对于团队开发是一个很大的问题。因为review代码或者合作时都会影响开发效率。或者某核心成员离开,导致项目倒闭的严重影响。所以我们必须重视react代码当中的语义化。ref是个不错的工具,快来学习一下吧。

3.1 代替原来的e.target.value

以前的案例中,我们写了下面的代码,使用了e.target,这并不直观,也不好看。这种情况我们可以使用ref来进行解决。

inputChange(e){
    
    this.setState({
        inputValue:e.target.value
    })
}

如果要使用ref,需要先在JSX中进行绑定, 绑定时最好使用ES6语法中的箭头函数,这样可以简洁明了的绑定DOM元素。

<input 
    id="jspang" 
    className="input" 
    value={this.state.inputValue} 
    onChange={this.inputChange.bind(this)}
    //关键代码——----------start
    ref={(input)=>{this.input=input}}
    //关键代码------------end
    />

绑定后可以把上边的类改写成如下代码:

inputChange(){
    this.setState({
        inputValue:this.input.value
    })
}

这就使我们的代码变得语义化和优雅的多。但是就我个人的经验来讲,我是不建议用ref这样操作的,因为React的是数据驱动的,所以用ref会出现各种问题

3.2 this.setState使用中的坑

比如现在我们要用ref绑定取得要服务的数量,可以先用ref进行绑定。

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

绑定后可以在addList()方法中,获取当前<div>的值。


addList(){
    this.setState({
        list:[...this.state.list,this.state.inputValue],
        inputValue:''
    })
    //关键代码--------------start
    console.log(this.ul.querySelectorAll('div').length)
    //关键代码--------------end
}

这时候你打开控制台,点击添加服务按钮,你会返现数量怎么少一个?(就是这个坑),其实这个坑是因为React中的setState是一个异步函数所造成的

那这个代码怎么编写才会完全正常呢?其实setState方法提供了一个回调函数,也就是它的第二个函数。下面这样写就可以实现我们想要的方法了。

addList(){
    this.setState({
        list:[...this.state.list,this.state.inputValue],
        inputValue:''
        //关键代码--------------start
    },()=>{
        console.log(this.ul.querySelectorAll('div').length)
    })
    //关键代码--------------end
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

. . . . .

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值