作者 | 郑嘉涛(羣青)
上篇我们讲了故事发生的背景,也简单阐述了组件及协议的设想:
一、丰富的通用组件库。
二、组件渲染能力,将业务组件渲染成通用组件。
三、协议渲染能力,以处理复杂交互。
以及这种开发模式带来的好处:
这样的设计初衷旨在大量减少前端工作,尤其是前后端对接方面,甚至可以认为对接是“反转”的,体现在两个层面:接口定义的反转和开发时序的变化。
如果你对我们的设计思路还不够了解,可以先阅读上篇:《疯了吧!这帮人居然用 Go 写“前端”?(一)》。
本篇我将更细致地介绍组件渲染和协议渲染,以及如何通过这两种渲染做到前端彻底不关注业务。
当然最后你会发现是否 REST 并非重要,重要的是合理的切分关注点,而框架只是运用切分的帮助手段。
具体而言,针对一个通用组件,如何完成业务逻辑?
比如说下面同样的一个卡片组件(Card),它由通用的元素构成和呈现:
cardComp:
props:
titleIcon: bug-icon
title: Title
subContent: Sub Content
description: Description
kanbanCardComp:
props:
titleIcon: requirement-icon
title: 一个简单的需求
subContent: 完成容器扩容不抖动
description: 需要存储记录用户的扩容改动,通过调用内部封装的 k8s 接口以实现。
taskCardComp:
props:
titleIcon: flow-task-icon
title: buildpack (java)
subContent: ✅ success
description: time 02:09, begin at 10:21 am ...
func Render(ctx Context, c *Comp) error {
// 1. query db or internal service
// 2. construct comp
return nil
}
// 伪代码,精简了数据结构和条件判断
func Render(ctx Context, c *Comp, ops string) error {
if ops != "view" {
doOps()
}
// continue render (aka re-render)
return nil
}
state
中体现,仍然是需求卡片的例子:kanbanCardComp:
props:
titleIcon: requirement-icon
title: 一个简单的需求
subContent: 完成容器扩容不抖动
description: 需要存储记录用户的扩容改动,通过调用内部封装的 k8s 接口以实现。
state:
ticketId: 42
这里我们需要引申一个实际的问题,以 web ui 为例:当用户访问一个页面时,这个页面并非只有一个组件,比如事项看板页面,就有诸如过滤器、看板甬道、事项卡片、类型切换器等多个组件。
protocol.yaml:
组件初始值
component:
kanbanCardComp:
state:
ticketId: ??
operations:
click:
reload: true
ticketDetailDrawerComp:
state:
visible: false
ticketId: ??
operations:
close:
reload: true
渲染过程
rendering:
__Trigger__:
kanbanCardComp:
operations:
click: set ticketDetailDrawerComp.state.visible = true
ticketDetailDrawerComp:
operations:
close: set ticketDetailDrawerComp.state.visible = false
__Default__:
kanbanCardComp:
state:
ticketId: {{ url.path.2 }}
ticketDetailDrawerComp:
state:
ticketId: {{ kanbanCardComp.state.ticketId }}
__Trigger__
部分,操作类型的渲染会临时性地修改部分组件的状态;其次执行 __Default__
部分,进行组件之间的数据绑定;最后会进行单个业务组件的渲染,这部分在第一篇文章中已经详细阐述。rendering
不过只是过程数据,最终需要转化成平凡的值。以这个例子而言,(假设用户进行了卡片的 click 操作)协议最终渲染成:component:
kanbanCardComp:
props:
后端组件基于 ticketId=42 渲染出的具体数据
titleIcon: requirement-icon
title: 一个简单的需求
subContent: 完成容器扩容不抖动
description: 需要存储记录用户的扩容改动,通过调用内部封装的 k8s 接口以实现。
state:
ticketId: 42
operations:
click:
reload: true
ticketDetailDrawerComp:
props:
后端组件基于 ticketId=42 渲染出的具体数据
...
state:
visible: true
ticketId: 42
operations:
close:
reload: true
paginationBar
进行了一次操作 next
,操作处理时便能拿到所需数据。components:
paginationBar:
state:
currentPageNo: 1
operations:
next:
reload: true
meta:
pageNo: 2
hierarchy:
root: ticketManage
structure:
ticketManage:
head
ticketKanban
head:
left: ticketFilter
right: ticketViewGroup
components:
ticketManage:
type: Container
head:
type: LRContainer
...
前端关注什么? 后端关注什么?
框架/协议应该关注什么?
欢迎从我们的官网 erda.cloud 了解更多关于 Erda Cloud 产品的最新资讯。也欢迎关注我们的 Github repo,我们的代码已经全部开源,点击【阅读原文】即可参与,期待你的 star ~~~