Gitee千Star优质项目解析: ng-form-element低开引擎解析
好家伙,
在写项目的时候,我发现自己的平台的组件写的实在是太难看了,于是想去gitee上偷点东西,于是我们本期的受害者出现了
gitee项目地址
https://gitee.com/jjxliu306/ng-form-elementplus-sample.git
组件库以及引擎完全开源,非常牛逼的项目,非常牛逼的作者
项目名:ng-form-element

整体的布局,组件样式,编辑器模板,组件拖动时的过渡动画,都写的非常漂亮,(比我写的好看多了)
于是我决定,扒一下他的内裤,学习(抄袭)一下
0.项目解析
官方文档:NG-FORM

于是我们快速定位到引擎部分

1.开始分析
我们知道,低开的引擎做的事无非是
把数据
变成视图
我们先来找数据
数据部分
//packages/index.vue
data() {
return {
selectItem: {},
arrow: false,
i18nkey: getUUID(),
formTemplate: this.template || {
list: [
],
config: {
labelPosition: 'left',
labelWidth: 100,
size: 'mini',
outputHidden: true, // 是否输出隐藏字段的值 默认打开,所有字段都输出
hideRequiredMark: false,
syncLabelRequired: false,
labelSuffix: '' , // 标签后缀
customStyle: ''
}
},
}
},
props: {
template: {
type: Object,
default: () => {
return {
list: [],
config: {
labelPosition: 'top',
labelWidth: 80,
size: 'mini',
outputHidden: true, // 是否输出隐藏字段的值 默认打开,所有字段都输出
hideRequiredMark: false,
syncLabelRequired: false,
labelSuffix: '' , // 标签后缀
customStyle: ''
}
}
}
},
然后来找视图部分
//packages/index.vue <ContainerPanel
:formTemplate="formTemplate"
@handleSelectItem="handleSelectItem"
:selectItem="selectItem"
:arrow="arrow"
>
</ContainerPanel> import ContainerPanel from './panel-container/index.vue'
:formTemplate:传模板数据的@handleSelectItem:这是一个事件处理器,当组件内的handleSelectItem方法被触发时,会执行传入的回调函数。handleSelectItem是组件内部定义的事件处理函数名。:selectItem:这是绑定的数据属性,用于传递一个"被选中的数据":arrow:暂时没看出来干嘛的
//packages/panel-container/index.vue
<el-form
:label-width="formTemplate.config.labelWidth + 'px'"
class="ng-form"
:label-position="formTemplate.config.labelPosition"
:hide-required-asterisk="formTemplate.config.hideRequiredMark"
:label-suffix="formTemplate.config.labelSuffix"
ref="form"
:style="formTemplate.config.customStyle"
:size="formTemplate.config.size"
>
<el-row :gutter="20" class="row">
<draggable
tag="div"
class="draggable-box"
v-bind="{
group: 'form-draggable',
ghostClass: 'moving',
animation: 180,
handle: '.drag-move'
}"
:force-fallback="true"
v-model="formTemplate.list"
@add="dragEnd($event, formTemplate.list)"
>
<transition-group tag="div" name="list" class="items-main">
<Node
:class="{'drag-move' : record.drag_ == undefined || record.drag_ }"
v-for="record in formTemplate.list"
:key="record.key"
:record="record"
:isDrag="true"
:config="formTemplate.config"
:selectItem="selectItem"
@handleSelectItem="handleSelectItem"
@handleCopy="handleCopy(record)"
@handleDetele="handleDetele(record)"
> </Node>
</transition-group>
</draggable> </el-row>
</el-form>
<transition-group>是 Vue.js 的内置过渡组件,用于给列表添加过渡效果。- el-form的作用我们后面说
//packages/form-design/items/index.vue
<template>
<ItemNode
v-if="isLayout"
:record="record"
:disabled="disabled"
:preview="preview"
:isDragPanel="isDragPanel"
:prop-prepend="propPrepend"
:selectItem="selectItem"
:style="{'display': recordVisible ? '' : 'none'}"
:models="models"
@handleSelectItem="handleSelectItem"
>
<!-- 递归传递插槽!!! -->
<template v-for="slot in Object.keys($slots)" :slot="slot">
<slot :name="slot" :record="record"/>
</template>
</ItemNode>
<el-form-item
v-else
:label="label"
:style="{'display': recordVisible ? '' : 'none'}"
:rules="recordRules"
:prop="recordProps"
:key="record.key"
:required="recordRequired"
:id="record.model"
:name="record.model"
:label-width="labelWidth"
>
<ItemNode
:record="record"
:disabled="disabled"
:preview="preview"
:isDragPanel="isDragPanel"
:selectItem="selectItem"
:prop-prepend="propPrepend"
:models="models"
@handleSelectItem="handleSelectItem"
>
<!-- 递归传递插槽!!! -->
<template v-for="slot in Object.keys($slots)" :slot="slot">
<slot :name="slot" :record="record"/>
</template>
</ItemNode>
</el-form-item>
</template> import ItemNode from './node.vue'
1.v-if="isLayout":是否为预览模式
//packages/form-design/items/node.vue <template> <component
:record="record"
:style="{
margin: record.margin && record.margin.length > 0 ? record.margin.join('px ') + 'px' : '0px',
borderRadius: (record.itemBorderRadius ? record.itemBorderRadius : 0) + 'px',
backgroundColor: record.backgroundColor ? record.backgroundColor : '', }"
:disabled="disabled"
:preview="preview"
:isDragPanel="isDragPanel"
:selectItem="selectItem"
:prop-prepend="propPrepend"
:models.sync="models"
@handleSelectItem="handleSelectItem"
@handleFocus="handleFocus"
@handleBlur="handleBlur"
:is="customComponent">
<!-- 递归传递插槽!!! -->
<template v-for="slot in Object.keys($slots)" :slot="slot">
<slot :name="slot" :record="record"/>
</template>
</component>
</template>
ok终于到了最后一层
最终的关键就是这么行代码
:is="customComponent":动态绑定组件名称,根据customComponent的值来渲染不同的组件。
customComponent() {
// 判断是否自定义组件
if(this.customComponents && this.customComponents.length > 0) {
const cs = this.customComponents.filter(t=> t.type == this.record.type)
if(cs && cs.length > 0) {
return cs[0].component
}
}
const selectItemType = this.record.type
// 将数组映射成json
if(this.items && this.items.length > 0) {
for(let i = 0 ; i < this.items.length ; i++) {
const itemList = this.items[i]
if(itemList.list && itemList.list.length > 0) {
const fs = itemList.list.filter(t=>t.type == selectItemType)
if(fs && fs.length > 0) {
return fs[0].component
}
}
}
}
return null
},
2.数据格式
在这个项目上随便做的一个表格并导出数据

{
"list": [
{
"type": "input",
"options": {
"defaultValue": "",
"type": "text",
"prepend": "",
"append": "",
"placeholder": "请输入",
"maxLength": 0,
"clearable": false,
"hidden": false,
"disabled": false
},
"label": "输入框",
"labelWidth": -1,
"width": "100%",
"span": 24,
"model": "input_17156872001522",
"key": "input_17156872001522",
"rules": [
{
"required": false,
"message": "必填项",
"trigger": [
"blur"
]
}
],
"dynamicLabel": false
},
{
"type": "radio",
"options": {
"defaultValue": "",
"placeholder": "请输入",
"dynamic": 0,
"options": [
{
"value": "1",
"label": "选项1"
},
{
"value": "2",
"label": "选项2"
}
],
"methodType": "get",
"dynamicPostData": "",
"remoteFunc": "",
"dataPath": "",
"remoteValue": "",
"remoteLabel": "",
"dictType": "",
"disableItemScript": "",
"hidden": false,
"disabled": false,
"linkage": false,
"linkData": []
},
"label": "单选框",
"labelWidth": -1,
"width": "100%",
"span": 24,
"model": "radio_17156872321432",
"key": "radio_17156872321432",
"rules": [
{
"required": false,
"message": "必填项",
"trigger": [
"blur"
]
}
],
"dynamicLabel": false
},
{
"type": "button",
"event_": false,
"listen_": false,
"options": {
"size": "mini",
"type": "primary",
"align": "left",
"control": "",
"eventName": "",
"script": "",
"plain": false,
"circle": false,
"round": false,
"disabled": false
},
"label": "按钮",
"labelWidth": 0,
"width": "100%",
"span": 24,
"model": "button_17156901763582",
"key": "button_17156901763582",
"dynamicLabel": false
},
{
"type": "rate",
"options": {
"max": 5,
"defaultValue": 0,
"allowHalf": false,
"hidden": false,
"disabled": false
},
"label": "评分",
"labelWidth": -1,
"width": "100%",
"span": 24,
"model": "rate_17156901773022",
"key": "rate_17156901773022",
"rules": [
{
"required": false,
"message": "必填项",
"trigger": [
"blur"
]
}
],
"dynamicLabel": false
}
],
"config": {
"labelPosition": "top",
"labelWidth": 80,
"size": "mini",
"outputHidden": true,
"hideRequiredMark": false,
"syncLabelRequired": false,
"labelSuffix": "",
"customStyle": ""
}
}
type:表示该组件的类型,该对象的类型为 "rate",用于评分。options:表示该组件的选项,包括:label:表示该组件的标签文本,值为 "评分"。labelWidth:表示该组件的标签宽度,值为 -1,表示使用系统默认值。width:表示该组件的宽度,值为 "100%"。span:表示该组件所占的栅格数,值为 24。model:表示该组件的 v-model 绑定值的变量名,值为 "rate\_17156901773022"。key:表示该组件的唯一标识,值为 "rate\_17156901773022"。rules:表示该组件的校验规则,包括:dynamicLabel:表示该组件的标签是否动态显示,值为 false。
3.总结
在翻了许许多多的低开项目后,发现,
巨大多数的低开项目要么引擎核心闭源,要么物料组件库闭源
而这个项目,所有的东西都开源了,真真正正的开源,真的牛bi
非常值得自学的一个低开项目
Gitee千Star优质项目解析: ng-form-element低开引擎解析的更多相关文章
- AngularJS进阶(三十九)基于项目实战解析ng启动加载过程
基于项目实战解析ng启动加载过程 前言 在AngularJS项目开发过程中,自己将遇到的问题进行了整理.回过头来总结一下angular的启动过程. 下面以实际项目为例进行简要讲解. 1.载入ng库 2 ...
- 保姆级教程,如何发现 GitHub 上的优质项目?
先看再点赞,给自己一点思考的时间,微信搜索[沉默王二]关注这个靠才华苟且的程序员.本文 GitHub github.com/itwanger 已收录,里面还有一线大厂整理的面试题,以及我的系列文章. ...
- 学习SpringBoot,整合全网各种优秀资源,SpringBoot基础,中间件,优质项目,博客资源等,仅供个人学习SpringBoot使用
学习SpringBoot,整合全网各种优秀资源,SpringBoot基础,中间件,优质项目,博客资源等,仅供个人学习SpringBoot使用 一.SpringBoot系列教程 二.SpringBoot ...
- 1K star+ 的项目是如何炼成的?
前言 首先标题党一下,其实这篇文章主要是记录我的第二个过 1K star 的项目 Java-Interview,顺便分享下其中的过程及经验. 需求选择 Java-Interview 之所以要做这个项目 ...
- mybatis源码-解析配置文件(二)之解析的流程
目录 1. 简介 2. 配置文件解析流程分析 2.1 调用 2.2 解析的目的 2.3 XML 解析流程 2.3.1 build(parser) 2.3.2 new XMLConfigBuilder( ...
- Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件
Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...
- Fixflow引擎解析(二)(模型) - BPMN2.0读写
Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...
- Fixflow引擎解析(一)(介绍) - Fixflow开源流程引擎介绍
Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...
- Android网络请求与数据解析,使用Gson和GsonFormat解析复杂Json数据
版权声明:未经博主允许不得转载 一:简介 [达叔有道]软件技术人员,时代作者,从 Android 到全栈之路,我相信你也可以!阅读他的文章,会上瘾!You and me, we are family ...
- spring mvc: 多解析器映射(资源绑定视图解析器 + 内部资源[普通模式/]视图解析器)
spring mvc: 多解析器映射(资源绑定视图解析器 + 内部资源[普通模式/]视图解析器) 资源绑定视图解析器 + 内部资源(普通模式)视图解析器 并存方式 内部资源视图解析器: http:// ...
随机推荐
- 【LGR-069】洛谷 2 月月赛 II & EE Round 2
目录 前言 洛谷 6101 [EER2]出言不逊 分析 代码 洛谷 6102 [EER2]谔运算 分析 代码 洛谷 6103 [EER2] 直接自然溢出啥事没有 分析 代码 洛谷 6105 [Ynoi ...
- 李东山:如何让 OpenHarmony 支持低功耗蓝牙芯片 GR551x
编者按:在 OpenHarmony 生态发展过程中,涌现了大批优秀的代码贡献者,本专题旨在表彰贡献.分享经验,文中内容来自嘉宾访谈,不代表 OpenHarmony 工作委员会观点. 李东山 深圳市汇顶 ...
- win7电脑IE浏览器开发人员工具中不能切换浏览器版本
win7电脑 IE浏览器 开发人员工具,不能切换IE版本 这个是IE浏览器的问题,需要安装个微软件东西就可以解决这个问题了.亲测有效 64位下载地址:https://wwi.lanzoui.com/i ...
- C++ 获取数组大小、多维数组操作详解
获取数组的大小 要获取数组的大小,可以使用 sizeof() 运算符: 示例 int myNumbers[5] = {10, 20, 30, 40, 50}; cout << sizeof ...
- 【Java面试指北】单例模式
单线程下的单例模式: public class Singleton { private static Singleton instance; private Singleton() {} public ...
- Excel 表间关联运算的示例
用 Excel 处理数据时,经常会涉及到多页 sheet 数据之间的关联运算需求,用 vlookup 可以完成部分简单关联,但较复杂的情况时仍然不太方便,常常需要多次操作才能完成.另外,当要做关联的文 ...
- mybatis generator生成mapper接口后的代理类,很方便使用。
1.spring 配置: <bean id="superMapperProxy" class="com.qws.v1.daoImpl.MapperProxy&quo ...
- web开发可不可以是这样的?
service不外乎就是数据校验,调用其它service,调用第三方api,读写数据库,既然这样,那我认为Service也可以做成可配置化的样子,配置项大致有 所需参数配置:参数列表,参数类型,参数长 ...
- warmup预热学习率
学习率是神经网络训练中最重要的超参数之一,针对学习率的优化方式很多,Warmup是其中的一种 (一).什么是Warmup?Warmup是在ResNet论文中提到的一种学习率预热的方法,它在训练开始的时 ...
- PolarDB B-tree 并发控制优化
简介: PolarDB 解决了 InnoDB 在 B-tree 并发控制上的限制,解决 index lock 竞争问题,并支持了 latch coupling. InnoDB 索引 InnoDB 引擎 ...