华山论“单”

配置开发

号外号外!唯品会第一个前端开源项目来啦,就是它 - ncform

官方github:https://github.com/vipshop/ncform


好了,广告打好了,今天,我来给大家讲个故事,故事名叫华山论“单”。此处应该有掌声,好了,Let's go:


佩之和赋占各自修炼多年后,相约华山比试修炼成果

人物介绍:

佩之,擅长配置,拥有高超的将具象抽象成配置的能力;

赋占,手速飞快,毫秒级完成复制粘贴, 人称闪电手;

此次的比试主题,就是(长期占据后台管理系统的C位)表单的开发效率

第一回合,最基本的表单+验证

只见赋占摩拳擦掌,哨声一响,以飞快的速度在element-ui的官方文档和代码编辑器之间来回切换,复制粘贴控件的代码,哒哒哒哒哒~~~

<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
  <el-form-item label="活动名称" prop="name">
    <el-input v-model="ruleForm.name"></el-input>
  </el-form-item>
  <el-form-item label="活动区域" prop="region">
    <el-select v-model="ruleForm.region" placeholder="请选择活动区域">
      <el-option label="区域一" value="shanghai"></el-option>
      <el-option label="区域二" value="beijing"></el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="活动性质" prop="type">
    <el-checkbox-group v-model="ruleForm.type">
      <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
      <el-checkbox label="地推活动" name="type"></el-checkbox>
    </el-checkbox-group>
  </el-form-item>
  <el-form-item label="特殊资源" prop="resource">
    <el-radio-group v-model="ruleForm.resource">
      <el-radio label="线上品牌商赞助"></el-radio>
      <el-radio label="线下场地免费"></el-radio>
    </el-radio-group>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button>
  </el-form-item>
</el-form>

{
  data: {
    ruleForm: {
      name: '',
      region: '',
      type: [],
      resource: '',
    },
    rules: {
      name: [
        { required: true, message: '请输入活动名称', trigger: 'blur' },
        { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
      ],
      region: [
        { required: true, message: '请选择活动区域', trigger: 'change' }
      ],
      type: [
        { type: 'array', required: true, message: '请至少选择一个活动性质', trigger: 'change' }
      ],
      resource: [
        { required: true, message: '请选择活动资源', trigger: 'change' }
      ],
    }
  }
}

源码在此>>>

此时,旁边的佩之微微一笑,淡定的丢出了一份配置

{
  type: 'object',
  properties: {
    name: {
      type: 'string',
      ui: {
        label: '活动名称'
      },
      rules: {
        required: {
          value: true,
          errMsg: '请输入活动名称'
        },
        minLength: {
          value: 3,
          errMsg: '长度在 3 到 5 个字符'
        },
        maxLength: {
          value: 5,
          errMsg: '长度在 3 到 5 个字符'
        }
      }
    },
    region: {
      type: 'string',
      ui: {
        label: '活动区域',
        placeholder: '请选择活动区域',
        widget: 'select',
        widgetConfig: {
          enumSource: [
            {
              value: 'shanghai',
              label: '区域一'
            },
            {
              value: 'beijing',
              label: '区域二'
            }
          ]
        }
      },
      rules: {
        required: {
          value: true,
          errMsg: '请选择活动区域'
        }
      }
    },
    type: {
      type: 'array',
      ui: {
        label: '活动性质',
        widget: 'checkbox',
        widgetConfig: {
          enumSource: [
            {
              value: '美食/餐厅线上活动',
              label: '美食/餐厅线上活动'
            },
            {
              value: '地推活动',
              label: '地推活动'
            }
          ]
        }
      },
      rules: {
        required: {
          value: true,
          errMsg: '请至少选择一个活动性质'
        }
      }
    },
    resource: {
      type: 'string',
      ui: {
        label: '特殊资源',
        widget: 'radio',
        widgetConfig: {
          enumSource: [
            {
              value: '线上品牌商赞助',
              label: '线上品牌商赞助'
            },
            {
              value: '线下场地免费',
              label: '线下场地免费'
            }
          ]
        }
      },
      rules: {
        required: {
          value: true,
          errMsg: '请选择活动资源'
        }
      }
    }
  }
}

源码在此>>>

赋占瞄了一眼,什么鬼,居然就一份配置就搞定了。

“似曾相识啊,不过这局这么简单,接下来复杂的你肯定搞不定,我就在接下来的回合KO掉你”

第二回合,城市选择器

赋占暗自窃喜了一下,这种组件之间有数据依赖的,我看你怎么破,然后又开始飞快地敲起键盘

<el-form :model="form" label-width="100px" class="demo-form">
  <el-form-item label="省份" prop="province">
    <el-select v-model="form.province" @change="getCities" placeholder="请选择">
      <el-option v-for="item in provinceList" :key="item.id" :label="item.name" :value="item.id">
      </el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="城市" prop="city">
    <el-select v-model="form.city" placeholder="请选择">
      <el-option v-for="item in cityList" :key="item.id" :label="item.name" :value="item.id">
      </el-option>
    </el-select>
  </el-form-item>
</el-form>

{
  created() {
    this.getProvince();
  },
  data: {
    form: {
      province: '',
      city: '',
    },
    provinceList: [],
    cityList: []
  },
  methods: {
    getProvince() {
      axios.get('http://daniel.org/api/test/getProvinces').then(res => {
        this.provinceList = res.data;
      })
    },
    getCities() {
      this.form.city = '';
      axios.get('http://daniel.org/api/test/getCities', {
        params: {
          provinceId: this.form.province
        }
      }).then(res => {
        this.cityList = res.data;
      })
    },
  }
}

源码在引>>>

此时,佩之神情淡定,挥手又甩出了一份配置,一下子又搞定了

{
  "type": "object",
  "properties": {
    "province": {
      "type": "string",
      "ui": {
        "label": "省份",
        "widget": "select",
        "widgetConfig": {
          "itemLabelField": "name",
          "itemValueField": "id",
          "enumSourceRemote": {
            "remoteUrl": "http://daniel.org/api/test/getProvinces"
          }
        }
      }
    },
    "city": {
      "type": "string",
      "ui": {
        "label": "城市",
        "widget": "select",
        "widgetConfig": {
          "itemLabelField": "name",
          "itemValueField": "id",
          "enumSourceRemote": {
            "remoteUrl": "http://daniel.org/api/test/getCities"
            "otherParams": {
              "provinceId": "dx: {{$root.province}}"
            }
          }
        }
      }
    }
  }

源码在此>>>

赋占心里直郁闷:“我去,这都可以”

第三回合,日期比较+验证

赋占心想:“这个的难点在于操作开始日期的值,要触发结束日期的校验,有点隔空操作的意思,看你怎么配出来”,自个又开始了飞快的哒哒哒哒哒~~~

<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
  <el-form-item label="startTime" prop="startTime">
    <el-date-picker
      v-model="ruleForm.startTime"
      value-format="timestamp"
      type="date"
      placeholder="选择日期">
    </el-date-picker>
  </el-form-item>
  <el-form-item label="endTime" prop="endTime">
    <el-date-picker
      v-model="ruleForm.endTime"
      value-format="timestamp"
      type="date"
      placeholder="选择日期">
    </el-date-picker>
  </el-form-item>
</el-form>

{
  data() {
    let validateStartTime = (rule, value, callback) => {
      if (value === '') {
        if (this.ruleForm.endTime) this.$refs.ruleForm.validateField('endTime');
        callback();
      } else {
        if (this.ruleForm.endTime && this.ruleForm.endTime < value) {
          callback(new Error('开始日期必须小于结束日期!'));
        } else {
          if (this.ruleForm.endTime) this.$refs.ruleForm.validateField('endTime');
        }
      }
    };
    let validateEndTime = (rule, value, callback) => {
      if (value === '') {
        if (this.ruleForm.startTime) this.$refs.ruleForm.validateField('startTime');
        callback();
      } else {
        if (this.ruleForm.startTime && this.ruleForm.startTime > value) {
          callback(new Error('结束日期必须大于结束日期!'));
        } else {
          if (this.ruleForm.startTime) this.$refs.ruleForm.validateField('startTime');
        }
      }
    };
    return {
      ruleForm: {
        startTime: 0,
        endTime: 0
      },
      rules: {
        startTime: [
          { validator: validateStartTime, trigger: 'change' }
        ],
        endTime: [
          { validator: validateEndTime, trigger: 'change' }
        ]
      }
    }
  }
}

源码在此>>>

佩之微微皱了眉头,思考了一下,手一挥,又一份配置飞了出来

{
  "type": "object",
  "properties": {
    "startTime": {
      "type": "string",
      "ui": {
        "widget": "date-picker"
      },
      "rules": {
        "customRule": [
          {
            "script": "dx: !{{$root.endTime}} || {{$root.endTime}} >= {{$root.startTime}}",
            "errMsg": "开始日期必须小于等于结束日期",
            "linkItems": [
              {
                "fieldPath": "endTime",
                "customRuleIdx": 0
              }
            ]
          }
        ]
      }
    },
    "endTime": {
      "type": "string",
      "ui": {
        "widget": "date-picker"
      },
      "rules": {
        "customRule": [
          {
            "script": "dx: !{{$root.startTime}} || {{$root.endTime}} >= {{$root.startTime}}",
            "errMsg": "结束日期必须大于等于开始日期",
            "linkItems": [
              {
                "fieldPath": "startTime",
                "customRuleIdx": 0
              }
            ]
          }
        ]
      }
    }
  }
}

源码在此>>>

赋占终于沉不住气了,“我去,你这个是什么东西啊,啥都可以配配配”

佩之悠然地挥动着手上的扇子:“这就是表单开发利器-ncform”


【广告时间】

ncform,一种令人愉悦的表单开发方式,仅需配置即可生成表单UI及其交互行为。

用了它,更规范;用了它,更稳定; 用了它,更高效;用了它,更幸福;

而传统手工开发的表单,千人千种写法,可谓百家争鸣,而维护者痛苦不堪啊!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,042评论 25 707
  • 引言 这卷书信是特别有意味的,因为这是保罗最后的一封信,是他在罗马最后一次坐监时写的,那时他晓得自己离世已为期不远...
    biddon阅读 1,694评论 0 0
  • 清晨,窗外微雨,窗外的雨声一扫心中的喧嚣情绪,雨滴拍打在窗玻璃上,犹如婴儿的手指在敲打,又如少女的吻,清纯而...
    谢茹妤阅读 261评论 0 4
  • 前一段时间我看到这个流传的图片,意思是多么可爱的小朋友,你看到他明亮的眼睛么?我一开始以为是瞎子,遭受过暗黑的过去...
    五彩冰峰阅读 409评论 3 0
  • 最难的是坚持 是坚持会让你心安 还是会让你不沮丧 多想去改变 可当你觉得你已经迈入正轨的时候 转头才发现你却摆脱不...
    成小南阅读 134评论 0 0