「可视化搭建系统」——从设计到架构,探索前端的领域和意义


阿里巴巴集团前端委员会主席 @圆心 对前端未来期许有四点:建立服务, Serverless,智能化,IDE。仔细想想,一个「可视化建立体系」的幻想空间,正能完美射中这些方面。前端的鸿沟在哪里,关于事务的价值又在哪里,咱们无妨静下来,一同从「可视化建立体系」的视点来考虑。

F ( ! ^— 有人说前端「可视化建立体系」说到底只是重复造轮子产生的玩具;有人说前端「可视化建立体系」实质是组件枚举,毫无含义。片面的认知必有其产生道理,但咱们无i 5 Q p j i e妨从更高的视点动身,并逼真落% w ~ z d x P } v地实践,或许你会发现:作为 Fg ] 8 w )Eer,咱们能做的工作或许更多。

页面建立技能门户概览m y G M F ? . ~ I和彩蛋放送

据我调查“简直每一个前! ] *端团队,都会有一个页面建立体系”。**页面建立技能是一个陈词滥调的论题,可这个论题伴随着前端技能的开展,历久弥新。**究其原因,包含但不限于:

  • 运营活动页面关于产品事务至关重要,是招引流量、进步留存的要害手段
  • 高频且重复度较高~ D Y m V s的活动页面开发,关于前端意味着很多的时间和人力本钱消耗

在此背景下,快速页面建立技能就显得尤为重要。

因为每个产品事务的特色、运营需求和规划标准不尽相同,因而页面建立渠道就呈现@ 0 e [J T X E Q J“百家争鸣,百家争鸣”的局势。咱们在“凭空捏造”的一起,饱览众家之长,对比归纳,继续优化。为此,咱们剖析了社区上简直全部开源产品和方案,包含但不限于:

  • # ~ ? W h y c u度 H5
  • iHw V a k q M ? b5
  • 转转魔. , ; ; % G O P +方渠道
  • 百度b M y v 2 l H O *外卖页面装备渠道:Blocks
  • 携程乐高体系
  • 人人贷活Y ! O动运营渠道
  • 新版微信修改器
  • 鲁班H] B G 2 j /5
  • 阿里云凤蝶
  • MAKA
  • 码良渠道
  • g3 L S e ] : K h Jrapes
  • 可视化布局 bootcss2 o b
  • 民间方案:pipeline-editor
  • 一个国外的民间方案:vv6 H m j z wvebjs

