lowcode之H5可视化搭建项目

7,524 阅读6分钟

简介

技术栈

组件拖拽功能:

组件配置功能:

关于可视化搭建,可以看这篇文章:页面可视化搭建工具前生今世

1.目标群体

面向开发者和普通用户,快速生成H5页面。有时候低代码比无代码更能提高生产力,脱离“复制粘贴”式的组件复用。对运营人员来说可以快速搭建一个营销页面,对开发来说可以方便的添加、组合组件,结合少量代码去复用之前组件。

2.精准还原设计稿

大部分搭建出来的H5页面,都是采用px单位,更多的是面相普通用户,不讲究像素还原。如果按照现在流行的移动端H5适配方案,设计稿宽度750px,使用rem或者vw单位,页面在各个分辨率的屏幕下展示才一致。这里我们组件最小的粒度是block,开发人员按设计稿还原组件,并暴露出可配置项,像颜色、背景、文案这些,才是交给非开发人员配置的。同时也提供一些基础组件:图片、富文本、视屏等,同时支持搭建一个无需设计的简单页面。

3.友好的组件开发体验

大部分开源可视化项目着重于使用者体验,而物料开发部分则一笔带过。如果你使用过storybook,就会觉得下面组件开发部分跟它十分相似,甚至省去了编写props跟表单的映射代码,可以直接拖拽生成。当然storebook的设计是方便编写、组织、测试组件,项目中一些想法也借鉴了storebook。

4.产出页面体积、版本控制

达到线上标准而不是demo阶段,需要考虑诸如“组件更新后已发布页面该如何处理依赖的组件”。目前版本控制还未实现,主要考虑几种实现方式:

  • 每生成一个页面,结合ci触发H5基座的构建,单独为每个项目生成build文件,后续组件更新跟已发布的页面就毫不影响了。
  • 每次修改组件发版后,打上一个版本号保存在数据库,并发布到静态资源服务器上,对应页面用到的组件,按照版本号来拉取,也就类似npm包版本的概念
  • 完全把组件部分拆分开来,按照npm版本来发包,H5基座安装对应版本组件库,不过这种方式对于开发过于复杂。

技术要点

布局模式:自上而下的排列布局

通常还有一种绝对位置布局,虽然灵活度高但是不利于组件的组合扩展。这里设定最小的组件单元就是占据一行的块级元素,可以在它上面或下面添加组件,可以调整顺序,可以排列组合成更大的组件。

画布:使用iframe

组件单位使用vw,就注定了只能使用iframe。还好元素的drag、drop事件可以跨iframe,并且iframe不用我们去考虑沙箱机制来避免变量、样式的污染,尤其是搭建页面这种多人参与的项目。

iframe间通信可以通过PostMessage实现,这里推荐一个库postmate,能方便的使用异步promise来传递消息、方法调用。

技术点

下面通过如何开发、到使用一个登录领券的组件,来展示其设计思路

1.在对应分类下创建组件,系统将分配一个id来标识此组件

2.本地h5lib目录下创建组件,并导出

这里css按照750px设计稿还原

import React from 'react';
import style from './index.less';

export default function(props:any) {
  //正常编写组件,这里我们接受3个可配属性
  const {mainColor, fontColor, imgUrl} = props;
  return (
    <div className={style.loginContainer}>
      <img className={style.img} src={imgUrl}/>
      <div className={style.formItem}>
        <div className={style.lable}>手机号</div>
        <input className={style.input1} placeholder="请输入手机号"/>
      </div>
      <div className={style.formItem}>
        <div className={style.lable}>验证码</div>
        <input className={style.input2} placeholder="短信验证码"/>
        <button className={style.codeBtn} type="button" style={{backgroundColor: mainColor, color: fontColor}}>获取验证码</button>
      </div>
      <button
        className={style.submit}
        type="button"
        style={{backgroundColor: mainColor, color: fontColor}}
      >立即领取</button>
    </div>
  );
}
// 导出时使用刚才分配的id作为key,并使用import()语法方便后续组件异步加载
export default {
  '6045ca8adf8e607d29d0bffb': import('../h5Lib/business/LoginCoupon'),
};

3.拖拽配置组件初始值

上一步我们组件接受三个props:mainColor, fontColor, imgUrl,可以直接拖拽颜色选择器、图片上传控件生成表单项。 11.gif

这里表单部分借助form-render实现,最终会生成一个描述表单项的schema:

151c6eb3-ec6d-4ce7-b3bb-1b16b17a54a6.png

如果这一步对比storebook,就是手动编写knobs部分映射代码了

4.接下来就可以愉快的拖拽生成一个完整的页面了

12.gif

5.手机访问生成的页面

组件和页面的预览图,通过html2canvas自动生成。

一个搭建好的页面,也可以设置为模板,利用模板可以快速生成相似结构的营销页面:

fc00dc9c-a434-4def-b2e9-41850e4c9cc8.png

手机扫描二维码体验:

下载.png下载 (1).png下载 (2).png

可以在chrome里查看,组件还实现了异步加载,不必担心组件库的膨胀导致加载缓慢。 其中登录组件需要精确还原设计稿,使用vw单位。

// 异步加载组件示例(首先得打包成异步组件,本项目使用parcel结合import()语法):
const fetchComponents = async function(pageSchema:IPageSchem){
  const tasks:any[] = [];
  pageSchema.forEach((page)=>{
    page.components.forEach((component)=>{
      const load = new Promise(async(resolve, reject)=>{
        const asyncComponent = componentList[component._id];
        if(asyncComponent){
          const timeStemp = new Date().getTime();
          const loadedComponent = (await asyncComponent).default;
          resolve({
            _id: component._id,
            name: component.name,
            component: loadedComponent,
            takeUp: new Date().getTime() - timeStemp,
          });
        }else{
          reject(`组件: ${component._id}加载失败`);
        }
      });
      tasks.push(load);
    });
  });
  try {
    const loadedComponents = Promise.all(tasks);
    return loadedComponents;
  } catch (error) {
    throw error;
  }
};

项目结构

项目分为两块:H5搭建、H5基座。

项目中也尝试使用了一些不错的库(代码会有些混乱):

  • 后台复杂场景的表单解决方案:formily
  • 针对React Hooks的状态管理:unstated

目前部分功能还在开发中,后端项目暂未开源。觉得不错的话加颗星关注后续迭代。 github.com/lx544690189…

H5搭建:

  • dev、build使用umi
  • 负责组件开发、管理、拖拽、页面生成的项目
  • .umirc.ts中pxToViewPort配置了h5lib目录px转vw(750px设计稿)
  • 设计页面时的H5画布(iframe)并不是由下面"H5基座"实现的,它们大部分的功能相同,但是一个仅开发设计阶段使用,另一个要用于生产环境。存在功能和职能差异,故分开。 dev
npm run dev:design

build

npm run build:design

H5基座:

  • dev、build使用parceljs
  • 负责最终生成的页面渲染
  • 动态加载组件
  • TODO:可以将页面的json schema直接打入index.html,或放到cdn,缩短首屏渲染时间 dev
npm run dev:mobile

build

npm run build:mobile

展望

项目虽然使用react编写,暂只支持react组件,理论上从“schema -> 组件”这一过程,并不存在语言、框架限制,vue、小程序都可以支持,只是需要把H5画布上“schema -> 组件”的中间层替换掉就可以了。