tuoxiansp / blog Goto Github PK
View Code? Open in Web Editor NEW个人博客
个人博客
这篇文章并不是谈如何分离界面代码和逻辑代码,而是彻彻底底告别使用代码书写界面的方式 — 设计师交付界面给工程师写代码逻辑。工程师不写哪怕一行界面代码,完全不关注界面绘制。
首先,组件化是一切的基础。
然后在组件化的基础上,让设计师能够使用组件拼装出界面。
设计师最终交付的其实就是一段界面数据。这段数据可以轻易在代码里被实例化为界面,并展示在用户眼前。
只不过我们最好是对工程师隐藏这一细节,对工程师来说,他就是在代码里引入了一个界面,并能够通过 id 获取某一个组件句柄,然后进一步写代码给组件赋值,把真实数据交由组件渲染成界面并最终展示给用户。
说到这里,你一定发现了:上述的思路,一点都不新鲜。
我自己也有见过和曾经用过。
这些已有的方案的具体细节我也忘记了。同时我很懒,不太情愿去翻已有的方案做对比。把我的方案说出来就好。
要实现告别界面代码(广义上工程师不再关注界面代码),我认为很关键的一点(也是至今未见实现的)就是界面要被彻底数据化,不带任何逻辑。
正因为不带任何逻辑,才能被设计师制作并交付。
为了让工程师不写界面代码,设计师必须交付完整的界面,不遗漏任何需要工程师后续写界面代码填补的交互细节。
为了实现这一点,我们需要解决一个可视化界面编辑中极为常见的问题:
界面通常是有逻辑的。我们很难摆脱逻辑来描述一个界面。
举个例子:我有⚡️和🌧两个基础的组件,现在需要根据今天的天气,来决定展示⚡️还是🌧。
可能有人会粗略一想:简单啊!写个天气组件把这俩组件集成一下不就行了。
isLightening => isLightening ? ⚡️:🌧
仔细想想,会发现事情并没有那么简单。
这种带一丢丢逻辑的组件,给我一天,能想出一万个。比如根据雷电天气的强度,我想展示 ⚡️、⚡️⚡️ 和 ⚡️⚡️⚡️ 怎么办?
我们不可能事先准备好所有可能用到的组件,只能给出最最基础的展示元素,交给设计师们自由发挥。
那么问题还在这里:
类似 isLightening => isLightening ? ⚡️:🌧
这样的组件,要如何在设计中表达呢?
我给出的办法是:使用集合。
设计师需列出组件的所有状态,所有这些状态的集合,便构成了这个组件。
于是,上述例子我们可以给出的解便是:
[⚡️, 🌧]
和[⚡️, ⚡️⚡️, ⚡️⚡️⚡️]
而把这样的数据导入到程序里,我们可以轻松地使用代码来控制最终的展示。
伪代码如下
() => {
const isLightening = getIsLightening()
return isLighting ? 0 : 1 //0 和 1 对应集合中的 [⚡️, 🌧]
}
最后,我把按照上述方案,以所有状态的集合来描述界面的方法称为界面的有限表述。
相对应的,只按照当前显示的内容描述界面的方法,称之为界面的单一表述。
编辑器维护这颗树的数据,对外开放增删改查,撤销重做等接口。
未来甚至可以做到通过不同的播放器来适配不同的平台。
树上的每一个组件通过输入属性决定自己的
组件可以通过组件编辑器的接口知晓是否处于编辑状态。
编辑状态下,组件可以提供交互编辑自己的输入属性。
这么做有两点好处
例:设计一个 Text 组件逻辑
当处在编辑状态下,显示光标,文字为可编辑状态
Strikingly 正是实践该理念的优秀产品[www.sxl.cn]
进一步,我们可以利用组件可以在编辑状态下,提供自己的交互逻辑编辑自身属性这一特性,我们可以设计出一个特殊组件—视图组件。
视图组件本质就是组件。只不过视图组件的属性是组件列表。
可以在视图组件中可视化增加、删除、调整组件的顺序,通过视图组件,我们获得了编排组件的能力。
视图组件的交互很大程度上决定了可视化编辑器最终是什么样子,如何使用。
例如:
根据具体目标可以设计出不同的视图组件,甚至可以多个视图组件共存。
有了视图组件,我们就可以开始往视图组件里“注入”组件、寻找需要的组件定制自己的界面了。
很多界面编辑器可能底层并不如此灵活,但是表面上都是按上述那么做的。
截止这一步,已经可以获得足够优秀好用的界面编辑器了。如 strikingly 、structor 等。
[https://github.com/ipselon/structor]Structor - React UI 编辑器
这是一套非常常见的理念:编辑器负责告诉组件它应该在哪里、用户选择了什么样的个性化方案。而最终能实现啥由组件库决定。
这里其实对组件的设计提出了非常大的挑战:编辑器把一块田地分给了你,你要做到尽量灵活地实现用户更多需求。
这里提出一个我认为非常具有代表性的问题:如何灵活地设计一个 Nav Bar 。
对照上图,我们代入前面的设计**,可以设计出如下的属性数据结构:
{logo, [{icon, name}]}
菜单文字可以自由选择是否有 icon ,有就给显示。预先提供了一些灵活性呢。
接下来考虑如何实现点击菜单触发相应的界面变化。
…
太难了,还是不考虑了吧。
Strikingly 就没有做这个事情。在 strikingly 里整个模板就是一个完整的程序,菜单也是这个程序的一部分,所以可以轻松实现菜单点击的页面联动效果。但是,如果你想保留这个菜单,但是页面内容部分换成其他的。嗯,strikingly 没有提供这个功能。
归根结底,我作为一个组件,拿着编辑器分配给我的一亩三分地,要能在自己的地盘上花式满足用户需求已经非常不容易了,现在还要我去管其他地方怎么显示?
—太难了。
于是呢,干脆就把要交给我管的地也给我吧。
用户点击菜单1,我就让菜单下面一大块显示 1 号地,点击菜单2,就显示 2 号地……
然后不知道 1 号地,2 号地具体显示什么怎么办呢?
也好说,让编辑器来分配新的组件过来管理就行了。
说了一大堆,总算是成功引到了正题—视图注入点。
任何组件都可以通过显示视图组件的方式,提供了视图的注入点,交由用户进一步编排组件。
举上面 Nav Bar 的例子,Nav Bar 组件把整个屏都占满,bar 的下方留下的大块空白区域是一个视图组件,用户可以使用这个视图组件的编排组件能力,把空白区域用其他组件填满。Nav Bar 这里就只负责控制空白区域是显示视图组件1还是视图组件2,至于视图组件1和2到底显示些什么,完全不用管。
再举一个 Nav Bar 上的细节:显示菜单的位置也可以通过放置视图组件来处理,用户往视图组件里加 Text 就显示文字,再往里添一个 Icon ,那就是文字+图标。还可以调换文字和图标的位置,变成不常见的左文字右图标,甚至左右俩图标,中间是文字。随心所欲。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.