From 463409cd567cd67ef65f25748e693e9324339134 Mon Sep 17 00:00:00 2001 From: 刘汉宸 Date: Fri, 26 Feb 2021 17:22:48 +0800 Subject: [PATCH] feat: 修改SchemaForm组件,更新文档 --- examples/router/routes.js | 6 ++++++ examples/views/docs/component/schema-form.md | 527 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------ examples/views/docs/develop/schema/introduce.md | 260 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ packages/schema-form/index.vue | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------ 4 files changed, 699 insertions(+), 204 deletions(-) create mode 100644 examples/views/docs/develop/schema/introduce.md diff --git a/examples/router/routes.js b/examples/router/routes.js index 0505211..bea3b2f 100644 --- a/examples/router/routes.js +++ b/examples/router/routes.js @@ -134,6 +134,12 @@ const _develops = [ group: '方案开发', children: [ { + path: 'introduce', + name: 'developSchemaIntroduce', + meta: { title: '介绍' }, + component: () => import('@/views/docs/develop/schema/introduce.md'), + }, + { path: 'schema-form', name: 'developSchemaForm', meta: { title: 'Schema Form 方案表单' }, diff --git a/examples/views/docs/component/schema-form.md b/examples/views/docs/component/schema-form.md index 566a59d..e4f710c 100644 --- a/examples/views/docs/component/schema-form.md +++ b/examples/views/docs/component/schema-form.md @@ -1,83 +1,116 @@ -# Form 表单 +# Schema Form 方案表单 -根据JSON Schema配置自动生成表单 +通过配置JSON Schema的方式快速生成一个表单 ## 基础用法 -配置`list`属性设置JSON Schema配置列表 +`schema`设置配置项,其中**props**参数与`z-form`组件参数相同,**items**则对应`z-form-item`组件,默认参数为``组件与`z-form-item`组件参数的并集。 -
- -::: snippet `v-model`值动态改变,支持初始化 +::: snippet 基础示例 ```html ``` ::: -::: snippet `span`设置行占位 +## 表单校验 + +配置下的`props`对应`z-form`的参数,可以在此统一配置`rules`;配置下的`items`的每一项都对应`z-form-item`,也可以直接配置`rules`设置该项的校验规则。 + +
+ +::: snippet 设置**props**下的校验规则示例 ```html ``` ::: -::: snippet `label-width`设置标题宽度 +::: snippet 设置**items**下的校验规则示例 ```html ``` @@ -85,196 +118,378 @@ export default {
-## 表单校验 - -配置`list`的配置项中的`rules` +## 表单提交 -
+表单会默认提供一个`footer插槽`,并提供表单的提交、取消、重置等方法,且相关方法都有对应的事件监听。也可以不使用插槽提供的方法直接自定义。 -::: snippet `v-model`值动态改变,支持初始化 +::: snippet 配置`footer`插槽提供触发方法的示例 ```html +``` + +::: + +::: snippet 自定义提交的示例 + +```html + + + ``` ::: -
+## 配置复用 -## 表单分组 +因为与`z-form`、`z-form-item`用法相同,所以除了可以用作表单以外,也可用作详情展示,同时因为本身是schema配置项,所以可以做到表单和详情**配置复用**。 -将表单内容进行分组显示 - -::: snippet 表单配置项的`group`值设置分组 +::: snippet 配置复用示例 ```html ``` ::: -## 自定义渲染 +## 自定义插槽 -对于一些特殊渲染逻辑的表单项,可以进行自定义渲染 +在某些特殊情况下,表单项可能是当前页面的临时组件,或者项目并没有全局引入组件,亦或者需要一些特殊的函数去处理,此时可以使用自定义插槽替换默认配置项。插槽默认提供了`value`和`onInput`用于维护当前值。 -
- -::: snippet 通过`render`方法渲染 +::: snippet schema配置中items配置项的`is`设置为`slot`,即可在组件下通过插槽的方式替换配置项。默认支持`具名插槽`、`label`插槽、`error`插槽,与`el-form-item`的插槽类似。 ```html ``` ::: -::: snippet 通过`slot`插槽渲染 +## 配置子节点 + +使用表单时,除了可能会出现单组件子节点以外,可能出现带有子节点的子组件。schema也支持对子节点进行配置。 + +::: snippet schema配置中items配置项的`children`可以配置子节点,格式同``组件。 ```html ``` ::: -
+## 复杂表单 + +一般情况下,复杂表单建议使用`z-form`、`z-form-item`等组件构建视图,`不建议`使用schema的方式配置。但是利用schema配置项的一些特性,也可以做到部分复杂表单使用schema配置完成。 + +::: snippet 包含了**插槽**、**子节点**、**自定义子节点**的复杂示例 + +```html + + + +``` -## API - -## Attribute 属性 - -参数|说明|类型|可选值|默认值 --|-|-|-|- -value | 值 | Object | - | - -list | JSON Schema配置项列表 | Array | - | [] -formClass | 表单class | String | - | - -titleClass | 标题class | String | - | - -contentClass | 内容class | String | - | - -itemClass | 表单项class | String | - | - -groupClass | 表单分组class | String | - | - -labelWidth | 表单项标题宽度 | String | - | - -labelPosition | 表单项标题位置 | String | - | top -size | 大小 | String | - | small -span | 占位 | Number | - | 24 - -## Events 事件 - -事件名称|说明|回调参数 --|-|- -input | 表单值变化 | 表单model -validate | 校验表单 | 是否通过,表单model \ No newline at end of file +::: \ No newline at end of file diff --git a/examples/views/docs/develop/schema/introduce.md b/examples/views/docs/develop/schema/introduce.md new file mode 100644 index 0000000..52849bb --- /dev/null +++ b/examples/views/docs/develop/schema/introduce.md @@ -0,0 +1,260 @@ +# 介绍 + +方案开发是一种使用类`JSON Schema`格式的预置数据,快速生成一个业务逻辑视图,并且能够被引用及复用。 + +## 使用场景 + +① 复杂后台管理项目中,某些相同的功能可能会多次出现在不同的使用场景中,并且**同时**具有**相似性**和**差异性**,而**组件化**不能更方便的解决类似的场景。 + +② 逻辑并不复杂,但是表单项非常多,需要反复编写大量**重复**的**布局代码**,导致**代码量大**,业务逻辑代码**维护不便**的场景。 + +③ 不同功能页面下,使用了相同的表单或表格等相同的功能模块,遇到**改动**时,需要重新在多个页面里多次**重复修改**代码的场景。 + +## 示例 + +某页面的详情功能,常规情形下,会出现大量重复的布局组件`el-row`、`el-col`及表单组件`el-form-item`等,进行取值展示时,也需要多次书写`form.xxx`。本是一个没有业务逻辑的展示型页面,但大量书写的重复的代码,导致行数过多,且如遇到增删某个展示项时,还需要重新调整布局代码。总体上来说,代码可读性低,可维护性差。 + +代码: + +```html + + + +``` + +仅视图层就有53行代码,改用Schema开发后可将视图层代码极致精简,可以使后端开发员修改前端代码时不需要关心界面布局及样式,只关心业务逻辑。 + +使用Schema开发后的代码,视图层1行,而配置项也仅需13行代码,并且无需关心布局代码和多层级数据取值容错: + +```html + + + +``` + +也可以将Schema配置项单独保存在js文件中,需要的时候引入使用即可: + +```js +// xxx.schema.js +export default { + props: { size: 'small', 'label-width': '100px', span: 12 }, + items: [ + { prop: 'dispatchLine.lineName', label: '线路名称' }, + { prop: 'dispatchLine.startStation.name', label: '出发站点' }, + { prop: 'dispatchLine.endStation.name', label: '目的站点' }, + { prop: 'customer.name', label: '客户名称' }, + { is: 'dictionary-select-name', props: { 'option-name': 'LINE_TYPE' }, prop: 'customer.name', label: '线路类型' }, + { prop: 'dispatchLine.startStation.city.name', label: '出发城市' }, + { prop: 'dispatchLine.stopOverCityName', label: '经停城市' }, + { prop: 'dispatchLine.endStation.city.name', label: '经停城市' }, + ] +} +``` + +这样可以将业务逻辑结构和视图抽离并可复用。 + +```html + + + +``` + +也可对原始配置项进行一个差异化的处理,比如配置项相同的情况下改变schema已配置的属性: + +```html + + + +``` + +或者在配置项的基础上再追加几个配置项: + +```html + + + +``` + +## 更多 + +更多具体示例,请查看`schema-form`、`schema-table`、`schema-page`文档说明。 \ No newline at end of file diff --git a/packages/schema-form/index.vue b/packages/schema-form/index.vue index 3e06e2e..b9f2fc2 100644 --- a/packages/schema-form/index.vue +++ b/packages/schema-form/index.vue @@ -5,47 +5,33 @@ - - - - - - + + + - - - 确定 - 取消 - - + @@ -55,28 +41,33 @@ import { cloneDeep, get, set } from '../utils'; export default { name: 'SchemaForm', components: { - DynamicRender: { - functional: true, - render(h, context) { - return context.props.render; - }, - }, - StaticRender: { - functional: true, - render(h, context) { - return h('span', [context.props.render]); - }, - }, - ChildrensRender: { + ItemRender: { functional: true, render(h, context) { - return context.props.value.map(item => { - if (Array.isArray(item.children) && item.children.length > 0) { - return h('childrens-render', { props: { value: item.children } }); + const props = context.props; + const item = props.item || {}; + let content = []; + if (item.render && typeof item.render === 'function') { + content = context.props.render; + } + if (item.children) { + if (Array.isArray(item.children)) { + if (item.children.length > 0) { + content = item.children.map(i => h('item-render', { props: { item: i } })); + } } else { - return h(item.is, { ...item }); + content = [item.children]; } - }); + } + let _props = item.props || {}; + if (props.value) { + _props = { ..._props, value: props.value }; + } + let _on = item.on || {}; + if (props.onInput) { + _on = { ..._on, input: props.onInput }; + } + return h(item.is, { attrs: item.attrs, props: _props, on: _on }, content); }, }, }, @@ -102,6 +93,13 @@ export default { schemaProps() { return this.schema.props; }, + slotProps() { + return { + submit: this.onSubmit, + cancel: this.onCancel, + reset: this.onReset, + }; + }, }, created() { const { originData, ...other } = this._data; @@ -120,6 +118,18 @@ export default { }, methods: { get, + validate(callback) { + return this.$refs.form.validate(callback); + }, + validateField(props, callback) { + return this.$refs.form.validateField(props, callback); + }, + resetFields() { + this.$refs.form.resetFields(); + }, + clearValidate(props) { + return this.$refs.form.clearValidate(props); + }, keywordFilter(val = {}) { const { children, is, ...other } = val; return other; @@ -135,9 +145,13 @@ export default { }); }, onCancel() { - this.model = cloneDeep(this.originData).model; this.$emit('cancel'); }, + onReset() { + this.model = cloneDeep(this.originData).model; + this.$refs.form.resetFields(); + this.$emit('reset'); + }, }, }; -- libgit2 0.21.0