React设计模式(第 2 部分)
这一次,我们将讨论模式、模式和模式。Context``````Presentational and Container Components``````Compound Components
上下文
根据React文档:
上下文提供了一种通过组件树传递数据的方法,而无需在每个级别手动传递道具。
简单地说,如果您有一个需要通过多个组件级别的全局状态,可以使用 。例如:如果您有一个会影响所有组件的组件,将简化该过程。Context``````theme``````Context
**注意。**使用时有一个潜在的障碍需要牢记:它可以降低组件的可重用性。数据将在作用域中可用,因此不能在 外部使用它。我找到了一个很棒的视频来解释这个问题, 并告诉你如何避免 “道具钻探” 。Context``````Context``````Provider``````Provider
让我们看一个上下文在行动的示例:
import React, { useContext, createContext } from “react”;
import “./styles.css”;
let data = {
title: “Welcome”
};
const Context = createContext();
export default function App() { return ( <Context.Provider value={data}>
const Card = () => { return (
const CardItem = () => { return (
const Title = () => { const data = useContext(Context); return
{data.title}
; };
正如我们在这个(基本)示例中看到的,我们有三个级别的组件,并且我们只使用最后一个级别的 。这样,我们不需要把道具传递给所有级别。data.title
有关上下文语法的一些提示
使用上下文时,我总是应用此语法。然而,当我再次写的时候,我发现一些事情:
- 在"静态数据"(如示例)中,我们实际上不需要 。我们可以自己履行这一职能:
Provider
let data = {
title: “Welcome”
};
const Context = createContext(data);
export default function App() { return (
在比例的另一端,我们可以使用 而不是 , 像这样:Customer``````useContext
const Title = () => {
return (<Context.Consumer>
{(data) =>
{data.title}
}
</Context.Consumer>);
};
演示和容器组件
这些组件(也称为 )是最著名的React模式之一。React 文档中没有引用它们,但 Dan Abramov 的文章提供了出色的指南。Smart And Dumb Components
简单地说,请参阅业务逻辑组件与 UI 视图的分离。Presentational And Container Components
让我们看看另一个场景:
- 我们需要构建一个组件。
Card
- 在卡内,我们还有三个其他组件: 和 。
Title``````Image``````Button
- 单击后,该按钮将更改图片。
在开始处理组件之前,让我们创建两个文件夹:“演示"和"容器”。现在,让我们构建三个组件:Presentational
标题.js :
import React from “react”;
export default function Title(props) {
const { children, …attributes } = props;
return <h1 {…attributes}>{children};
}
图片.js :
import React from “react”;
export default function Image(props) {
const { src, alt } = props || {};
return ;
}
按钮.js :
import React from “react”;
export default function Button(props) {
const { children, …attributes } = props;
return <button {…attributes}>{children};
}
最后,我们可以在容器文件夹组件中生成,称为 。Card
卡.js :
import React, { useEffect, useState } from “react”;
import Title from “../Presentational/Title”;
import Image from “../Presentational/Image”;
import Button from “../Presentational/Button”;
export default function Card() { const [card, setCard] = useState({}); const [srcIndex, setSrcIndex] = useState(0);
useEffect(() => { setCard({ title: “Card Title”, image: { imagesArray: [ “https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTh87QN4DkF7s92IFSfm7b7S4IR6kTdzIlhbw&usqp=CAU”, “https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRjFnHdaH1i1m_xOaJfXTyq4anRFwRyCg1p1Q&usqp=CAU” ], alt: “card image” } }); }, []); const { image } = card; const changeImage = () => setSrcIndex((index) => index < image.imagesArray.length - 1 ? index + 1 : index - 1 ); return (
如果您想查看完整的代码,请在此处查看。
**注意!**你们很多人可能想知道为什么需要分成不同的组件。你可以把它们写在里面,对吗?Card
当我们分离组件时,我们可以在任何地方重用它们。但更重要的是,实现其他模式(如 或 )要容易得多。HOC``````Render Props
复合成分
在我看来,这是最复杂的模式之一,要理解,但我会尽量简单地解释它。
当我们谈论 时,最简单的方法是思考和使用HTML。您可以将它们视为具有基本功能的一组组件。有些状态是全局(如在模式中)或从容器(如模式)管理的。Compound Components``````select``````option``````context``````presentational and container
**复合成分
**是这两者的混合体。这几乎就像他们每个人都有自己的状态, 他们从内部管理他们。
让我们看看下一个场景:
- 我们需要开发和组件。
Select``````Option
- 我们希望生动,不同的颜色。
Option
- 颜色会影响颜色。
Option``````Select
让我们看看示例:
应用程序.js
import React from “react”;
import “./styles.css”;
import Select from “./Select”;
import Option from “./Option”;
export default function App() { return (
- 渲染 和 组件。
App``````Select``````Option
Option.Blue
是"颜色组件"。Option.Red
选项.js
sdsdimport React, { useEffect } from “react”;
function Option(props) { const { children, style, value, setStyle } = props; useEffect(() => { if (setStyle) setStyle({ backgroundColor: style.backgroundColor }); }, [setStyle, style]); return ( ); }
Option.Blue = function (props) { props.style.backgroundColor = “blue”; return Option(props); };
Option.Red = function (props) { props.style.backgroundColor = “red”; return Option(props); }; export default Option;
- 在这里,您可以看到 和 的实现。显而易见,我们渲染组件,只需向道具添加属性。
Option.Blue``````Option.Red``````Option
- 来自 。它用于将所选颜色更改为所选选项的颜色。
setStyle``````Select
选择.js
import React, { useState } from “react”;
export default function Select(props) { const { children } = props; const [style, setStyle] = useState({});
const findOptionActive = (e) => { const index = e.target.value * 1; const optionStyle = { …e.nativeEvent.target[index].style }; if (optionStyle) setStyle({ backgroundColor: optionStyle.backgroundColor }); };
const childrenWithProps = React.Children.map(children, (child, index) => { return React.cloneElement(child, { …child.props, value: index, setStyle: index === 0 && Object.keys(style).length === 0 ? setStyle : null, style: { backgroundColor: “white” } }); });
return ( ); }
- 现在,我们有一个具有 属性的 select 函数。
onChange``````style
findOptionActive
获取选项的样式并相应地更改选择的样式,- 魔法真的发生在.通常,当收到时,我们无法访问儿童道具 - 但在的帮助下,我们能做到。正如你所看到的,我们可以通过 , 和 作为道具.
childrenWithProps``````Select``````children``````React.Children``````React.cloneElement``````value``````setStyle``````style
要获取完整代码,请单击此处。
- 原文作者:知识铺
- 原文链接:https://geek.zshipu.com/post/react/save01/React%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%AC-2-%E9%83%A8%E5%88%86/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com