文章目录
- 1. approval介绍
- 1.1 功能应用
- 1.2 项目地址
- 2. jsxPreview.vue应用
- 2.1 页面结构
- 2.2 表单解析
- 3. 功能拓展
- 3.1 数据回显
- 3.2 拓展样式
- 3.3必填字段完成后执行某方法
1. approval介绍
1.1 功能应用
approvalFlwo是一款关于工作流应用的开源免费项目,用户可以通过网页在线拖拽各个组件(输入框、选择框、布局容器、滑块20中常见的组件),自己布局、设计一个表单的样式,并配套着有相应的组件解析及 数据回显解析规则。
对比钉钉请假流程,请假需要的一个基本条件:
1、请假理由
2、向谁请假(审批人)
3、让谁看到(抄送人)
4、如果请假一天之内,审批人必须是xxx;请假一周,审批人必须是xxx
作者说明的功能简介:
1.表单配置(form-generator)
拖拽表单,生成布局页面
配置拖拽组件属性,定制组件形态
生成JSON数据并生成预览页面
2.流程节点配置(仿钉钉界面)
创建审批流程(发起人,审批人,条件节点,抄送人)
配置节点详细数据,包括条件节点表达式及期望值等
配置节点对表单得权限(目前并未在预览页面中做控制)
必填节点校验
2. jsxPreview.vue应用
2.1 页面结构
jsxPreview的作用为:表单样式的回显,及数据回显的解析(案例上没有使用,但是我们可以去拓展这个功能,作者提供了表单填写完毕之后json数据的生成及解析),主要的功能拓展都是基于本页面来现实的。
<script>
const xxx = {
....
};
function xxx() {
....
};
export default {
....
}
</script>
<style>
....
</style>
可以发现这个单页中没有用到<template></template>
,全部是根据var confGlobal = this.$route.params.formData || mockData.formData
获取到json数据后,通过解析动态生成的。
问题一: 如何在export default
外层function中调用methods里的方法?
可以把方法定义在window中以供全局使用
mounted() {
window.initialProcess = this.initialProcess;
},
2.2 表单解析
const layouts = {
colFormItem: function(){},
rowFormItem: function(){}
}
layouts定义了colFormItem、rowFormItem两种不同属性的表单解析方式。
查找怎么使用的?
{ Array.isArray(conf.children) && conf.children.map((el) => layouts[el.layout](el, h, ctx)) }
//--------------------------------------------------
return layouts[c.layout](c, h, this, initData);
根据json数据中定义的不同字段代入layouts从而执行colFormItem/rowFormItem的方法。
3. 功能拓展
3.1 数据回显
分析可得到layouts是解析json数据然后渲染到页面上的。
buildData(ctx, conf.defaultValue, conf.vModel);
//conf.defaultValue,数据中默认的值
//conf.vModel 同v-model,绑定的值
即可以判断是否存在要回显的数据,如果存在的话,就用要被回显的数据。不存在的话,就默认不是数据回显
if (defData) {
!_isMounted && buildData(ctx, defData, conf.vModel);
} else {
!_isMounted && buildData(ctx, conf.defaultValue, conf.vModel);
}
在调用layouts的时候,把回显的数据穿过来即可
3.2 拓展样式
render(h){}
作为一个中心整合的存在,它return出来html代码
return <div class='preview-container only-read' style={'width:' + this.containerWidth + '%;'}>
<el-row class='details-from-date'
gutter={this.confGlobal.gutter}
style='padding: 2rem 2rem 0;'
>
{this.buildForm(h)}
</el-row>
<div class='width-slider' style='display:none;'>
<el-slider vModel={this.containerWidth} min={100} max={100}></el-slider>
</div>
{this.buildDrawer(h)}
}
同样可以在这儿定义相应的html,使页面渲染出来
3.3必填字段完成后执行某方法
layouts中定义着form数据变化的检查功能,
<render
formData={ctx[ctx.confGlobal.formModel]}
conf={conf}
value={ctx[ctx.confGlobal.formModel][conf.vModel]}
ref={conf.rowType === 'table' ? conf.vModel : undefined}
onInput={handleInput}
/>
handleInput
就是表单触发的方法
可以查看render.js中
function vModel ( self, dataObject, value ) {
// dataObject.props.value = value
dataObject.on.input = val => {
self.$emit( 'input', val )
}
// 因为有些组件的v-model绑定的事件是change 所以这里也得监听
dataObject.on.change = val => {
self.$emit( 'input', val )
}
}
每次输入或者改变都会触发一次,比如当在输入框中输入一串值得时候
每次输入的值改变 | 触发得到的值 |
1 | 1 |
12 | 12 |
123 | 123 |
12 | 12 |
失去焦点 | 失去焦点 |
– | 12 |
这儿的思路是:判断最后一次和上一次的值是否相同,如有更好的思路也欢迎留言
// 全局定义两个变量
var aa = [];
var num = 0;
const layouts = {
...
colFormItem: function(){
const handleInput = val => {
if (num === 0) {
aa[num] = val;
num = 1;
} else {
aa[num] = val;
num = 0;
}
// console.log(aa);
if (val !== undefined && aa[0] === aa[1] && conf.required) {
window.initialProcess();
}
}
}
...
}