Code Monkey home page Code Monkey logo

blog's People

Contributors

tuoxiansp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

blog's Issues

谈真正分离代码与设计

告别界面代码 - 真正分离代码与设计

这篇文章并不是谈如何分离界面代码和逻辑代码,而是彻彻底底告别使用代码书写界面的方式 — 设计师交付界面给工程师写代码逻辑。工程师不写哪怕一行界面代码,完全不关注界面绘制。

如何做?

首先,组件化是一切的基础。

然后在组件化的基础上,让设计师能够使用组件拼装出界面。

设计师最终交付的其实就是一段界面数据。这段数据可以轻易在代码里被实例化为界面,并展示在用户眼前。

只不过我们最好是对工程师隐藏这一细节,对工程师来说,他就是在代码里引入了一个界面,并能够通过 id 获取某一个组件句柄,然后进一步写代码给组件赋值,把真实数据交由组件渲染成界面并最终展示给用户。


说到这里,你一定发现了:上述的思路,一点都不新鲜。

我自己也有见过和曾经用过。

这些已有的方案的具体细节我也忘记了。同时我很懒,不太情愿去翻已有的方案做对比。把我的方案说出来就好。

我的方案

要实现告别界面代码(广义上工程师不再关注界面代码),我认为很关键的一点(也是至今未见实现的)就是界面要被彻底数据化,不带任何逻辑。

正因为不带任何逻辑,才能被设计师制作并交付。

为了让工程师不写界面代码,设计师必须交付完整的界面,不遗漏任何需要工程师后续写界面代码填补的交互细节。

为了实现这一点,我们需要解决一个可视化界面编辑中极为常见的问题:

界面通常是有逻辑的。我们很难摆脱逻辑来描述一个界面。

举个例子:我有⚡️和🌧两个基础的组件,现在需要根据今天的天气,来决定展示⚡️还是🌧。

可能有人会粗略一想:简单啊!写个天气组件把这俩组件集成一下不就行了。

isLightening => isLightening ? ⚡️:🌧

仔细想想,会发现事情并没有那么简单。

这种带一丢丢逻辑的组件,给我一天,能想出一万个。比如根据雷电天气的强度,我想展示 ⚡️、⚡️⚡️ 和 ⚡️⚡️⚡️ 怎么办?

我们不可能事先准备好所有可能用到的组件,只能给出最最基础的展示元素,交给设计师们自由发挥。
那么问题还在这里:

类似 isLightening => isLightening ? ⚡️:🌧 这样的组件,要如何在设计中表达呢?

我给出的办法是:使用集合。

设计师需列出组件的所有状态,所有这些状态的集合,便构成了这个组件。

于是,上述例子我们可以给出的解便是:

[⚡️, 🌧][⚡️, ⚡️⚡️, ⚡️⚡️⚡️]

而把这样的数据导入到程序里,我们可以轻松地使用代码来控制最终的展示。

伪代码如下

() => {
    const isLightening = getIsLightening()
    return isLighting ? 0 : 1  //0 和 1 对应集合中的 [⚡️, 🌧]
}

命名

最后,我把按照上述方案,以所有状态的集合来描述界面的方法称为界面的有限表述。

相对应的,只按照当前显示的内容描述界面的方法,称之为界面的单一表述。

可视化界面编辑器设计

一 设计理念

界面、编辑器、播放器

界面是一棵组件树。
image

界面编辑器就是对这棵组件树进行编辑和持久化的工具。

编辑器维护这颗树的数据,对外开放增删改查,撤销重做等接口。

界面播放器输入组件树,可以得到界面展示

未来甚至可以做到通过不同的播放器来适配不同的平台。

组件

树上的每一个组件通过输入属性决定自己的

  • 展示
  • 交互

组件可以通过组件编辑器的接口知晓是否处于编辑状态。
编辑状态下,组件可以提供交互编辑自己的输入属性。

这么做有两点好处

  • 编辑器关注的始终只有组件树,组件的属性,无需关注如何编辑组件属性
  • 组件可以为自己的业务需要,量身定做最适合的交互来编辑属性

例:设计一个 Text 组件逻辑
当处在编辑状态下,显示光标,文字为可编辑状态
image

不处于编辑状态,则显示文本内容
image

Strikingly 正是实践该理念的优秀产品[www.sxl.cn]
image

视图组件

进一步,我们可以利用组件可以在编辑状态下,提供自己的交互逻辑编辑自身属性这一特性,我们可以设计出一个特殊组件—视图组件。

视图组件本质就是组件。只不过视图组件的属性是组件列表。
可以在视图组件中可视化增加、删除、调整组件的顺序,通过视图组件,我们获得了编排组件的能力。
视图组件的交互很大程度上决定了可视化编辑器最终是什么样子,如何使用。

例如:

  • 我们可以在视图组件里放一个输入框,通过输入组件名称,回车,来添加组件,也可以通过感知拖进来的组件,来更友好地添加组件。
  • 视图组件可以是一个默认的 block ,添加进来的组件都基于默认的流式布局。也可以是一个经过扩展的有具体长宽的区域,可以把组件拖到区域的任何一个位置,获得坐标位置,成为一个绝对定位的容器。

根据具体目标可以设计出不同的视图组件,甚至可以多个视图组件共存。

视图注入点

有了视图组件,我们就可以开始往视图组件里“注入”组件、寻找需要的组件定制自己的界面了。
很多界面编辑器可能底层并不如此灵活,但是表面上都是按上述那么做的。
截止这一步,已经可以获得足够优秀好用的界面编辑器了。如 strikingly 、structor 等。
image

[https://github.com/ipselon/structor]Structor - React UI 编辑器
这是一套非常常见的理念:编辑器负责告诉组件它应该在哪里、用户选择了什么样的个性化方案。而最终能实现啥由组件库决定。
这里其实对组件的设计提出了非常大的挑战:编辑器把一块田地分给了你,你要做到尽量灵活地实现用户更多需求。

这里提出一个我认为非常具有代表性的问题:如何灵活地设计一个 Nav Bar 。
image

对照上图,我们代入前面的设计**,可以设计出如下的属性数据结构:
{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 ,那就是文字+图标。还可以调换文字和图标的位置,变成不常见的左文字右图标,甚至左右俩图标,中间是文字。随心所欲。

总结

  • 可视化编辑从功能上分是两大块:编辑器和播放器
  • 界面是一棵组件树,编辑器做的就是对这棵树进行编辑,和数据持久化
  • 组件通过输入的属性决定如何显示和交互,这一点同样适用于编辑的过程
  • 编辑器需要至少一个编排组件的组件 — 视图组件,视图组件可替换,籍此实现了编辑器的可扩展性。
  • 任何组件都可以通过内嵌视图组件来实现更高的灵活性。

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.