专栏首页一Li小麦组件设计基础(1)

组件设计基础(1)

设计易于维护的组件

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

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

react的组件

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

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

Functional Component(函数式组件)

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

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:

// 只做浅拷贝比较
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)
  }
}

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

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判断外部世界是否正确地使用了组件的属性,是否必须等。

Hello.PropTypes={
  name:React.propTypes.string.isRequired;
}
Hello.defaultPropTypes={
  name:'world'
}

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

state

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

阅读以下代码

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

此时界面是:

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

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存在的目的就是让组件来改变的。

本文分享自微信公众号 - 一Li小麦(gh_c88159ec1309),作者:一li小麦

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 组件设计基础(2)

    早期的react设计了许多的生命周期钩子。它们严格定义了组件的生命周期,一般说,生命周期可能会经历如下三个过程:

    一粒小麦
  • react核心api

    react从16年12月开始,已经学了有2年多了。react引导了作者找到了第一份比较专职的前端工作。react 2014年横空出世,以其革命性的写法,带动了前...

    一粒小麦
  • 闲话react路由守卫

    老外做生意的思路和中国人不太一样,中国人喜欢便宜货,比如说买相机,期望什么都给你配好,还附送一大堆东西。而老外发给你的货干干净净,所谓贵的要命名牌也只不过是廉价...

    一粒小麦
  • React 深入系列3:Props 和 State

    文:徐超,《React进阶之路》作者 授权发布,转载请注明作者及出处 ---- React 深入系列3:Props 和 State React 深...

    iKcamp
  • 41. Vue组件传值-父组件向子组件传值

    前面写了组件的创建、切换等等篇章,主要讲述了组件自身如何在父组件app中如何渲染使用。这里存在一个问题,就是父组件的数据如何传递到子组件中。

    Devops海洋的渔夫
  • react --- React中state和props分别是什么?

    组件从概念上看就是一个函数,可以接受一个参数作为输入值,这个参数就是props,所以可以把props理解为从外部传入组件内部的数据。由于React是单向数据流,...

    小蔚
  • React之父子组件传递和其它一些要点

    react是R系技术栈中最基础同时也是最核心的一环,2年不到获取了62.5k star(截止到目前),足可见其给力程度。下面对一些react日常开发中的注意事项...

    牧云云
  • [译] 更可靠的 React 组件:单一职责原则

    原文摘自:https://dmitripavlutin.com/7-architectural-attributes-of-a-reliable-react-c...

    江米小枣
  • React 总结初稿一

    18 年转眼即逝,不同寻常的一样。这一年我毕业了,入坑前端。工作只用 vue ,自己又学了 react , TypeScript ,小程序,这些在工作中从未用到...

    sunseekers
  • Flutter最佳入门方式:写一个计算器

    工作以来,我在学习新知识的时候,常常与在应试教育阶段被传授的方法作斗争——把书本的内容100%复制到脑中才算学会吗?不会被使用或者不常用的知识,花费大量功夫去记...

    用户1269200

扫码关注云+社区

领取腾讯云代金券