本篇文章参考以下博文
前言
我们开发的过程中,如何能提高开发效率?这是一个合格程序员始终都要考虑的问题,在前段时间的开发过程中,发现同事们在代码提交的时候,总会或多或少的有一些代码冲突,由于公司是使用的 SVN 进行代码管理的,要迁移到 Git 的话成本太高,所以就思考,有没有什么方法能够避免掉这个冲突,修改又不用很大?
结合以前的项目,配置路由的时候,把所有页面的入口引入到一个配置文件中,路由在匹配入口的时候,也从配置文件中读取,这样解耦各个页面之间的功能。
借鉴这个思路,组件之间应该也可以实现类似这种模式。
页面样例
举个例子,我们需要实现下面这样一个页面。
由于页面功能比较复杂,整个页面被划分为四个模块 A, B, C, D ,分别交给四个开发来完成,理想很美好,大家各自开发各自的模块,互不影响,但是当 A, B 页面都需要修改父组件的某些功能的时候,就很容易出现代码冲突。
按照上面的配置文件的思路,我们这样来配置 config 文件。
import ComponentA from './ComponentA';
import ComponentB from './ComponentB';
import ComponentC from './ComponentC';
import ComponentD from './ComponentD';
export BaseInformation = {
A: {
href: '#html_A',
title: 'title_A',
className: 'class_A',
component: ComponentA,
},
componentList: [
{
href: '#html_B',
title: 'title_B',
className: 'class_B',
component: ComponentB,
},
{
href: '#html_C',
title: 'title_C',
className: 'class_C',
component: ComponentC,
},
{
href: '#html_D',
title: 'title_D',
className: 'class_D',
component: ComponentD,
}
]
}
上面代码中,我们可以看到,当各个开发人员完成组建后,引入到这个配置文件即可。
解释下上面的思路:
- href :为组件的路径,为了方便锚点定位识别
- title :组件标题
- calssName :组件唯一类名
- component :组件
这里解释下为什么 BaseInformation 里面要分成 A 和 componentList 两个属性,而不是 A,B,C,D 四个。主要是页面组成导致我们配置需要灵活变化,样例的页面可以分为左右结构,左边是 A 组件,右边三个按顺序排列的组件,为了遍历方便,我们可以把右侧的三个组件直接放到数组中,遍历数组完成组件渲染。
下面是父组件引入的时候,正对配置文件的一些编码:
import { BaseInformation } from './config'
function Father(props) {
return (
{/* 左侧 A 组件 */}
{
<BaseInformation.A.component />
}
{/* 右侧 B,C,D 列表 */}
<div>
{
BaseInformation.componentList.map(item => {
return (
<item.component id={item.gref} className={item.ClassName} key={item.id} />
)
})
}
</div>
)
}
代理目的
这样我们就完成了,父对子的一层代理,这个时候有的同学可能会疑问,为什么要增加这一次层代理,直接引入不香嘛?
我们直接引入第一,不方便查找,通过这种代理引入,我们可以很清晰的查看到每个组件的位置。我们平时在开发过程中,总需要消耗一段时间去熟悉项目中组件间的关系,尤其是接手别人的项目的时候,这种方式可以让我们快速理清组件间的相互关系。
第二,可以解决一部分样式泄漏问题,代理的配置文件是由一个人进行配置的,那么可以保证类名不重复。
第三,大家开发完组件后,只需要引入到这个 config 文件中即可,每个组件都是独立的,这样会大大降低代码冲突的问题,从而提高开发效率。各个模块的开发人员不需要了解模块是怎么被引入到页面的,不需要修改父组件。
由于使用的配置文件的形式,组件间的耦合降低了,那为了确保通信,我们需要使用一个状态管理容器,比如 Redux 。
当然了上面的引入方法只是一个简易的实现,我们还可以通过对配置文件的层级进行划分,明确出组件间的树形关系。比如下面这种形式:
export BaseInformation = {
father: {
href: '#father',
title: 'title_father',
className: 'class_father',
component: ComponentFa,
chlidren: [
{
href: '#html_son',
title: 'title_son',
className: 'class_son',
component: ComponenSon,
},
]
},
}
这种方式可以直观的查看到,组件的嵌套关系。
当然了,配置文件如果这样写,只能由划分组件的人那个人进行设置,这样缺少些灵活性,我们可以借鉴 qiankun 微前端框架。使用形式类似下方这种模式。
import { loadMicroApp } from 'qiankun';
/** 手动加载一个微应用 */
const microApp = loadMicroApp(
{
name: "microApp",
entry: "https://localhost:7001/micro-app.html",
container: "#microApp"
}
)
// 手动卸载
microApp.mountPromise.then(() => microApp.unmount());
上面是 qiankun 的引入和使用方式,是不是我们配置文件的一些信息及其相似,我们可以把刚才的代理封装一下,让它可以灵活的手动添加和卸载相应的组件,那这样我们在控制某个组件的显示隐藏时,不需要再新增一个变量来控制它的显示与否了。在任何地方,只要你喜欢,就可以随意控制任何组件的挂载。
具体实现的方式,请关注我的后续博客,里面会对封装方法,进行详细描述,或者各位同学可以参考 qiankun 的封装模式,大部分封装手段借用了其中的思想。