基于react的组件库主题设计方案_第1页
基于react的组件库主题设计方案_第2页
基于react的组件库主题设计方案_第3页
基于react的组件库主题设计方案_第4页
基于react的组件库主题设计方案_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基于react的组件库主题设计方案基于react设计与开发的组件库主题方案,以HippyReact主题方案设计为例需求背景单一的视觉不再满足用户体验需求,为提高用户体验,提高应用体验口碑,同时提高开发者效率,我们希望提高组件库的可定制化,因此提供换肤功能以及多种类组件中的样式定制功能,允许用户将应用切换不同主题风格的皮肤,也允许开发者对指定组件进行样式改造。设计目标性能一个方案的落地前提得有性能的保障,不重新初始化视图,避免出现闪屏、卡顿等性能缺陷现象,同时也要保障功能稳定,不能存在部分组件不按预期切换主题现象。可维护性组件库需不断迭代完善,应避免过多的条件判断,避免在单个组件上有过多的主题特殊逻辑,主题的设置和组件的实现应解耦,保证后续可维护可扩展。可配置可配置分为两部分,一部分为可配置任意全局统一的样式变量,或者某个组件的局部样式;另一部分为强制模式,即指定部分组件不跟随主题变化而变化,保留着本身一种样式。易用性提供快捷接入主题的接口,降低学习成本和时间成本。粒度细分组件层面的主题定制、整套组件库的主题定制。开发者可以修改全局样式,比如更换全局中字号的字体大小,也可以局部修改样式,比如按钮组件A的边框颜色。样式提取暴露出提取当前整套样式的接口,方便开发者提取指定样式做二次操作。比如开发者需要提取当前主题颜色作为视图背景色,可从组件库中获取。样式可定制内容,包括但不限于:颜色:品牌色、默认背景色、通用背景色、基本文本颜色、辅助文本颜色、链接色文本:文本大小,字重,字体间距等按钮:圆角大小,按钮尺寸,边框尺寸等图片:图片尺寸,圆角大小等技术选型主题定制是大多数组件库都会提供的一个核心样式相关的功能,技术选项上需要考虑的两点:如何生成一份全局样式配置表组件如何获取样式配置表针对以上两点,我们做了一些分析:如何生成一份全局样式配置表目前各类组件库最常用的是以下两种方案:借助gulp/webpack等打包工具相关的插件,配置需要定制的样式变量,在打包时覆盖对应变量值。重写样式,覆盖样式配置表,生成新的全局样式配置表。在我们实现的hippy-react-ui中我们并没有提供打包的能力,而是把这部分移交到业务侧处理,原因是现在大部分业务发布时都会对业务进行打包处理,业务侧可能灵活设置打包配置内容,而不受限于组件库打包,另一方面是让业务侧使用组件时可以快速定位组件内部结构,方便排查使用过程中遇到的问题。因此我们选用了以上第二种方案,提供一份默认的样式配置表,而业务侧可以写入重新样式对其覆盖。组件如何获取样式配置表组件库是基于hippy-react设计开发的,hippy-react提供的数据的传递有两种:通过props属性自上而下(由父及子)进行传递Context提供了一种在组件之间共享值的方式,不必显式地通过组件树的逐层传递props第一个方案使用简单,只需要将样式从根节点往下一层层传递即可,但它的缺点也是需要一层层传递。我们的组件库中,复合组件很多,比如列表组件中用到了按钮组件,按钮组件中用到了文本组件,这要求每个组件都需要获取一遍props再往下传递,不仅加大开发成本,对影响了后续开发的可维护性。而第二个方案,我们只需要使用context提供主题的提供者和消费者,在需要使用主题的组件中注入即可,但它有个缺点:每次更新context的内容,都会将所有消费到主题的组件重新更新一遍。而针对context的缺点,我们可以放下这个顾虑,因为主题本身也是只消费一遍,在切换主题的时候进行消费,而不是高频的去使用。因此组件获取样式配置表是通过context的方式进行获取。设计方案通过上面技术的选型,我们确定了两点:重写样式,覆盖样式配置表,生成新的全局样式配置表组件通过Context提高的组件之间共享值的方式,获取样式配置表生成样式配置表以上是生成全局样式表的过程,在讲解流程前需补充说明上图中深色/浅色主题:组件库内置两份主题色,主题的切换主要是颜色部分的切换,提供两种主题的原因是我们尽可能通用化配色,比如以下几个例子,背景色/背景图片我们可以随意替换,但作用在其之上的内容,简单分为深/浅两种方案基本可以适用到大部分场景。样式优先级组件库自带的样式分为三部分:跟主题相关的深色主题和浅色主题,还有与主题切换无关的其他样式,在业务侧未指定主题时,组件库默认使用浅色主题的颜色配置表+其他可配置的默认样式值,如字体大小,字重等,业务侧可以重写样式,最终生成的样式表作为提供者Provider给到各个组件使用。我们暴露一个属性value={}给业务侧赋值给组件库,业务侧可以在对象中传入指定的主题,比如value={theme:"light"}或者value={theme:"dark"},我们提供一个便利,业务侧可以直接传入value="light"或value="dark"。如果希望针对某个样式值进行重写,可以value={textBaseColor:"#555555"}。在组件库中,我们根据业务侧传入的自定义内容进行判断且合并成新的样式配置表:functiongetStyle(style){if(style==="light"){returnuseTheme(lightStyleSheet);}elseif(style==="dark"){returnuseTheme(darkStyleSheet);}else{constthemeStyle=style&&style.theme==="dark"?darkStyleSheet:lightStyleSheet;returnuseTheme({...themeStyle,...style});}};该函数中style即为业务侧传入的value,首先判断style是否为主题(light/dark),是即返回对应主题表。useTheme是一个合并样式的方法,参数是样式对象。functionuseTheme(args={}){returnObject.assign({},defaultStyle,args);}可以看到这个方法只是一个合并的操作,defaultStyle指向了默认的样式表。Context传递共享值以上为样式合并的过程,接下来我们需要将样式配置表作为样式提供者(Provider)传递到各个消费者(consumer)各个组件中。Context提供了一个无需为每层组件手动添加props,就能在组件树间进行数据传递的方法。提供主题的Provider(提供者)和Consumer(消费者),我们通过React.createContext()创建上下文,使得Provider和Consumer可以接收和获取同一信息。constThemeContext=React.createContext(defaultTheme);Provider:用于接收主题和样式参数,并与默认样式合集、深/浅色主题样式合并。如上文所提到的,我们允许给组件传入指定主题变量:"dark"或者"light",也允许传入自定义样式对象,如:{hiColorTheme:"#666666"},下图展示样式获取过程,根据优先级(用户自定义样式>用户自定义主题>默认主题)会生成一份配置表,而我们所有允许定制的样式,样式属性值均从配置表获取。//ThemeProvider:将样式合集写入value提供给消费者constThemeProvider=(props:ThemeProviderProps)=>{letstyle=getStyle(props.value);return<ThemeContext.Providervalue={style}>{props.children}</ThemeContext.Provider>;};Consumer:用于获取样式合集并提供给子组件Consumer获取到的样式合集作为生成子组件的函数参数,这就要求子组件是以函数的方式获取样式合集,后面如何使用中会对应介绍,如下classThemeConsumerextendsReact.Component{render(){return(<ThemeContext.Consumer>//children是一个函数,而非组件{style=>{returnps.children(style);}}</ThemeContext.Consumer>);}}组件接收样式表如上图,我们将Provider包围在最外层,建议在根节点使用,根据需要也可包裹置于局部组件。在Provider中的任意Consumer均可获取到同一份样式表,当Provider更改自定义值时,在任意订阅的地方均可以获取到最新样式表,从而更新节点。在根节点使用Provider,并引入自定义样式或者指定主题<Providertheme={{theme:"dark",defaultFontSize:18}}><HiText/><HiList/></Provider>Text组件<Consumer>{(themeStyle)=>{return(<Textstyle={{fontSize:themeStyle.defaultFontSize}}>Text组件</Text>);}}</Consumer>List组件<Consumer>{(themeStyle)=>{return(<View><Textstyle={{fontSize:themeStyle.defaultFontSize}}>List组件</Text><HiText/></View>);}}</Consumer>强制模式强制模式即当用户切换主题时,该模式下的组件不会跟随主题变化。何时会使用到该模式呢?例如上图,是在浅色主题下的展示,但蓝框中因为有固定的背景图存在,我们不希望它跟随主题色切换文本颜色,而是固定为深色模式下的浅色文本颜色,就需要用到强制模式让它主题固定下来。

