前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >组件设计基础(1)

组件设计基础(1)

作者头像
一粒小麦
发布2019-12-04 12:09:04
4120
发布2019-12-04 12:09:04
举报
文章被收录于专栏:一Li小麦一Li小麦

设计易于维护的组件

单一职责原则在react组件设计中依然管用,尤其是维护一个大型的页面时。但也不是事无巨细都需要拆分。根据所谓"高内聚低耦合"的思想,逻辑紧密的组件是不适合拆分的。

react的组件基础,应当时时复习。必要时自己写一写。

react的组件

在react中组件有很多种方法,es5下createClass在React16以后的版本全部废弃。

而上文计数器的实例,就是一种标准的创建,通常包含交互与状态。此外还有两种创建的思路:

Functional Component(函数式组件)

通常用于创建无状态的组件。它接受props作为参数,和标准创建相比,没有继承React.Component。

代码语言:javascript
复制
function Hello({name}){
  return <>{hello,${name}}</>
}
Hello.PropTypes={
  name:React.propTypes.string
}
Hello.defaultPropTypes={
  name:'world'
}

PrueComponent(纯粹组件)

在维护一个拥有众多子组件的页面时,也许有些组件跟你当前的功能八杆子打不着。但最后的结果也参与了渲染。react15.3之后就出现了PrueComponent的概念。

PureComponent改变了生命周期方法shouldComponentUpdate,并且它会自动检查组件是否需要重新渲染。这时,只有PureComponent检测到state或者props发生变化时,PureComponent才会调用render方法,因此,你不用手动写额外的检查,就可以在很多组件中改变state

如果让你手写一个PureComponnet:

代码语言:javascript
复制
// 只做浅拷贝比较
const shallowCompares=(a,b)=>{
  if(a==b){return true;}
  if(Object.keys(a).length!==Object.keys(b).length){
    return false;
  }
  return Object.keys(a).every(k=>a[k]==b[k]);
}

class Pure extends Component{
  shouldComponentUpdate(nextProps,nextState){
    const {props,state}=this;
    return !shallowCompares(props,nextProps) && !shallowCompares(state,nextState)
  }
}

现在稍微改写下上节的计数器:

代码语言:javascript
复制
import React, { Component , PureComponent} from 'react';

class Show extends PureComponent {
    render() {
        console.log('渲染了')
        return (
            <div>
                1
            </div>
        )
    }
}


export default class ClickCounter extends Component {
    constructor(props){
        super(props);
        this.state={
            count:0
        }
    }

    handleClick=()=>{
        this.setState((preState)=>{
            return {
                counter:preState.count++
            }
        })
    }

    render() {
        return (
            <div>
                <Show/>
                <button onClick={this.handleClick}>点我</button>
            </div>
        )
    }
}

这个案例中,作为一个纯组件,Show无论怎么点击都不会触发渲染。

props

在React中,prop(property的简写)是从外部传递给组件的数据,一个React组件通过定义自己能够接受的prop就定义了自己的对外公共接口。每个React组件都是独立存在的模块,组件之外的一切都是外部世界,外部世界就是通过prop来和组件对话的。

既然prop是组件的对外接口,那么就应该有某种方式让组件声明自己的接口规范。简单说,一个组件应该可以规范以下这些方面:

  • 这个组件支持哪些prop;
  • 每个prop应该是什么样的格式。

React通过propTypes来支持这些功能。在ES6方法定义的组件类中,可以通过增加类的propTypes属性来定义prop规格,这不只是声明,而且是一种限制,在运行时和静态代码检查时,都可以根据propTypes判断外部世界是否正确地使用了组件的属性,是否必须等。

代码语言:javascript
复制
Hello.PropTypes={
  name:React.propTypes.string.isRequired;
}
Hello.defaultPropTypes={
  name:'world'
}

当然这只是开发辅助功能,生产环境应该考虑去掉。

state

"不要直接修改组件的state",是react的常识。

阅读以下代码

代码语言:javascript
复制
import React, { Component } from 'react'
import PropTypes from 'prop-types';

const styles = {
    counter: { 
        width: 200, 
        display: 'flex' 
    },
    showbox: {
        width: 80,
        textAlign: 'center'
    }
}

class ClickCounter extends Component {
    constructor(props) {
        super(props);
        this.state = {
            count: props.initValue
        }
    }

    handleIncrease = () => {
        this.setState((preState) => {
            return {
                counter: preState.count++
            }
        })
    }

    handleDecrease = () => {
        this.setState((preState) => {
            return {
                counter: preState.count--
            }
        })
    }

    render() {
        return (
            <div style={styles.counter}>
                <button onClick={this.handleDecrease}>-</button>
                <div style={styles.showbox}>{this.state.count}</div>
                <button onClick={this.handleIncrease}>+</button>
            </div>
        )
    }
}

ClickCounter.propTypes = {
    initValue: PropTypes.number.isRequired
}

ClickCounter.defaultProps = {
    initValue: 0
}

export default ClickCounter

此时界面是:

如果我们把新增的逻辑改为:

代码语言:javascript
复制
handleIncrease = () => {
    this.state.count++;
    // this.setState((preState) => {
    //     return {
    //         counter: preState.count++
    //     }
    // })
}

点击3次+号你会发现增加怎样都不成功。点击减法时,state一下变成了2。

直接修改this.state的值,虽然事实上改变了组件的内部状态,但只是野蛮地修改了state,却没有驱动组件进行重新渲染,既然组件没有重新渲染,当然不会反应this.state值的变化;而this.setState()函数所做的事情,首先是改变this.state的值,然后驱动组件经历更新过程,这样才有机会让this.state里新的值出现在界面上。

prop和state的差异

•prop用于定义外部接口,state用于记录内部状态;•prop的赋值在外部世界使用组件时,state的赋值在组件内部;•组件不应该改变prop的值,而state存在的目的就是让组件来改变的。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一Li小麦 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 设计易于维护的组件
  • react的组件
    • Functional Component(函数式组件)
      • PrueComponent(纯粹组件)
      • props
      • state
      • prop和state的差异
      相关产品与服务
      腾讯云代码分析
      腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档