Comments (4)
可视化搭建的前世今生
页面可视化搭建,最早可以追溯很远,耳熟能详的就是Dreamweaver,以及后来基于jquery等前端搭建的项目,随着web开发的发展,前后端分离与数据驱动DOM动态页面,逐渐成为历史。
页面构成
我们认为一个页面简单的说是由HTML结构与数据组成静态页面,配合一些逻辑变成为动态页面。(css样式,在这里我们归入Data一类中)
页面组件化
页面经过渲染之后,是 HTML 元素构成的树形结构,其中的结点便是我们前端经常提到的组件,主要实现了功能封装和可复用的两个功能。数据来源主要为内部维护变量和外部传入变量。
附:组件化还是要重提,主要是因为组件化的存在,才让现在的搭建器发挥得更优。
落地页开发痛点
活动页面特点
前端业务中, 经常需要开发产品介绍页/营销页/活动页/图片展示页等页面. 这类需求有以下几个特点:
页面类似: 同行业的落地页页面布局和业务逻辑较固定.
需求高频: 不同的人员每周会有多个这种需求.
迭代快速: 开发时间相对较短, 上线时间紧.
开发性价比低: 开发任务重复, 俗称画页面,消耗各方的沟通时间和人力.
常规开发流程
流程:
- 运营/产品提出页面需求prd文档.
- 开发根据UI设计稿完成页面开发.
- 测试进行页面测试.
- 运维进行页面上线.
- 运营/产品进行线上验收.
痛点:
高效率的流程
- 运营/产品提出页面需求prd文档.
- 运营/产品在搭建系统中选取合适的模板进行页面搭建.
- 页面自动化发布上线, 页面需求完成, 流程完结.
- 如果运营/产品没有找到合适的模板.
- 开发进行页面模板开发, 并将页面模板添加到搭建系统中.
运营/产品继续流程2.
随着搭建系统时间的推移,会沉淀出越来越多的组件/模块提供使用,对开发的依赖越来越低。
参考:
页面可视化搭建工具技术要点
页面可视化搭建工具前生今世
from sunxinfei.github.io.
关于搭建框架
目前一些旧的搭建平台,组件、搭建器、配置项,这三个耦合度非常高,导致后期拓展性很差。举例:当要添加一个例如视频之类的简单组件,如果需要动组件列表、搭建器、配置项这三个地方的代码,则可以断定耦合度非常高了。
引用一段话
任何一个有一定复杂度、会持续增长的应用最重视的,其实并不是开发速度,而是可维护性和可扩展性。 这也是框架设计者们摆在首位的事情。可扩展性的好坏取决于框架的扩展机制。在我们的上面的设计中需要扩展的有两部分,组件和功能。组件的扩展可以通过允许用户提交自定义组件来实现。功能的扩展主要由框架开发者完成。 --侯振宇
在文章页面可视化搭建工具技术要点中提到框架要解耦是最优解,而大部分搭建项目其实确实是服务于业务线,而导致react的落地页,搭建平台也是react语言,如果要实现框架与组件的解耦可行性也是有的,因为我们不管渲染层面是什么语言其实搭建器产生的都是一段段json数据,所以关注点又回到了搭建器的操作台的组件预览,是否需要用搭建器的语言再实现一遍,而且配置区域的数据变化就不能为redux或vuex的语法,从这两点考虑,框架与组件解耦就需要值得商榷了。但是后面随着微前端等前景的发展,未来还是可以完美实现的。
所以除了框架解耦不再讨论之外,下面会从组件和配置项两个纬度讨论解耦的事情。
可视化工具结构
我们以一个开源的工具为例:
其实可视化搭建工具的结构一般分成四块,如图所示,按照数字对应关系分别为:
- 组件列表:可以使用的组件的列表,一般是组件的图片和文案展示;
- 操作台/画布:进行组件拖拽布局、选择等交互操作;
- 配置区域:配置选中组件的属性;
- 功能按钮:用来保存、预览、redo、undo等操作;
组件列表
组件列表中的组件主要分为三类:
- 基础/业务组件:原子类型的,比如:文本、图片、按钮、轮播图等;
- 组合组件:由原子类型的组件拼接而成的json结构,相当于mini的模版;
- 第三方组件:由他人开发完成,注册到组件市场;
关于组件市场的**如下图:
所以组件市场中的组件和普通组件差别不大,属性配置按照规定的地方进行书写,渲染时动态加载第三方的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属性的对数据结构的遍历、计算与揉合,这里不多做赘述。
配置区域
整体思路就是配置区域对配置区域读/写,组件对配置数据读取,如下图:
而组件通过props传入的数据驱动渲染:
关于组件配置项的描述,为各组件差异化的配置数据定义数据结构和字段类型,我们这里用JSON表示, 因为其格式灵活,支持数据嵌套,前端友好。
如果为每个组件都编写一个表单页面,工作量较大;对于复杂的配置项,表单页面的编写工作量可能会大于页面组件的开发工作量。我们将配置项的颗粒度细化出来,比如配置项是"Text",我们就渲染出一个Input框,如果配置项是“Color”,我们则渲染出一个"Colorpicker",这个**在JsonEditor和云凤蝶项目中得到体现。
我们将配置项进行原子性的抽离,这样就会得到:
- 简单的数据类型:Boolean、Color、Date、Image、Number、Text等;
- 复杂数据类型:Array、Object;
复杂数据类型和简单数据类型嵌套,基本可以满足大部分组件的配置。当然在实际的业务中可能出现一些特殊的要求或者UI设计师设计出特殊的配置项样式,我们可以将这一类归为业务数据类型,比如字体配置:Font,开发者单独开发,由于组件和配置项借助schema.json配置项解耦,独立开发Font的配置即可,配置项可插拔状态,拓展性很好,完全不依赖组件。
实时预览(兼容手机端)
现在预览状态兼容手机端展示主要是两种:
一种是百分比:百分比的这种目前遇到的不多,出现的场景一般是画布中每行元素固定,也就是画布中元素不支持任意位置拖拽;
一种是px转rem:px转rem这种方式目前比较常见,元素位置为absolute,将data中存储的px数值,计算为对应的rem值即可。但是注意一点,如果是fix的元素,在pc预览时,如果给内容区域设定了最大宽度,如下图的样式:
这时候,就需要写一些特殊的代码来兼容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.
相似项目汇总
行业竞品(排名不分先后)
- 头条巨量引擎官方落地页制作工具:橙子建站
- 阿里SaaS 模式的智能建站平台:云凤蝶
- 百度H5: https://h5.bce.baidu.com/
- 基于智能内容创意设计:易企秀
- 页面搭建界中的PhotoShop:ih5
- 美团外卖前端可视化界面组装平台 —— 乐高
开源系列:
- https://github.com/baidu/amis
- https://github.com/givanz/VvvebJs
- https://github.com/jaweii/Vue-Layout
- https://github.com/ly525/luban-h5
- https://github.com/ymm-tech/gods-pen
....
form表单开源系列:
- https://github.com/GavinZhulei/vue-form-making/
- https://github.com/alibaba/form-render
- https://github.com/jdorn/json-editor
from sunxinfei.github.io.
补充-关于联动
{
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)
- 实现拖拽网格布局排版思路 HOT 3
- vagrant box add laravel/homestead 失败
- 仿飞冰项目中的总结 HOT 3
- 移动端前端适配 HOT 5
- Vue项目中添加骨架屏
- React Native Notes -- 2019 HOT 3
- Node 文件上传
- leetcode中的一些题解 HOT 3
- Selenium
- Docker + Node + Pm2 + Redis + Puppeteer HOT 6
- 前端基础 HOT 14
- 2019微信分享链接自定义文案与图片
- Electron项目总结 HOT 13
- 前端字体优化二三事 HOT 3
- 前端性能优化二三事 HOT 5
- 前端单元测试二三事 HOT 3
- 前端监控二三事
- 前端引导二三事 HOT 4
- 3D二三事 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sunxinfei.github.io.