强制模式的实现是采用了拦截Provider传递给Consumer的方式,如下图:例如文本组件中使用了Consumer接收全局样式,但如果业务使用了Text组件,并赋予了主题属性,那么我们会将主题属性告知Consumer,在Consumer中,局部组件提供主题属性优先级高于Provider提供的主题属性值。renderChildren(style:any){letchildren=ps.children(style);if(children&&ps&&ps.theme){//判断局部逐渐是否传递了主题属性letpartStyle=getStyle(ps.theme);children=ps.children(partStyle);}returnchildren;}暴露样式表上文中提到主题的切换均作用于组件库中的组件,当业务不需要组件而需要获取样式表的内容进行其他操作时,我们需要给到业务侧当前的主题样式表,使得用组件库的业务可以做更多的界面统一。于是我们在主题Provider提供了一个静态变量,允许业务获取classThemeProviderextendsComponent<ThemeProviderProps>{staticstyleConfig:DefaultStyle;render(){conststyle=getStyle(ps.value);ThemeProvider.styleConfig=style;//暴露主题配置表......}}如何使用Provider引入使用:将Provider置于根节点上//app.js<Providertheme="dark"></Provider>theme属性使用定制主题theme可传入"dark"或者"light"<Providertheme="light"></Provider>定制样式theme可以重写样式表中默认的样式,如需修改默认字体中字号的大小<Providertheme={{hiFontSizeM:20}}></Provider>定制主题+定制样式<Providertheme={{theme:"dark",hiFontSizeM:20}}></Provider>全局定制背景色默认使用主题背景色。优先级:style属性>更改配置表定制背景色>默认主题背景色//更改配置表定制背景色:背景色使用的是样式表中的hiBgColor值<Providertheme={{hiBgColor:"#666666"}}></Provider>//style属性更改背景色<Providerstyle={{backgroundColor:"#666666"}}></Provider>强制模式importHiTextfrom"../HiText";<HiTexttheme="dark">default(Text28A)</HiText><HiTexttheme={{hiBgColor:"#666666"}}>default(Text28A)</HiText>获取样式配置表//引入ProviderletstyleConfig=Provider.styleConfig;重点问题解决兼容新旧SDK主题设计核心用到了hippy-react的Context,这是hippy-react2.0.3之后提供的API,针对SDK未升级的旧业务,我们需要兼容处理,避免报错。组件库采用的是判断版本号和检查是否有Context判断该版本是否支持主题切换constThemeContext=React.createContext?React.createContext(defaultStyle):null;constIS_SUPPORT_THEME=((HippyReact&&HippyReact.version&&versionCompare("2.0.3",HippyReact.version)))&&ThemeContext;对于低版本使用到主题功能的部分,我们同样需要给到指定的样式表Provider兼容方式:constThemeProvider=(props:ThemeProviderProps)=>{conststyle=getStyle(props.value);if(IS_SUPPORT_THEME){//支持主题切换,使用ContextAPIreturn(<View{...props}style={[{backgroundColor:style.hiBgColor||"#FFFFFF"},props.style]}key={style.type}><ThemeContext.Providervalue={style}>{props.children}</ThemeContext.Provider></View>);}else{//不支持主题切换,返回Provider下的children内容return(<View{...props}style={[{backgroundColor:style.hiBgColor||"#FFFFFF"},props.style]}key={style.type}>{props.children}</View>);}};Consumer兼容方式:classThemeConsumerextendsReact.Component<ThemeConsumerProps>{staticdefaultProps:ThemeConsumerProps={children:()=>{}

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论