相关技能剖析文章:

  • 页面可视化建立东西前生今世
  • 页面可视化建立东西技能要害
  • QQ会员活动运营渠道演变和技^ F { * N m能实践——高效活动运营
  • 积木体系,将运营体系做到极致
  • 活动运营主动化渠~ q r % + / * v道实践
  • 可视化建立前端工程 –h f o _ D q w & R 阿里飞冰了解一下
  • 飞冰关于活动引擎的可学` # @ h 6习之处
  • 前端工程实践之可视化建立体系
  • 怎么规划高扩展的在线网页制作渠N I G ! s J J 9
  • 鲁班H5作者:@小小鲁班
  • ) 9 _ l ? % ^ _ 4恶了写活动页?快来撸一个页面生成器吧!

其特色和技能方向可以各有特色,但总体可以R s _ n # B d T归纳为以下图示:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

依照目标受众,可区别:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

5 8 ~ N 6 / a S们也从海量优异方案中总结出处理这一类运营需求的**通用手段:将杂乱页面的建立抽象成结构化数据,由结构数据驱动组件/模版的组装。**简略的这样一句话很好了解,依照这样的主意也能构建出一个可用的渠道,但能否更进一步,想在技能和事务上打破) O X瓶颈,还需求打通更多环节:

  • 结构化数据怎么规划才能统筹高雅和高功用,且天然支撑活动修改时的“韶光游览 Redo/Undo”功用
  • 怎么平衡页面的自在发挥度和标准一致度
  • J % / 7 6 @ k u X么打破原始模版引擎,借力框架(7 * ] N o g TReact、Vue 等)组件化思维,并做到 framework free
  • 怎么高雅完结专题模版功用,一键导入功用以及插拔式修改
  • 怎么贴合自身事务特色,平衡实用性、适用性和可扩展性
  • 怎么不断继续迭代,以适应新的需求开展
  • 怎么凭借社区的力气s Y K,做大做强
  • 怎么最大化发挥可装备,怎么最大化便利接入方扩展
  • 怎么防止组件枚举堆积的紊乱

业界已有方案中,有的较好地处理了这些要害点中一个或多个问题,有的更像是一个练手的玩具。请读者继续阅览,接下来我将介绍「结] D r V d [ a 合修改器L d . 2技能的页面建立渠道」思路,全体如下图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

当修改器技能遇见页面建Q y G i立需求

让咱们先回到一个广泛而有趣的问题上:“ – $ Q n前端开发的难点到底在什么地方?”。

在这个问题下,旧有 @于江水 说到两个点:

  • 事务逻辑很杂乱而且多变
  • 笔直范畴m O e * : v处理方案并不简略

这儿对其b b : ] k ? u 6答案进行简略搬运和扩展,原答案可参阅:于江水的回答。
顺着这个思路咱们来剖析,前面说到的运营活动页面——单纯开发这些页面难度其实不高。可是关于前端团队来说,假如高频多变的运营需求在短时间内集中爆发,那么| R @就成了一个体系性的问题了。比方极端状况:关于淘宝双十一、京东大促,简c v C P 4略地堆人堆时间也只是无济于事。所以诞生了页面建立渠道。

这样一个渠道涉及到的技能点是**网状的:比方涉及到开{ @ { b –发东西链、数据结构规划、烘托器和交互规划、数据源导入、页面编译构建、页面生成、代码发布、活动发布、版别办理、在线X 6 i 7 j + 1 d运营办理、权限办理、可视化“所见即所得”完结、后端存储、CDN 同步、数据$ K k & c打点j 0 S和统计、数据剖析等。**后续结合渠道化才能,也会涉及到组件商场的规划,7 0 f k S A ^乃至 seri % Z V 2 R i Everless,no/low code 技能。

**而作为笔直范畴一个不行忽视的方向——修改器开发,技能难度只会更高:**除了修改器本身的各种功用完结外,还需求统筹兼容性,更要适应事务需求。一起,修改器便是生产东西,任何一个中后台体系似乎都必不行少,需求商场上,不管是石墨文档、钉钉文档、头条飞书等都有着广泛而激烈的需求。该范畴值得深耕而# k 2 2 g Q优异开发专家却百里挑一。

为了处理「可视化建立体系」,咱们测验把一个上述「杂乱的事务渠道」和「笔直范畴的富文本开发」这两大难题结合起来,打造一个功用强壮的修改器,一起完结页面建立渠道9 & + q的工作——这听上去尽管是“难上加难”,但似乎两大方N 9 Y & X g 3向的融合是一种美妙的思路和立异。

详细来说,修改器除了支撑传统富s ) %文本功用以外,需求参加对@ & 9 –事务功用区块的支撑,这时候在数据结构上,选用 JSON base 的存储办法:传统富文本区块以 JSON 字段存储富文本内容,其它复合型自定义事务区块存储为 JSON 目标结X r $ V ( T构。在此根底上,X ? X M S d B _咱们完结对该 JSON 目标结构的解析,完a ^ n s g s T [结修改器内“所见即所得”Q Q a 8 q

这儿单独说一下富文本之外的“复合型自定义事务区块”。咱们知道终究建立出来的页面将会充满各种 Sku 产品、自定义组件、用户卡片等区块,终究这些内容的输出需求被 C 端烘托器所了解、所解析。

咱们来结合下图,进一步阐明:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

区块 1 是传统富文本内容,区块 2 是一个复合型 # 8 _自定义事务区i f ! r块——Sku 卡片,区块 3 是另一个复合型自定义事务区块——用户卡片。这样一来修改器不再是一个单一的富文本修改器,而是终究输出内容为杂乱 JSON 类型的多功用修改器。

不同事务场景、特色,需求彻底不同的前端处理方案,在开发这些笔直处理方案的时候,事务剖析、技能选型、架构规划、开发落地是十分难的。接下来,就让咱们一步步探究,一步步完结一个依据并统筹修改5 / C | N F器技能的多功用的页面建立渠道。

灵敏强壮的 Markdown 修改器和页面建立立异测验

我信任现如今没有T ) g m i k程序员不知道 Markdown,n ] {它对程序员或许全部互联网从业人员来说都十分友爱。简略说,V – C i w NMarkdown 是一种轻量级标记言语0 n L _ U M a y,它答应咱们运用易读易写的纯文本格局编写文档。现如今许多网站都广泛运用 Markdown 来编撰帮助文档或是用它来在社区上发表音讯。比方:GitHub、Wikipedia、简书、reddit 等。

除了易 y U W R 8 d `于编写,Markdown 的可扩展性和可转化性也是它收到追捧的重要原因。也正因为如此,咱们初期的运营活动页面建* { } 7 7 V [ H S立便是依据 Markdown 修改器施行的。详细流程如图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

当然这只是一个十分大略简易版的流程示意图,接下来我将分:

  • Markdown 扩展和自定义解析器
  • 完善运用体会,打造页面生成才{ K ! ! o j o 6 D

两个方面进行详细解释。

Markdown 扩展和自定义解析器

Markdown 原本运用场景是面向文档和写作,它支撑的标记和语法并不能满足全部场景需求。因而社区上存在不少 Markdown 解析器,其意图是6 i 6 ( N对 Markdown 源内容进行解析和扩展。在众多解析器傍边,最知名的便是 marked.js 了。这儿简略对 marked.js 这个库原理进行剖, z F (析,将会有助于了解后续咱们的完结方案。

说起解析,其实便是经典的“编译原理”套路。套用在 marked.js 上,如下图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

y t l k + [ .作机制很简略,marked.js 承受输入源文本字符串后,创立词法解B 2 B 8 F析器实例:

con{ T # C Y mst lexer = new marked.Lexer()

词法解析器实例 lexer 的任务是将输入源进行分词,解析出 tokens:

c; 8 n x f 4 Lonst tokens = lexer.lex(content)

怎么g d + J ] T w # m了解分词生成的 tokens 呢?其实 tokens 便是W @ R ` : ^ _ AST 目标(或直接把它了解成 json 数据,它是树形结构,表达出 Markdown 中阶段,块引证,列表,标题,规则和代码块等信息)。

接下来,marked.js 实例化一个解析器:

const parser = new marked.Parser()

该解析器 parserF ~ ? b z + L o – 接纳 tokens,依据 tokens 生成 html 富文本= 0 Y Y ! D a

const html = parser.parse(tokens)

当然,这只是很大略的流程,但细心的读者可以窥出t S ) t c端倪:**假如想扩展 Markdown 语法:咱们可以批改 lexer 生成 tC n n . . 2 l K pokens 的函数,意图是参加咱们的自定V P ~ | R义 Markdown 语法解析成新类型 token 的才能;一起批改 parser 解析函数,依据新 token 类型,生成咱们预期成果。**这/ i I : 8 ;儿我不在深入赘述这个进程,事实上,咱们选用的方案也没有 fork 去批改 marked.js 代x H l 5 i o 6 S c码,而是自己依据 marked.js,封装了更上层的解析器。

完善运用体会 打造页面生成才能

由上可知,咱们的页面建立需求首要集中在刺进各种组件卡片,刺进带链接 banner 图片等复合型自定义事务区! x G t r . = ( :块。这每一个需求都应该对应一个 Markd~ d Kown 的新语法规则。

比方,输入:

<SkuCell>live@12345@rondStyle</SkuCell>

则表明页面中刺进一个 id 为 12345 的 Sku 卡片。

假如让运营同学手动输入上述语法内容无疑是痛苦且不行承受的。因而咱3 _ X + ] p 们规划了 Markdown 修改器的按钮:「增加 Sku Cell」,点击按钮之后,会弹出表单对话框,由运营输入5 I $ X | , M . Sku 类型和 id ,即可主动在 Markdown 修改器中光标所在方; . @ V p a 1位刺进一行内容:3 A R e m d

<SkuCell>live@12345@rondStyle</SkuCell>

这样的规划便利运营运用和回忆。因而关于运用者来说,只需求了解根本的 Markdown 语法,而不需求再去记牢和手动输入新式语法。

**为了满足“所见即所得”需求,咱们需求在运营键入内容时f V y * N = M w,一起进行对输入源的解析。**解析的进程需求逐行n C | i ( V进行:H 0 ! k S

  • 假如解析当时行内容契合 Markdown 原始语~ S ? D法,则用U g E f $ marked.jR ^ gs 进行解析,得到解析出来的富文本成果,推入成果数据栈(这儿的数据栈是一个 result 数组)
  • 假如解析当时行内容契合新扩展的 Markdown 语法,c o O 2 6 C则运用自己的解析器函数(暂且命名为 fePars_ g % 6e)对该行进行解Y Z 1析(解析器函数完结是一个简易的编译分词进程
  • feParse 函数接纳扩展新语法内容,关于不同表意办法运用不同的 helper 处理,比方处理 <SkuCH b ^ F .ell>live@12345@rondStyle</SkuCell> 将会被 skuCellHelper 函数处理
  • skuCellHelper 函数解析内容,剖析得到分词成果(标记为 formData):
type: 'live',
sku_} U 7 ? Gid: 12345e J [ F X,
style: 'rondStyle'
  • 依据上面分词成果,恳求后端接口,获取该 Sku 对应的数据,比方该 id 为 1234w Z Y O E5 的 live 数据(标记为 liveData):
author: 'li) , ] 9 : Xve 作者名',
id: 12345,
created_date: '2019 10-12 20:34',
description: 'live 介绍',
duration: '20mins',
// ...
  • 依据以上两种数据:formData 和 liveData,运用 Reacv P H =t 服务端烘托才能j / @ n f R 7,取得该 Sku 组件对应的富文本 skuRichText:
const skuRichText = ReactDOMServer.renderToString(<SkuCell data={... formData, ... liveData} />Q r _ z 4 Z X;)
  • 将 skuRichText 推入成果数据栈 result

终究咱们逐行解析的成果产出为:

result = [
0 b ~ D 4 9 r z'榜首行富文本内容''第二行 Sku 卡片对应的富文本内容',
// ...
]

兼并 result 内容,烘托出富文本,A X 7 2 &显现在页面右侧,完结所见即所得作用。

总结一下完结“所见即所得作用”的要害为:

  • 自定义 Markdown 语法解析器
  • 运用 React 服务端烘托才能得到特殊组件的富文本内容

需求指出的是,在实践施行傍边:运营在修改器中,保存并提交给后端的数据区别于上述 result,它也是一个数组:submitData,用来表明运营输入的内容( c C 3 }。关于原始 Markd& = O : w * M g {own 语法,咱们直接运用其对应e v i – C x的富文本内容;关于新的扩大语法,咱们并没有运用其对应的富文本内容,而是运用了上述 formData 的数据结构,终究提交相似内容:

submitData = [
{
type: 'richText',
content w 7 q: '<p>XXXX&l? s ` it;/p>'
},
{
type: 'skq Y ( ! u 4 J nu',
content: {
type: 'live',
sku_id: 12345,
style: 'rondStyle'
}
},
// ...
]

**这样的考虑是为了 C 端用7 v 2 ~ F户在恳求页面时,可以取得最新的实D * _时 Sku 数据。**怎么了解实时 Sku 数据呢?在运营修改页面时,假设刺进一条 Sku 的标题信息为“标题一”。再一天后,该 Sku 的标题信息变成了“标题二”。假如咱们保存并运用t B | [ D L = ;了运营修改时运用的富文本信息,那么 C 端页面必定是“标题一”,而不是最新的“标题二”。因而咱们只提交该 Sku 的 id。当有 C 端用户恳求页面时,由后端通过 RPC/Http 调用,获取最新的数据,并由组件在服务端烘托出内] / s容,终究返回给前端。

整个流程如下:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

到此为止,咱们完结了一款依据 Markdown,运用 Markdown 语法灵敏性,扩展而成的修改器。这个修改器j T . } ! S , V 中内置了比方「b – & P ^ i刺进 Sku 卡片」c _ 3 5 z H N ]、「刺进 Banner 图」等一系列的事务功用。

依据这套思维,咱们完结了帮助运营快速建立活动页面的复合型修改器和页面生成器,它的长处十分显着:

  • 输入即所见,所见即所得
  • 支撑灵敏扩展z ` Y .,可以依据解析器支撑p 2 t全部类型的语法和恣意组件
  • 运营只需求了解根本的 Markdown 语法即可,扩展语法由点按按钮完结

终究作用图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

**技能方案都是在不断演化推进傍边开展并完善3 0 ^ ! P [ s的。在该渠道运行半年多之后,咱们大胆进行了立异优化,并终究用更高效的方案完结了全{ X u 5 @ ` j x +面替换。**感兴趣的读者请继续阅览。

不止是富文本修改器

上面咱们说g C _ $ M Z `到了已有复合型修改器即页面生成器的长处,通过半年多的) , } C 3 @ c ! +线上服务M M 9 D ; X m @ m后,咱们再去深入剖析一下它的缺点:

  • 修改器内 Markdo– 2 P l (wn 语法内容,关于运营依然较为晦涩难明
  • 运营仍是需求必定Z f q的学习和运用本钱
  • 依托实时解析和烘托的“所见即所得”
  • 关于每一种新的组件,都要创立一种新的 MarkdoE , G z f e 3 Twn 语法

这些缺点很好了解,这儿着重讲# . ` [ ( o q 7 s一下“所见即所得”。**上面咱们说到“所见即所得”,实践依托了实时解析内容源为全量富文本,并实时烘托富文本的才能。**尽管满足了需求,可是这样的做法功用本钱较高,即便加上常用的“防抖和截流”手段,关于浏览器的压力依然不小。能不能像“积木体系”、“拖拽建立页面体系”相同,直接在“画布”上批改,做到更加实在的“所见即所得”呢?

“拖拽体系”优缺点鲜明。
首要,以# & H A & y N H e很多 H5 生成东西为代表的拖拽体系尽管看上去功用强壮,可是实质上却是依托组件的堆积和无穷尽W y h的装备扩展,终究产出的数据形态和功用粗野生长下去,比较容易呈现“失控”的局势,而逐步被边缘化。
这儿的失控既指运营侧、产品规划侧没有一致束缚,也包含了代码胀大后的维护视点的失控。另一方面,从终究成果上看,拖拽体系将页面的拼接转嫁到运营身上,这些“搬砖”的工p V j o D M作量关于运营其实也并不算小,一起它缺少“标准化”的强制束缚,不利于视觉规划的一致,运营同学“自我发挥”反倒不必定y z K n L : v Y彻底是功德。退一步来说,社区上现已存在不少可用的拖拽体系,重复造轮子也毫无含义。

结合咱们的需求特色:页面区块和规划款式固定、组件形态固定、页面排版固定、重文字和图片内容、页面交互并不杂乱,咱们以为_ . } y 1多功用富文本修改器将会e 7 j v I是一个值得深入试水的方向。

传统的富文本修改器便是一个强壮的“超级文字加工厂”,相似咱们常用的 word,运营可以在其上“肆意挥洒”。怎么在富文本修改器上,参加规划标准,并完结事务组件增加呢?

首要,富文本修Z L :改器是前端一个十分值得深入研究的重要方向,社区上各类开源富文本修改器也不在少数,可是从时间和开发本钱的视点来看,咱们既不想从头完结一个{ o _融入了自己事务的增强型富文本P V $ R H K x z修改器;又不想做各种魔改已有方案。

无法找到一个合适的处理r u #方案,仍是让咱们先从需求视点剖析:

  • 新式多功用富文本修改器,需求支撑前史上的 Markdown 语法数据,不然会呈现前史数据不兼容的线上问题
  • 新式多功用富文本修改器,不仅为页面生成器服务,也要可以支撑多类型横向事务以及纯富文本修改器事务
  • 新式多功用富文本修改器,要支撑全部富文本的特性,包含仿制粘贴内容等
  • 新式多功用富文本修改器,要支撑刺进自定义组件和区块,比方 Sku 卡片等
  • 新式多功用富文本修改器4 j 4 5 D _ ^,应该插件化,可插拔
  • 新式多功用富文本修改器,要做到彻底的所见即所得
  • 新式多功用富文本修改器,要支撑模版方式快速建立页面
  • 新式多功用富文本修改器,k ; J要接入格局主动标准机制,主动完结标点揉捏、一致排版等功用

综上需求和规划方案,咱们选Y t m h B用了 Draft.js 作为这套多功用修改器的底层框架,一句话足以总结做出该挑选的原因:**Draft.js 实践上并不是一个富文本修改器,它其实是一个用于构建富文本内容和富文本修改器的根底设施。**做个i R ] V *比喻:假如把富文本内容比作一p 7 O 3 M c }幅画,Draft.js 只提供了画纸和画笔,至于怎么画,开发者享有很大的自在 ——(出自文章:Draft.js 在知乎的实践)。

这正契合咱们的需求:咱们不要一个完好的处理方案,而需求一个舞台。至于怎么解析内容,怎么烘托内容,怎么生成数据,应该悉数由开发者把控。事实证明,这样的立异规划关于页面建立生成器以及传统修改事务场景十分贴合,咱们终究完结了现在服务于后台体系的强I k @ + ( 2 l 6 t壮多功用修改器 —— Versatile Editor。

Versatile 译为“文武双全的;有多种技能的;多面手的;多用途的,多功用的”。现在 Versatile Editor 现已全R $ [ M Z m f 3面接管了全部后台体系修改需求。它的技能规划和体系也十分明晰。下面咱们首要从

  • 数据结构规划
  • a ~ ) x #件体系规划
  • 多数据源支t | N c r ! P C d
  • 运用体会U f S规划
  • l U c E ^ ~ [ e R面模版支撑
  • 其他细节

六个方面进行剖析{ 3 _ 0 I | z y G

别出心裁的数据结构

**数据结构的规划思维是:**运用成果数据栈(数组)存储每一个 Draft.js 修改器块级内容,数据每一项都次序对应每一个块元素。这些块元素分为两大类:纯富文本内容和纯自定义组件内容。关于纯富文本内容,咱们从头完结了将 Draft.js 的不行变数据结构解析转化为富文本的东西函数 draftToHtml;关于纯W x B / , ? P q自定义组件,咱们只提取出组件最小复原数据(比方 Sku Cell 组件的j J ? * sku id 等信息)。

运营R 9 n q g F在修改器侧; I w 4 ? c a提交流程如下图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

详细# – E k + F B Y Z阐明一下图中的中心 contentState。contentState 是 ContentState 类型的目标,它规则了怎么存储详细的富文本内容,包含文字、块级元素、行内款式、元数据等。

这儿需求留意的一点是:在输出数据上,咱们至少提交两种数据给后端存储:

  • rawContent
  • renderTreeData

其中 rawContent 是依据不行变数据 contentState 进行序列化后的成果,rawContent 可M L i ] o Y o T以通过数据表明出当时修改器内全部内容。咱们提交 rawContent 的意图是用于修改复原。当运营再次打w N ^ h开修改器时,修改器可以依据 rawContent 敏捷烘托出上一次提交的全部内容,以H # O供修改。

**而 renderTreeData 是通过计算并处理后提交的数据,它的意图是存储到数据库中,用于后端返回给 C 端页面,C 端页面终究依据 renderTreez p l 2 l Z j t |Data 由烘托器烘托出g : 9 z % . s .完好的活动运营页面。**由上图可知,renderTreeData 的生成,咱们开发了 RenderTreeGenerator 的实例上 generate 办法:

new RenderTreeGenerator(
contentState,
getToHtmlY ( ] 1 a COptions(cq t % A r D z yontentSB W i 6 Q / ]tate, this.props.editorConfig),
this.customBlockModules
).gena  n  kerate()

如图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义
「可视化搭建系统」——从设计到架构,探索前端的领域和意义

RenderTreeGenerator 承受 Draft.js 的不行变数据类型 contentState 作为榜首个参数,自定义装备项作为第二个参* p R T 9数,e [ L hReact 组件调集 this.customBlockModulE o l = H R X Ues 作为第三个参数。this.customBlockModules 是一个数组,包含了全部自定义区块 React 组件名,在自b u ( ! m /定义区块类型射中该数组时,需求启动自定义区块,并生成结构1 H B 0 m O ,化数据。

generate 办法简略伪代码阐明如下:

generate() {
this.output = []
this.blocks = this.contentState.gW Y 4etBlocksAsArray()
this.totalBlocks = this.blocks.length
this.currentBlock = 0
this.indentLevel =h W - T n R n 0
this.wrapperTag = null
this.richTextk W ~ u X $Array = []
this.finalOutput = []
const processRichText = () => {
this.| o doutput.push({
type: 'RICHTEXT',
data: th| 9 - 9 !is.processRichText()
})
}
while (this.currentBT ( V Q  Zl; h d kock < this.totalBlocks) {
coe K An / ) y 5 j 3 h :st block = this.blocks[this.currentBlock]
let blockType = block.getType()
let type = blockType
// 关于 atomic 类型,假如当时类型在 this.customBlockModules 傍边,则 export 出烘托数据以及当时 type
if (block.getEntityAt(0)) {
const entity = this.contentState.getEntity(block.getEntii X x u Z i . PtyAt(0))
type = entity.getType()
if (this.customBlockModules.has(type)) {
const en; r a z | 7 c _tityData = entity.getData()
this.output.push({
type,
data: entityData
})
this.currentBlock += 1
} else {
// 不在 this.customBlockModules 傍边,仍依照富文本导出
proceU V 6 } a ~ n qssRichText()
}
} else {
processRichText()
}
}
// 其他美化或整理工作,比方接连富( . x r ^ g文本区块的兼并
return this.finalOutpuo 8 G R F A z M Ht
}

这儿不同于前期 MarR k B [ R [ 3 ; Gkdown 修改器的要害3 ? 3 M G点首要有两处:

  • 咱们监听修改器区块的 onBlur 事件,在此事件触发时,开始生成成果数据
  • “所见即所得”——不再需求在手动实时解析烘托完结。因为N 6 6 $ a ) X 6 Dr, K @ 9 W Maft.j~ . )s 是一个依据 React 的修改器,咱们可以直接在修改器中烘托出一个 React 组件

如下图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

以上两个特征也正是依据 Draft.js 的多功用修改器优于 Markdown 修改器的要害点。

可插拔、可移植的插件化和: 7 F V T o J F组件化规划

多功用修m t + Q z a改器的多功用不是说说而已,为了支撑海量功用需求,且考虑到便利第三方功用扩展,咱们规划了良好的修改器插件体系。**现在项目3 . h :中运用了 11 个插件,它们涵盖了:**刺进代码、刺进公式、刺进链接、刺进引证、刺进视频、仿制粘贴复原内容、刺进图片、刺进要点款式、刺进注解等。**项目还沉淀出来海量事务组件,包含:**页面喵点组件、Banner 图组件M g 7、Sku 卡片组件、各类按钮组件、滚动列表组件、图片画廊组件等。全部的组件和插件原则上都是可以面v & L向社区、面向第三方运用的,一起后续方案只需求一个 NPM 包即可接入一个新的功用或新的自定义组件类型。**这也为后续的组件商场规划、no/low cod9 F c Re 规划打下了根底。

在修改器初始化时,咱们注册并实例化各种插件以及自定义组件。因为咱们多功用修改器的理念就包含了结构化和数据化,全部的这些插件和组件都可以依托 decorator 进行解析,这也就意味着:从别的一处修改器实例中仿制任何内容(包含自定义组件)到当时修改器,都G S & T P N z t可以直接复原数据,无缝完美支撑组件的仿制粘贴功用。

多数据源支撑

任何一项技能立异和更迭,都要考虑前史包袱和前史债款的处理。多功用修改器也不例外,前面说到,前史修改内容是运用 Markdown 格局的。以运营页面生成器场景为例,前史活动页面 A 对应的后端存储数据是 Markdo4 4 s T Jwn 字符串。咱们在运用新的多功用修改器替换旧的 Markdown 修改器后,假如运营同学想再次修改活动页面 A,新的多功用修改X & , p R %器上天然就要兼容前史内容。

**为此咱们的方案是:**在修改器中接纳到E K O s : |数据源后,假如嗅探为前史 Markdown 格局,那么先运用 marked.js 将此 Markdow/ z : h o .n 格局内容转化为富文本内容,再依据富文本内容转化为 Draft.js 支撑的不行变数据结O s * 2 i 6 c构。

总结一下,关于修改器初始化时的数据源(rawContent)| n P % – 7处理流程如下图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

关于修改器获取的数j 4 1 / }据 rawContent,咱们运用 isDraftJson 东西函数判别该 rawCol ) l 2 Hntent 是否可以被多功用修改器以 Draft.js 支撑的数据解析:假如可B l & X ] I z以,则证明 rawContent 为由z + z U v新的多功用修改器提交的数据,可以直接运用并恢复出修改器内容。假如 isDraftJson(rawCon_ ~ ^ K | ltent) 判别为 false,那么就表明无法被 Dra} U _ Wft.js 解析,需求兼容前史 Markdown 语法,由 marked.js 解析出富文本后再交给 Drafty b :.js 处理,由富文本生成 Draft.js 的不行变数据;假如E ! U Q y 8 0 x解析都失败,则直接将 rawContent 视为 textarea 内容,直接填入到修改器傍边。

图中并未画出假如~ ? 1 $ rawContent 为空(或不存在)时的处理办法。实践上,假如 rawContent 为空,咱们运用 ContentState.createFromTen O e w w o R & ^xt(”)s 8 u W E 1 办法生成一个初始化为空内容的不行变数据。

实践进程因为c , $ W _ i , 7前史包袱原因,关于多数据源的支撑完结更为杂乱,这过于特殊,咱们不再展开。

继续打磨运~ V z 9 / 9 V x u用体会

修改器一个十分重要的论题便是体会。信任很多人都经历过修改器的体会之殇} 7 1 (:“输入卡顿、怪异的% a z光标方位”等,但这儿我以为没有必要剖` t [ k F Y析传统修改器的体会优化论题,更有含义的是从咱们特有的多功用修改器d i t , | H特色入手,聊一聊用户体会。

举一个例子:依照 Draft.js 的规划,每一个区块之间上下都会有个空行。如图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

这样会导致提交修改器? d n } A ?内容时,生成的自定义区块数据前后会包含了两个空区块数据,终究导致烘托出的页面也会包含两个空白行,直接影响页面规划作= m x k % z K u用。社区上关于这个规划的 issue 评论不少,比方 Empty line o^ P * k o E O 2n addi8 @ U k O ng atomic block。

**事实` G [ v R : ] o J上,这是为了灵敏D t g # m ? .地在自定义区块前后增加或删除内容。**设想,假如咱们接连增加了三个自定义区块——Sku 卡片 A,Sku 卡片 B,Sku 卡片 C。**假如 A,B,C 之间没有空行,那么咱们怎么在卡片 A 和卡片 B 之间刺进一个新的卡片 D 呢?**假如 ABC 卡片彼此之间坚持一个空行,那么运用者可以用光标定位到 AB 之间的空行,再刺进卡片 D。这便是自定义区块前后主动存– Q = P n * #在空行的含义。

有的开发者或许会想:咱们可以坚持这个空行的存在,在终究生成的数据时,主动将空行删除不就可以了吗?事实上,拿到 Draft.js 修改器的数据时,咱们无法判别是用户自主回车创立的预期中的空行,仍是自定义区块自带的前后空行,因而无法直接在成果数K + n g 5据上粗暴地移除空行。

为了达到更好# z L E ; * t的运用体会:咱们开发的 Focm c y Z ^ ; Z usPlugin 插件,高雅地处理了问题:依然是每一个自定义区块前后不保留空行,可是运用 FocusPlugin 插件,使得每一个自定义区块都可以被点击选中,或许用键盘上下键遍历选中,选中之后可以直接摁下回车键* ] a A K,增加空行,乃至可以摁下 delete 键,删除该区块。如图:当自定义区块a c M u S D被选中时:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

终究这套x 4 e n依据 FocusPlugin 插件的方案O } 7 , v l n l k使得交互更加顺利天然,达到了更好的作用。依据此,咱们可以十分顺利地完结自定义区C 1 B块的更改:比方当时选中区块为一个 id 是 1234 的 Sku 卡片,假E Q ] f如运营需求替换为 id 是 5678 的 Sku 卡! / f R L V R a Y片,只需求挑选当时区块,选中S t # s t K s之后在右侧呈现的修改区中更改 id 内容,确认后; H 5 a z J ~ y即完结替换,如图所示:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义
「可视化搭建系统」——从设计到架构,探索前端的领域和意义

依据 FocusPlugin 插件,以` Q ? M j F f 9批改当时 Sku 卡片 id 为例,id 进行批改后,发送获取新的 id 的数据,并在数据成功获取后调用 modifyAtomicBlock(entityKey, data) 办法,触发 replaceEnti7 5 , 8 ( : x 1tyData(editorState, entityKeyi O @ Z _ + v e T, data)( ; C M `法进行$ 3 Z 5 ;修改器不行变数据的更新,并由 handleEditorStaQ 3 teChange 办法一起更新状况,终究反应在修改器视N D _ G t N x L图中。

这一修改产生进程总结图为:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

运用体会确实不是一蹴即至的的工作,这是一个需求继续迭代优化的进程。通过不断地打磨,Versaj q ) k – i _tile Editor 终究趋于稳定。现在 Vek d Z 9 Mrsatile Edi6 z 5 C j ` N Ator 现已支4 p d ) 6 C $ 3 J撑了数百量级的页面建立,以知乎投进的页面为例,包U / * 1 } 6 H O含但不限于:

  • 高考直击
  • 抗击疫情——问候奔赴一线的逆行者
  • 爱要「盐」选
  • 朗朗活动页面——每个爱音乐的孩子必听的大师课
    等高流量内容。

页面. . ^ g b + m模版支撑

Daft.js 修改器内容是彻底依据数据状6 , B _况的,它运用了不行变数据库进行数据的更新操作,秉承纯函数式更l _ = 0新,因而天然关于“韶光游览(Undo/Redo)”的特性可以良好支撑。另一方面,全部皆数据也让咱们完结“页面模版”功用十分简略而奇妙。

咱们可以将0 1 j全部模版拆分为几个大的自定义区块,并创立这个活动模版所对应的数据:比方关于模版 A:头部为一个头图 Banner,咱们可以修改器中创立一个由占位图表明的 Banner 图片;第二区块为电子T ] s @ Z ! B O ?书榜单 Top1* q |0,即可在修改器中创立一个 Ranking 组件,并由恣意占位 10 个电子书数据填充,以此类推。提交数据之后,即可取得描绘这个页面模版@ 4 Y 0 4的数据。

当运营在创立页面,并挑选运用「排行榜模版 A」时,咱们就用现已提早预制的数据作为 rawContentT # { m 9 I V U 进行修改器初始化。得到模版后,运营即可增加批改,快速完结模版页面创立。

全体流程如下:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

其他细节

到此为止,咱们介绍了社区方案和咱们自己继续迭代的方案。其中还有一些小的细节在这儿简要带过,首要包含:预览、排版、安全性、装备体系几个方面阐x ? : E } z 0 y T明。

“所见即所得”使得运营修改活动效( G – E z . [率大幅进步,可是在修改器提交发布和推行之前,仍是需求一个4 N l U ]完好X B = ? v的可预览页面地址供进一步回H c 1归。因为这些推行页面都是面向移动端,因而咱们在这个多功用修改器兼页面生成器的产品规划上,预留有页面m v 9 . 6发布地址和二维码生成功用,进一步优化运营运用体会。如图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

另一方面,咱们关于页面文字的编审有着严厉的要求,比方:不能运用中文引号,需求运用「」;英文和数字与Y ) ^ ; + j ( v Y其他汉字之间需求预留; 5 6 ! `一个空格;乃至标点的方位也有严厉标准,需求完结传统相似“标点悬挂、标点挤眼”等一系列排版需求。因而,该多功用修改器兼页面生成V $ E $ ? g 1器装备了可插拔的主动排版才能,首要完结主动排版标准的审校和批改,如图:

「可视化搭建系统」——从设计到架构,探索前端的领域和意义

一个页面Z X A 0 t往往无N d d F L Y法只由修改器生成,或许还包含装备内容。这些装备需求咱们用进入修改器之前的表单来承载,K + f R表单填写结束,生成根底装备数据后,再进入修改器进行创作。表单是页面中数据交互的根本方式,关于: ~ j $ ( T非开p o L 发人员运用也没有运用门槛,可是牢记不行将表单规划的过于杂乱。一起要留a : 9 !意,修改体系和装备体系需求解偶的原则。

**前面说到修改器便是生产东西,修改器的效能就意味着生成效率。m p * ? p @ # O Q一旦修改器呈现线上问题,那么就会直接影响V + J ; s s正常的X J P生产活动。**因而,为了确保修改器的安全性和强健性,咱们参加了测验环节。首要包含:单元测验,UI 测验。单元测验首要验证要害函数和办法的正确性,比方上面说到的 autoFormat 办法,各种插件的输入和输出正确性校验,数据批改的东西办法校验等;UI 测验首要依托 Enzyme,来确n G M保要害交互的正常运行。

最终,其他涉及点比方:一键w u . 7 [ o换肤、字数统计等因为篇幅原因,这儿都不在胪陈。

富文本修改器是一个深坑,Draft.js 尽管背靠 Facebook 团队,但也一直在深坑中挣扎,咱们此间开发进程确实是一部血泪史,但咱们团队也在此方向积累了丰富的经历C g e m ] P y #,后续W ] [ 2 g ]技能细节也会逐个进行分享,请继续重视订阅。

总结

**我一直在考虑,什么样的文章可以给读者带来真正的考虑和启迪。**一方面鞭辟入里解说言语特性和规划,深入技能细节,庖丁解牛般的剖析是咱们所需求的,这类文章需求靠代码说话;另一方面,总结整理技能趋势,从更高的视点叙述方案的落地和演进,更是对大局观和格局的培育,这关于团队的技能规划和舵向同样至关重要。Z ^ 7 z @ W

这篇文章浅显总结了业界在「可视化页面建立」技能探究的方方面面,并整理了各种相关技能博客和剖析文章。咱们还介绍了修改器技能和修改器技能所能给% E 4 m c h L & n「可视化页面建立」带来的破局和立异。在此根底上,咱们/ / W . Q 6 =更是从一个自研的公司级「可视化页面建立体2 T P d , o }系」入手,从探究阶段到成熟阶段的演进前史进行了介绍。

事实上,「可视x 1 O ) [ B q J化页面建立体系」的论题还远为结束:咱们正在此方向上探究更多或许,「微组件/微前端」,「页面归因才能」、「no/low code 技能」、「自定义组件埋点以及 A/B 流量才能」、「运行时的组件构建和烘托方案」,乃; s f & V至「Serveless」、「云端 Ix 9 ) _ [DE」等。后续咱们将会继续产出相关文章,请读者继续重视:技能博客,咱们也在广泛求贤。

回到文章开篇所说到的那个问题上:“前端开发的难点到底在什么地方?”,我想已有答案的开发者将继续优化答案,依然不知l @ = ) / =道的开发者很快将会找到自己的答案。

Happy coding!

发表评论

提供最优质的资源集合

立即查看 了解详情