在组内有多次分享过有关于React最佳实践的一些应用场景,发现效果比推荐阅读内容或枯燥的解释原理来得更好。所以决定也在博客中采用这种方式:文章结合实例开发。
目录
内容
React与乐高
乐高的特点:
- 有足够细致的基础部件
- 拼装组合的可能性也足够丰富
- 从小部件,不断拼搭,形成大单元
你记住这几点,用React去实现内容,其实也就是在做乐高。
- react为你提供了基础的jsx,它如同乐高这种介质
- react为你提供了各种钩子函数,以及jsx之间的组件语法,它就如同乐高的零件在拼接时的衔接方式
- react允许我们定义一个只包含文本的组件,也可以允许定义一个复杂的组件;他们可能有状态,有可能没状态,总之,它们是组件,由这些组件我们可以组建出更加复杂的应用。
create-react-app
有句话怎么说来着?一句命令一时爽,一直命令,一直爽。哈哈。开个玩笑。当然有些人也可能就只会这个命令。好吧,我们就从这个命令开始。
npx create-react-app calculator
我们从一个计算器开始创建。
不想写样式,偷个懒
接下来我们先从静态架子开始实现,先别管动态的内容如何实现。因为这个过程也能有助于你消化和理解如何更优的实现这个内容。
写静态内容肯定就会有涉及样式,那我就推荐些tailwindcss。这个原子样式编程,关键可以帮我省时间啊。
安装一下;npm install -D tailwindcss
初始化下配置,产生了tailwind.config.jsnpx tailwindcss init
- 修改下这个配置如下:
module.exports = { content: ["./src/**/*.{html,js}"], theme: { extend: {}, }, plugins: [], }
- index.css里面就写下面的内容即可
@tailwind base; @tailwind components; @tailwind utilities;
- 然后就可以使用了
<div className="bg-white"></div>
当然还有涉及使用font icon。 我这里以FontAwesome使用来说明。
- 先安装核心
npm i --save @fortawesome/fontawesome-svg-core
- 安装需要icon包
# Free icons styles npm i --save @fortawesome/free-solid-svg-icons npm i --save @fortawesome/free-regular-svg-icons
- 安装react相关
npm i --save @fortawesome/react-fontawesome
- 使用:
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faSun, faMoon } from '@fortawesome/fontawesome-free-solid'; <FontAwesomeIcon icon={faSun} /> <FontAwesomeIcon icon={faMoon} />
兵马未动,“拆解”先行
“拆解”什么呢?拆解你要实现的内容。先不用急着写代码,脑袋瓜子里面先全面的把要实现的内容拆解一遍。
拆解深刻的理解其实可以理解为相似内容的拆解,动与静的拆解,公有与私有的拆解。先别急,停顿片刻。仔细想想我为什么这样说……
相似内容的拆解: 提炼相似点,提升服用度
动与静的拆解: 为后续组件优化做好铺垫
公有与私有的拆解: 公共的内容需要提炼出来,全局控制。
现在我们开始拆解这个计算器把。
如上图:
- App.js 应用壳子
- segment 就是零件目录了
- Wrap.js 计算器壳子
- ThemeSegment.js 计算器设置主题的模块
- DisplaySegment.js 计算器的显示模块
- DisplayJit.js 计算器-计算内容
- DisplayResult.js 计算器-计算结果
- DisplayHistory.js 计算器-计算历史
- ControlSegment.js 计算器的输入模块
- KeyWrap.js 计算器中输入模块中的按键模块
可以清楚的看到我这样划分的用意。其中按照功能块划分为了以上一些模块,其中KeyWrap是会被多次服用copy为不同的按键。其他模块则只有一个。但各自的功能不同,各司其职。所以这样的拆解是有意而为之的。
梳理数据
我们前面完成了静态内容,接下来我们得着手数据流了。计算器的数据流该如何抽象呢?先想想我们要做的这个计算器会涉及哪些功能?
- 输入数字,符号,进行计算
- 通过显示屏展示出输入的内容,计算出来的结果
- 额外加入了一个皮肤主题切换的功能
那么我将它抽象为:
- 主题切换功能
- 计算器核心功能
那么一个个来剖析并实现。这里数据上我们先需要将数据进行理解,理解它们的属性,它们哪些是公共的,哪些是私有。
这里会涉及到全局数据,那么react中原生提供的相应能力就是context。当然你可能会说为什么不用redux之类的。不要忘记,我们现在是主要在于借助实践理解react,所以对于一些核心点,尽可能先从原生的api来使用。
所以我这里通过context来定义全局“数据流”, 为了方便引用,我统一将这类全局的数据流放在config.js中。
-
主题切换功能,公共属性。主题控件负责接受输入,产生相应数据,作用于全局中的各个组件中的颜色,当然也作用于主题控件自身的交互效果。
定义一个ThemeContext, 负责读写主题的值;
再定一个GetThemeColor, 根据当前主题的值产出具体的颜色值;
最后定义ThemeColorMap, 暗黑和纯白两套颜色值;//定义 const ThemeContext = createContext('theme') const ThemeColorMap = { bg:[" bg-white "," bg-black "], controlbg: [" bg-slate-100 ", " bg-slate-900 "], keybg: [" bg-slate-200 ", " bg-slate-950 "], text:[" text-gray-500 ", " text-gray-400 "], btnactive: [" text-black ", " text-white "] } const GetThemeColor = (type, theme)=>{ return ThemeColorMap[type][(theme==="light"?0:1)] } //赋值 const [ theme, setTheme ] = useState("light") <ThemeContext.Provider value={{theme,setTheme}}> ... </ThemeContext.Provider> //使用 const themeObj = useContext(ThemeContext); <div onClick={()=>themeObj.setTheme("light")} className="cursor-pointer mx-2" > <FontAwesomeIcon icon={faSun} className={classNames({ [GetThemeColor("btnactive", themeObj.theme)] : themeObj.theme === "light", [GetThemeColor("text", themeObj.theme)]: themeObj.theme !== "light" })}/> ... </div>
-
计算器功能,公共属性。输入数字,运算符,通过我们后续的将编写具体逻辑,将这些输入进行效果,然后产出结果。
先计算器定一个CalculatorContext,这个里面我们需要认真分析下,所需要涉及的读写内容。
//仔细分析计算器功能, 细化功能逻辑,则定义如下读写机制 //计算器运算,用于运算的,例如除以是 / const [ cInput, setCInput ] = useState("") //计算器运算显示,用于显示运算的内容,例如除以是 ÷ const [ cInputDisplay, setCInputDisplay ] = useState("") //计算器运算历史 const [ cHistory, setCHistory ] = useState([]) //计算器的输入栈。我们还需要一个输入的顺序记录**计算器的输入栈** const [ inputStack, setInputStack ] = useState([]) //包裹 <CalculatorContext.Provider value={{ cInput, setCInput, cInputDisplay, setCInputDisplay, cHistory, setCHistory, inputStack, setInputStack }}> <ThemeSegment /> <DisplaySegment /> <ControlSegment /> </CalculatorContext.Provider>
接下来就是
DisplayHistory上面用于显示历史
显示多少条历史呢?通过全局配置管理它,config.js里面加入一个HistoryNumDisplayJit, 显示需要运算的内容
DisplayResult, 显示运算的结果
可能运算内容存在执行时意外错误,catch一下。KeyWrap,输入键。这个里面承载的内容会最多。
- 它会被复用,按照不同的传入值,赋予不同的功能含义
- 它的不同功能,在被触发后,也需要提供相应的逻辑来应付整体的执行
因此它的内容就大致是2块内容,UI + 输入时每一步的核心逻辑。
UI:
输入时的逻辑:const clickBtnHandler = ()=>{ //每一步输入的核心逻辑。有兴趣后续可以自行查看源代码。 }
总结归纳
我们做了这个,实际上就主要应用到了以下几块内容:
- 组件化思维理解业务实现,时刻牢记,一切皆组件
- 如何引用tailwindcss
- 如何使用fontIcon
- context的使用
- useState
- useContext
以上的每个概念似乎都不困难。我们先从这个最简单的实例着手理解react的应用。各位慢慢细品。码字不易,各位按需自行阅读。
0 条评论