博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React组件设计模式(一)
阅读量:7230 次
发布时间:2019-06-29

本文共 3928 字,大约阅读时间需要 13 分钟。

完整代码可查看,这里截取的代码不影响理解就行。

页面效果可查看

首先编写一下我们的公共组件

单个商品组件(商品组件:展示价格、购买数量)

goodsItem.js

// 单个商品import React from 'react';const GoodsItem = props => {  const { goods: {name, num, price}, handleSub, handleAdd } = props;  return 
{name}
{num}
价格:{price}
};export default GoodsItem;

商品列表组件(循环展示库中的商品)

goodList.js

// 商品列表import React from 'react';import GoodsItem from './goodsItem';class GoodsList extends React.Component {  constructor(props) {    super(props);    this.state = {      goodsData: []    }  }  componentDidMount() {    const { goodsData } = this.props;    this.setState({ goodsData: goodsData});  }  handleAddorSub(id, type) {    let { goodsData } = this.state;    let newGoods = goodsData.reduce((newData, goods) => {      if (goods.id === id) {        goods.num = type === '+' ? goods.num + 1 : goods.num - 1;      }      newData.push(goods);      return newData;    }, [])    this.setState({ goodsData: newGoods })  }  render() {    const { goodsData } = this.state;    return (      
{goodsData.map(goods =>
this.handleAddorSub(goods.id, '+')} handleSub={() => this.handleAddorSub(goods.id, '-')} /> )}
); }};export default GoodsList;

我们一般编写组件,都会这么去做,list包裹item,循环展示item。数据放在list组件中,item作为一个无状态组件,只做他的展示。

数据交互通过props传递,点击+-会改变购物车里的数据。

现在需求来了,双12来了(就在昨日),所有商品8折优惠。

这意味着我们需要修改goodsData中所有商品的价格。

这并不难,我叶良辰有100种方法可以修改商品数据。找个可行的生命周期,比如componentDidMount中修改list组件state.goodsData就行了。

如果每次修改都直接修改goodList组件,也是可以的,大不了多传几个props来判断需要打折还是修改商品名称等等。

但是有些需求是交叉的,如果一直这样写,久而久之组件会变得越来越臃肿,最后爆炸。

好的解决方案应该是goodsList不去动他,外加一层来进行包装,实现我们的逻辑。

这样既保证了goodsList的,又能实现逻辑的复用。可谓一箭双雕。

用两种组件设计模式可以帮助到我们。

一. renderProps 模式

renderProps其实是利用组件的props.children api,将函数当成组件的一种写法。

我们调用公共组件的方法如下:

我们用renderProps模式实现打折商品组件:

{(data) =>
}

可以看到,DiscountedGoodsList的子组件是一个函数,那么一个函数是怎么渲染成组件的?

再来看看DiscountedGoodsList组件的代码:

const DiscountedGoodsList = props => {  // 8折优惠逻辑  const setRenderPropsData = (data) => {    let renderPropsData = data.reduce((array, goods) => {      let obj = {};      for (let k in goods) {        obj[k] = k === 'price' ? (goods[k] * .9).toFixed(2) : goods[k];      }      array.push(obj);      return array;    }, []);    return renderPropsData;  }  let goodsData = setRenderPropsData(props.goodsData);  return (    
{props.children(goodsData)}
);}

setRenderPropsData的作用是实现8折优惠逻辑,将所有商品价格调整。

然后调用props.children这个api,得到在上面我们编写的函数。

props.children也就是函数(data) => <GoodsList goodsData={(data)} />的引用。

将处理后的数据goodsData作为参数执行,最终返回<GoodsList />组件,这就是renderProps模式。

以后我们需要调用价格优惠的商品列表组件,直接调用DiscountedGoodsList即可。

renderProps的模式实现了逻辑的共用,且对GoodsList组件毫无副作用,从而达到我们的目的。

二. HOC(高阶组件)模式

所谓的高阶组件,其实就是一个函数,该接受component为参数,返回一个处理后的component。

编写我们的高阶组件如下:

const BrandGoodsList = (Component, goodsData) => {  // 8折优惠逻辑  const setRenderPropsData = (data) => {    let renderPropsData = data.reduce((array, goods) => {      let obj = {};      for (let k in goods) {        obj[k] = k === 'name' ? goods[k] + '【品牌】' : goods[k];      }      array.push(obj);      return array;    }, []);    return renderPropsData;  }  let brandGoodsData = setRenderPropsData(goodsData);  return 
}

BrandGoodsList组件的逻辑就是给商品名称加上【品牌】的标示,区分商品。

高阶组件的调用比较简单:{BrandGoodsList(GoodsList, goodsData)} 直接执行返回组件,然后渲染。

实现了两种模式,现在我们将他们一起用,实现一个既打折,又是品牌商品的组件。

{(data) => BrandGoodsList(GoodsList, data)}

挺舒服的吧,随时分离,随时结合。正是高内聚、低耦合本人啊。

最后,完整的调用看一下:

基本商品列表组件:
打8折商品列表组件(renderProps模式实现):
{(data) =>
}
品牌商品列表组件(高阶组件模式实现): {BrandGoodsList(GoodsList, goodsData)}
既是打折商品,又是品牌商品(两种模式复用)
{(data) => BrandGoodsList(GoodsList, data)}

总结:

1、renderProps 模式的核心是props.children的使用。

2、高阶组件的写法看起来更舒服,比较受欢迎。

3、两种模式解决的问题:复用逻辑、不污染底层组件。

觉得有帮助的点个赞,甚至可以关注一波哦~

转载地址:http://gkcfm.baihongyu.com/

你可能感兴趣的文章
Delphi listview 点击列头排序
查看>>
android preference page
查看>>
mysql索引挑选
查看>>
关于冰岛足球的段子
查看>>
在 Windows 中安装 Laravel 5.1.X
查看>>
TeamViewer 9发布-在Linux下安装运行
查看>>
Centos7 Gitea安装教程 - 一款易搭建,运行快的Git服务器
查看>>
CentOS minimal 网络配置
查看>>
Nginx架构
查看>>
为什么结构体中的数组不能用const int变量指定大小?
查看>>
模板特化疑问
查看>>
ruby多线程理解
查看>>
享用甜点时要不要来杯咖啡?Java 与树莓派 (Raspberry PI)
查看>>
精通Oracle 10g Pl/SQL编程
查看>>
邱怡轩:R中大规模矩阵的SVD与矩阵补全
查看>>
C++ Primer习题集(第5版)
查看>>
centos7 mysql 5.7 yum安装
查看>>
JSOUP简单应用
查看>>
Mysql,SqlServer,Oracle主键自动增长的设置
查看>>
开源 java CMS - FreeCMS2.3会员登录
查看>>