Skip to content
On this page

模板设计


模板设计

由之前的篇幅介绍,我们大致清楚我们的目标是搭建一套与编辑器解耦的模板来支撑未来多种多样的玩法。那么模板是由谁来提供呢?很明显的答案是由对应的业务开发同学来不断建设和丰富模板库。既然模板库独立于编辑器且由相关业务线开发同学自己来来发,而开发规范因为团队的不同可能会有所差异,所以我们设计一套具有相关约定且框架无关的模板体系,来满足多业务线同学的开发诉求。无论您使用 ReactAngularVue小程序 可视化搭建系统都可以适配,因为底层使用了一种通用的描述语言来描述页面的结构、表现、行为等属性。

其次还需要考虑一个问题:模板独立于编辑器,但是编辑器是需要对模板组件进行编排,对模板数据进行编辑。那么如何显示模板和编辑器之间的联动?针对以上问题,我们可以设计这样的一套架构来解决:

下面我们将会以 vue 模板为例,来实现一个可以独立于编辑器的模板页面。

初始化模板页面

假设某一个团队用的 h5 技术栈是基于 vue 2.x 的,那么我们开始基于vue cli来动手了:

shell
$ vue create coco-template

然后选择 vue 2.x 模板来初始化项目,最终我们会得到一个 coco-template 项目。接着我们思考一个问题:因为我们设计的可视化搭建的操作对象是面向业务方同学,传统的开发模式可能是单页一个大组件代码从头写到尾,但这样并不利于页面的可视化编排,因为可视化编排需要按照组件的维度对页面布局进行调整。所以我们要对模板的编写方式进行约束,我们需要按照组件开发的方式制定目录结构如下:

bash
coco-template
...
├─package.json
├─src
|  ├─App.vue
|  ├─main.js
|  ├─components
...

components 中将会放置我们的相关页面组件。

模板组件设计

接下来我们按照实际业务需求为例,来介绍如何设计模板组件。假设我们现在需要实现这样一个基础的信息填写表单:

按照上面所描述的,我们需要按照组件化的方式来开发这个模板,我们可以按照组件样式的形式对页面进行组件拆分:

  1. 头部 banner 组件
  2. 内容输入组件
  3. 内容提交 button 组件

这样设计本身并无太大问题,可是我们需要注意的是 button 组件是无法脱离于内容输入组件单独存在的,因为其中包含了内容输入组件所需的业务逻辑。所以他一定是需要和内容输入组件同时存在,不然也就变得没有意义。(暂不考虑低代码模式) 所以我们可以按照业务功能的维度划分成2个组件:

  1. 头部 banner 介绍组件
  2. 内容填写 form 组件

接下来再调整我们的目录结构如下:

bash
coco-template
...
├─package.json
├─src
|  ├─App.vue
|  ├─main.js
|  ├─components
|  |     ├─form
|  |     ├─banner
...

props schema 设计

项目基础的结构我们已经调整过了,接下来开始开开心心写代码了,比如写一个 banner 组件,我们需要知道 banner 中哪些信息是可以通过配置化来动态设计的。比如 banner 的图片和 banner 的点击跳转地址。那么我们的组件写起来可能是这样的:

html
<template>
  <a :href="obj.link">
    <img
      :src="obj.src"
      width="100%"
      alt="图片"
    />
  </a>
</template>

<script>
export default {
  name: 'banner',
  props: {
    obj: {
      type: Object,
      default: () => {}
    }
  }
}
</script>

到这里,我们的一个 banner 组件 开发完了....?先别急,再想一下:我们虽然将组件的可编辑的属性通过了 props 来表述出来了,但是外部如何来感知我们具体的数据格式和类型? 对页面的可编辑部分, 需要准确描述可编辑部分所需的配置数据; 配置数据是异构的, 不同页面、不同组件的配置数据各不相同。 所以需要对不同页面、不同区块定义各自配置数据的数据结构和字段类型。 理想的配置数据格式为 JSON, 因为其格式灵活, 前端友好; 理想的配置数据描述格式为 JSON Schema, 因为一方面是国际化标准,另一方面我们不需要再造一套标准,减少很多时间。 那么接下来我们按照 JSON Schema 的规范来表述一下我们的 banner 组件 props。在 banner 组件 下再建一个 package.json 文件:

json
{
  "type": "object",
  "properties": {
    "src": {
      "title": "图片地址",
      "type": "string",
      "format": "image"
    },
    "link": {
      "title": "跳转链接",
      "type": "string",
      "format": "url"
    }
  },
  "required": [
    "src"
  ]
}

这样我们就用 JSON Schema 的规范加上一点点拓展,完成了对组件可编辑 props 的描述:我们需要一个 图片地址,一个 string 类型的数据,一定要是 image 交互形式。一个 点击跳转链接, 需要是 string 类型的数据结构,一定要是 url 交互形式。而且 src 属性必填。

form 组件也是同理,然后再来看一下我们的目录结构:

bash
coco-template
...
├─package.json
├─src
|  ├─App.vue
|  ├─main.js
|  ├─components
|  |     ├─form
|  |     |  ├─index.vue
|  |     |  └package.json
|  |     ├─banner
|  |     |   ├─index.vue
|  |     |   └package.json
...

对应的 JSON Schema 如下:

json
{
  "type": "object",
  "properties": {
    "btnText": {
      "title": "按钮文案",
      "type": "string"
    },
    "action": {
      "title": "提交接口地址",
      "type": "string",
      "format": "url"
    }
  },
  "required": [
    "btnText"
  ]
}

总结

上面我们已经基本完成了一个最出的模板结构,接下来我们带着问题在去思考一下:组件描述和设计我们都ok了,那么如何把我们有哪些组件以及组建的描述信息告知给编辑器呢?🤔 我们下章继续介绍。