厌倦了编写活动页面?快来获取页面构建器吧!
时间:2023-04-02 19:58:00
HTML
前言如果你经常接触一些公司的活动页面,你可能经常会遇到以下问题:这些项目周期短,需求频繁,迭代快,技术要求低,成长空间小。但是,我们仍然在马不停蹄地逐一追赶产品的需求。随着公司规模的扩大,我们不能无限制地增加人力,不断重复这些活动。这里就不介绍一些具体的概念了,因为要介绍的概念太多了,作为前端的我们,直接写代码就好了!!!!如果想了解更多,欢迎访问:源地址blogsGoal我们的目标是实现一个页面制作后台,在后台我们可以为页面选择组件-->布局样式调整-->在线发布-->编辑并修改这样的流程操作。架构设计首先是提供组件供用户选择,然后我们需要一个组件库,然后我们需要调整所选组件的布局样式,所以我们需要一个页面编辑后台,然后我们需要渲染编辑后的输出数据进入真实页面,所以我们需要一个节点服务和一个模板模板来填充。发布上线。这直接连接到每个公司的内部发布系统。我们不会在这里详细说明。最后一个编辑功能是修改配置,所以我们需要一个数据库,这里我选择使用mysql。当然你也可以顺便做权限管理,页面管理……等等。扯了这么久,先画个图了解下大概流程:打开组件实现首先我们来实现组件部分,因为组件关联的是后台编辑的预览和最终发布的使用。组件设计我们应该尽量保持组件对外的一致性,这样我们在渲染的时候就可以对外提供统一的数据接口。这里我们的技术选型是基于Vue的,所以后面的代码部分也是以Vue为主,但还是一样,其他语言也类似。根据上图,我们的组件会被一个一个拆分出来发布到npm仓库中。为什么要这样设计?其实我之前也考虑过设计一个组件库,所有的组件都包含在一个组件库中,这样只需要发布一个组件库包,使用的时候可以按需加载。后来在实践过程中,发现这样不适合协同开发。其他前端如果要贡献组件,接入的改造成本也很高。比如:小明在自己的业务中写了一个Button组件。该组件经常被其他项目重用。他想把这个组件贡献给我们的系统,供模板使用。如果是组件库,他必须先Pull我们组件库的代码,然后按照组件库的标准格式提交。这样一来,懒惰的小明未必愿意这么做。最酷的方法当然是在本地构建一个npm库。我们不关心我们是用TypeScript还是其他的进行开发,我们也不关心我们选择的Css预处理器。我们不关心,甚至不关心编码标准的ESLint。最后只传编译好的文件。这避免了组件库的约束。依托NPM完善的release/pull和版本控制机制,让我们少做一些额外的工作,快速搭建平台。说了这么多,那代码呢?,我们以一个Button为例,我们提供这样的外部组件:{{data.context}}
可以看到我们对外只暴露了一个props。这种方式的好处是可以统一组件暴露的数据,组件内部可以随心所欲的发挥。注意这里我们还可以引入一些第三方的组件库,比如mint-ui之类的。后台编辑的实现在写代码之前,先考虑一下需要实现哪些功能:属性编辑区,为用户提供编辑组件内部props的功能;一个组件选择区,允许用户选择他们需要的组件;组件预览区,功能编辑区的实现,为用户提供拖拽排序页面预览为了方便,我们先实现组件的属性编辑功能。我们需要考虑组件公开哪些可配置信息。如何将这些可配置信息同步到后台编辑区供用户编辑,一个按钮的可配置信息可能是这样的:如果把这些配置都写在后台库里,根据当前选择的组件加载不同的配置,维护会比较麻烦,而且随着组件的增多,会变得臃肿,所以我们可以把这些配置存储在服务端,后台只需要按照存储的规则解析即可。例如,我们实际上可以这样存储编辑配置:[{"blockName":"按钮布局设置","settings":{"src":{"type":"input","require":true,"label":"按钮文案"}}}]我们在编辑后台,通过接口请求这些配置,然后我们就可以渲染规则了:/***根据类型,选择创建对应的组件*@param{VNode}vm*@returns{any}*/createEditorElement(vm:VNode){letdom=nullswitch(vm.config.type){case'align':dom=this.createAlignElement(vm)break;case'select':dom=this.createSelectElement(vm)中断;case'actions':dom=this.createActionElement(vm)break;case'vue-editor':dom=this.createVueEditor(vm)中断;default:dom=this.createBasicElement(vm)}returndom}组件选择区首先我们需要考虑一下,组件如何注册?因为组件是用户使用的在选择的时候,我们需要渲染组件,所以我们可以提供一个节点脚本来遍历需要的组件,并安装和注册组件://定义渲染模板和路径varOUTPUT_PATH=path.join(__dirname,'../packages/index.js');console.log(chalk.yellow('Generatingpackagereferencefile...'))varINSTALL_COMPONENT_TEMPLATE='{{name}}';varIMPORT_TEMPLATE='import{{componentName}}from\'{{name}}\'';varMAIN_TEMPLATE=`/*由'./compiler/build-entry.js'自动生成*/{{include}}constcomponents=[{{install}}]constinstall=函数(Vue){组件。map((component)=>{Vue.component(component.name,component)})}/*伊斯坦布尔忽略if*/if(typeofwindow!=='undefined'&&window.Vue){install(window.Vue)}export{install,{{list}}}`;//渲染参考文件vartemplate=render(MAIN_TEMPLATE,{include:includeComponentTemplate.join(endOfLine),install:installTemplate.join(`,${endOfLine}`),version:process.env.VERSION||require('../package.json').version,list:listTemplate.join(`,${endOfLine}`)});//写引用fs.writeFileSync(OUTPUT_PATH,模板);最终呈现的文件如下所示:})}/*istanbulignoreif*/if(typeofwindow!=='undefined'&&window.Vue){install(window.Vue)}export{install,WButton}这也是组件库常用的写法,所以这里的想法是将发布在npm上的组件聚合起来,聚合成一个组件包引用。当我们在后台编辑时,我们需要将它们全部导入:import*asW_UIfrom'../../packages'Vue.use(W_UI)这样我们的组件就注册好了。组件选择区主要提供组件的选项。我们可以遍历组件,提供一个列表供用户选择。当然,如果我们每个组件只提供一个组件名,用户可能不知道这个组件长什么样子,所以我们最好提供一个组件长什么样子的缩略图,这里我们也可以在组件时使用节点脚本发行了。这里要实现的代码很多,所以我就大致说一下流程,因为不是核心逻辑,是可选的,只能说体验会更好:用户开启dev-server使用ChromeToolpuppeteer编写代码和测试服务器脚本,将页面调整为手机模式,并对当前的dev-server进行截图。生成截图文件,上传到节点服务,关联组件。这样就可以在加载组件选择区的时候给组件附加一个缩略图。组件预览区当用户在选择区选中一个组件,我们需要在预览区显示出来,那么我们怎么知道用户选中了哪些组件呢?总不能把所有的组件都预先写进渲染区,用v-if判断选区吧?当然没那么傻,Vue已经提供了动态组件的功能:data">
为什么我们不用缩略图来代替真实的组件呢?一方面,生成的缩略图大小有问题。另一方面,我们需要编辑联动,即编辑区的编辑需要及时反馈给用户。附加问题说了这么多,好像一切顺利,但是在实践中,我们发现了一个明显的问题:我们中间的预览区其实是为了尽可能模拟移动端页面的效果。但是如果我们添加一些包含类似position:fixed样式的组件,我们会发现样式存在明显的问题。典型的如DialogLoading等。所以我们参考了m-ui组件库的设计,将中间预览操作容器展示为iframe。将iframe的大小调整为375*667,模拟iPhone6的移动端,这样就不会有样式问题了。但是这样又产生了一个难点,就是左边的编辑数据如何及时的反映到iframe中呢?没错,就是postMessgae。大致思路如下: