Coder Social home page Coder Social logo

Comments (4)

SunXinFei avatar SunXinFei commented on June 29, 2024

可视化搭建的前世今生

页面可视化搭建,最早可以追溯很远,耳熟能详的就是Dreamweaver,以及后来基于jquery等前端搭建的项目,随着web开发的发展,前后端分离与数据驱动DOM动态页面,逐渐成为历史。

页面构成

我们认为一个页面简单的说是由HTML结构与数据组成静态页面,配合一些逻辑变成为动态页面。(css样式,在这里我们归入Data一类中)
image

页面组件化

image
页面经过渲染之后,是 HTML 元素构成的树形结构,其中的结点便是我们前端经常提到的组件,主要实现了功能封装和可复用的两个功能。数据来源主要为内部维护变量和外部传入变量。
附:组件化还是要重提,主要是因为组件化的存在,才让现在的搭建器发挥得更优。

落地页开发痛点

活动页面特点

前端业务中, 经常需要开发产品介绍页/营销页/活动页/图片展示页等页面. 这类需求有以下几个特点:
页面类似: 同行业的落地页页面布局和业务逻辑较固定.
需求高频: 不同的人员每周会有多个这种需求.
迭代快速: 开发时间相对较短, 上线时间紧.
开发性价比低: 开发任务重复, 俗称画页面,消耗各方的沟通时间和人力.

常规开发流程

流程:

  1. 运营/产品提出页面需求prd文档.
  2. 开发根据UI设计稿完成页面开发.
  3. 测试进行页面测试.
  4. 运维进行页面上线.
  5. 运营/产品进行线上验收.

痛点:

  • 方多参与, 反复沟通, 串行流程.
  • 页面上线周期长, 无法快速响应活动需求.
  • 人力陷入重复工作泥潭, 忙碌而低效.
    image

高效率的流程

image
流程

  1. 运营/产品提出页面需求prd文档.
  2. 运营/产品在搭建系统中选取合适的模板进行页面搭建.
  3. 页面自动化发布上线, 页面需求完成, 流程完结.
  4. 如果运营/产品没有找到合适的模板.
  5. 开发进行页面模板开发, 并将页面模板添加到搭建系统中.
    运营/产品继续流程2.
    随着搭建系统时间的推移,会沉淀出越来越多的组件/模块提供使用,对开发的依赖越来越低。

参考:
页面可视化搭建工具技术要点
页面可视化搭建工具前生今世

from sunxinfei.github.io.

SunXinFei avatar SunXinFei commented on June 29, 2024

关于搭建框架

目前一些旧的搭建平台,组件、搭建器、配置项,这三个耦合度非常高,导致后期拓展性很差。举例:当要添加一个例如视频之类的简单组件,如果需要动组件列表、搭建器、配置项这三个地方的代码,则可以断定耦合度非常高了。
引用一段话

任何一个有一定复杂度、会持续增长的应用最重视的,其实并不是开发速度,而是可维护性和可扩展性。 这也是框架设计者们摆在首位的事情。可扩展性的好坏取决于框架的扩展机制。在我们的上面的设计中需要扩展的有两部分,组件和功能。组件的扩展可以通过允许用户提交自定义组件来实现。功能的扩展主要由框架开发者完成。 --侯振宇

在文章页面可视化搭建工具技术要点中提到框架要解耦是最优解,而大部分搭建项目其实确实是服务于业务线,而导致react的落地页,搭建平台也是react语言,如果要实现框架与组件的解耦可行性也是有的,因为我们不管渲染层面是什么语言其实搭建器产生的都是一段段json数据,所以关注点又回到了搭建器的操作台的组件预览,是否需要用搭建器的语言再实现一遍,而且配置区域的数据变化就不能为redux或vuex的语法,从这两点考虑,框架与组件解耦就需要值得商榷了。但是后面随着微前端等前景的发展,未来还是可以完美实现的。
所以除了框架解耦不再讨论之外,下面会从组件和配置项两个纬度讨论解耦的事情。

可视化工具结构

我们以一个开源的工具为例:
image
其实可视化搭建工具的结构一般分成四块,如图所示,按照数字对应关系分别为:

  • 组件列表:可以使用的组件的列表,一般是组件的图片和文案展示;
  • 操作台/画布:进行组件拖拽布局、选择等交互操作;
  • 配置区域:配置选中组件的属性;
  • 功能按钮:用来保存、预览、redo、undo等操作;

组件列表

组件列表中的组件主要分为三类:

  • 基础/业务组件:原子类型的,比如:文本、图片、按钮、轮播图等;
  • 组合组件:由原子类型的组件拼接而成的json结构,相当于mini的模版;
  • 第三方组件:由他人开发完成,注册到组件市场;

关于组件市场的**如下图:
image
所以组件市场中的组件和普通组件差别不大,属性配置按照规定的地方进行书写,渲染时动态加载第三方的js与css文件即可;

{
    "type": "comp-feed",
    "version": "0.0.22",
    "properties": {
        "title": {
            "type": "String",
            "name": "用户名",
            "value": "测试一版"
        },
        "avator": {
            "type": "Image",
            "name": "头像显示",
            "value": "https://s.gravatar.com/avatar/518515a45a5c15165f559857c3d60a95?size=100&default=retro",
            "canDelete": true
        }
    },
    "event": {
        "qrShow": 453849
    }
}
loadResources(docData) {
      let head = document.getElementsByTagName("head")[0];
      let promiseList = [];
      docData.pages.forEach(item => {
        (item.children || []).forEach(val => {
          // 异步组件
          if (val.compType !== 1 && val.type) {
            promiseList.push(
              new Promise(resolve => {
                let tmpSrc =`https://unpkg.com/ ${val.type}${
                  val.version ? `@${val.version}` : ""
                }/dist/js/index.js`;
                let script = document.createElement("script");
                script.type = "text/javascript";
                script.src = tmpSrc;
                script.onload = () => {
                  resolve();
                };
                head.appendChild(script);
              })
            );
            promiseList.push(
              new Promise(resolve => {
                let tmpSrc = `https://unpkg.com/ ${val.type}${
                  val.version ? `@${val.version}` : ""
                }/dist/css/index.css`;
                let link = document.createElement("link");
                link.href = tmpSrc;
                link.setAttribute("rel", "stylesheet");
                link.setAttribute("type", "text/css");
                link.onload = () => {
                  resolve();
                };
                head.appendChild(link);
              })
            )
          }
        });
      });
      Promise.all(promiseList).then(() => {
        this.pages = docData.pages || [];
      });
    }
上述代码自动加载如下的js和css文件
https://unpkg.com/[email protected]/dist/css/index.css
https://unpkg.com/[email protected]/dist/js/index.js

操作台/画布

这里主要集中以下操作技术:

  • 元素拖拽
  • 缩放与旋转
  • 辅助线计算
  • 对齐方式
  • 层级调整
  • 防止误操作
  • 右击菜单
  • 快捷键
  • redo/undo

多是基于组件data中top、left、height、width属性的对数据结构的遍历、计算与揉合,这里不多做赘述。

配置区域

整体思路就是配置区域对配置区域读/写,组件对配置数据读取,如下图:
image
而组件通过props传入的数据驱动渲染:
image
关于组件配置项的描述,为各组件差异化的配置数据定义数据结构和字段类型,我们这里用JSON表示, 因为其格式灵活,支持数据嵌套,前端友好。

image

如果为每个组件都编写一个表单页面,工作量较大;对于复杂的配置项,表单页面的编写工作量可能会大于页面组件的开发工作量。我们将配置项的颗粒度细化出来,比如配置项是"Text",我们就渲染出一个Input框,如果配置项是“Color”,我们则渲染出一个"Colorpicker",这个**在JsonEditor云凤蝶项目中得到体现。
我们将配置项进行原子性的抽离,这样就会得到:

  • 简单的数据类型:Boolean、Color、Date、Image、Number、Text等;
  • 复杂数据类型:Array、Object;

复杂数据类型和简单数据类型嵌套,基本可以满足大部分组件的配置。当然在实际的业务中可能出现一些特殊的要求或者UI设计师设计出特殊的配置项样式,我们可以将这一类归为业务数据类型,比如字体配置:Font,开发者单独开发,由于组件和配置项借助schema.json配置项解耦,独立开发Font的配置即可,配置项可插拔状态,拓展性很好,完全不依赖组件。
image

云凤蝶Schema
JsonSchema

实时预览(兼容手机端)

现在预览状态兼容手机端展示主要是两种:
一种是百分比:百分比的这种目前遇到的不多,出现的场景一般是画布中每行元素固定,也就是画布中元素不支持任意位置拖拽;
一种是px转rem:px转rem这种方式目前比较常见,元素位置为absolute,将data中存储的px数值,计算为对应的rem值即可。但是注意一点,如果是fix的元素,在pc预览时,如果给内容区域设定了最大宽度,如下图的样式:
image
这时候,就需要写一些特殊的代码来兼容fix属性的模块了:

//fix模块css的left计算
getLeft() {
      if (document.body.offsetWidth > 750) {
        return this.data.css.left + (document.body.offsetWidth - 750) / 4;
      } else {
        return this.data.css.left;
      }
    },
//fix模块计算上or下fix位置
    getTopOrBottom(data) {
      if (data.properties.fixPos == "top") {
        return `${data.css.top / 50}rem`;
      } else {
        return `${-data.css.top / 50}rem`;
      }
    }

同理在搭建操作台渲染fix类型的组件时,也需要特殊处理。

from sunxinfei.github.io.

SunXinFei avatar SunXinFei commented on June 29, 2024

相似项目汇总

行业竞品(排名不分先后)

  • 头条巨量引擎官方落地页制作工具:橙子建站
  • 阿里SaaS 模式的智能建站平台:云凤蝶
  • 百度H5: https://h5.bce.baidu.com/
  • 基于智能内容创意设计:易企秀
  • 页面搭建界中的PhotoShop:ih5
  • 美团外卖前端可视化界面组装平台 —— 乐高

开源系列:

form表单开源系列:

from sunxinfei.github.io.

SunXinFei avatar SunXinFei commented on June 29, 2024

补充-关于联动

{
  tmpSelect:{
    type:'SelectRadio',
    config:{
      options:[{
        id:'1',
        name:'aaa'
      },{
        id:'2',
        name:'bbb'
      }]
    },
    value:'1'
  },
  form1:{
    type: 'Input',
    config:{
      name:'表单1'
    },
    value:'表单value值',
    dev:{//联动控制
      show:{//控制是否展示 也可以为disabled等控制
        param1:{//变量
          filed:'tmpSelect',
          eval:'===',
          value:'1'
        },
        param2:{
          filed:'tmpSelect',
          eval:'!==',
          value:'2'
        },
        logic:' %{param1}% || %{param2}%' //条件:tmpSelect === 1 || tmpSelect !==2才展示
      }
    }
  }
}

如上示例,我们有一个tmpSelect的组件,组件表现形式是SelectRadio,有aaa和bbb两个选项,如果想通过tmpSelect来控制form1是否展示,则给form1添加控制属性dev,dev中有show/disabled等组件状态控制。

from sunxinfei.github.io.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.