这个 table 中,主题模板有很多状态,比如:草稿 状态、已发布 状态、待审核 状态等等;点击这些状态又进入到不同的操作页中,比如:草稿对应 新建 操作页,已发布对应 修改 操作页,待审核对应 审核 操作页等等。在不同的操作页中意味着要请求不同的 接口、不同的接口意味着有不同的请求 参数。你会惊讶的发现 新建页、修改页、审核页 其实都长得差不多! 大概像下图这样色的(因为它们都会列出 table 的大部分字段,不同的字段存在不同的展现,有些只读、有些可写、有些存在关联项等等):
实际项目中的 form 会比上述截图所示复杂得多。比如本瓜所在项目中,这样的操作页,有几十个字段,包括查看、编辑、状态关联等。此处仅做抽象示意处理。基于上面的背景,我们可以想象:如果每个操作页面都是独立的,新建页有几十个表格字段、编辑页有几十个表格字段、审核页有几十个表格字段……而这些字段大部分类似,只是在部分字段上有区别或定制化的写法,那肯定不至于:有几个操作页,就复制几个页面吧?!这样没有任何复用思维,每当需要增删改字段的时候,都要在多个页面中进行操作,这是“大聪明”做法。
于是乎,我们需要复用!!(复用!又是复用!写业务代码最牛b的地方就是复用。高耦合、低内聚就是说如何复用。设计模式也是为了合理复用;就连写算法的时候,复用也是最牛b的,如何复用题干条件、或者复用空间来换取时间等等)手段、方法、途径有很多,这里拎出来单讲的一点复用是:对请求参数的封装复用。// 设一个页面的全局表格对象
const ruleForm = {
type:"fe",
time:"20200721",
title:"day day up",
status:"draft",
weight:999,
comment:"great",
balabala:"我是冗余参数1",
bilibilib:"我是冗余参数2"
}const {type,time,.title,status.weight,comment} = ruleForm // 解构得值
const getCreateParam = function(){
// ...省略一系列操作
return {only: "create"}
}
const createParam = getCreateParam() // 得到特殊传参
const param = {
// 公共传参
type,
time,
title,
status,
weight,
comment,
// 特殊传参
createParam
}
createRequest(param).then(res=> ... )const {type,time,.title,status.weight,comment} = ruleForm
const getEditParam1= function(){
// ...
return {only1: "edit1"}
}
const editParam1 = getEditParam1()
const getEditParam2= function(){
// ...
return {only2: "edit2"}
}
const editParam2 = getEditParam2()
const param = {
// 公共传参
type,
time,
title,
status,
weight,
comment,
// 特殊传参
editParam1,
editParam2
}
editRequest(param).then(res=> ... )const {type,time,.title,status.weight,comment} = ruleForm
const getReviewParam1= function(){
// ...
return {only1: "review1"}
}
const reviewParam1= getReviewParam1()
const getReviewParam2= function(){
// ...
return {only2: "review2"}
}
const reviewParam2= getReviewParam2()
const getReviewParam3= function(){
// ...
return {only3: "review3"}
}
const reviewParam3= getReviewParam3()
const param = {
// 公共传参
type,
time,
title,
status,
weight,
comment,
// 特殊传参
reviewParam1,
reviewParam2,
reviewParam3
}
reviewRequest(param).then(res => ...)class CommonParam {
constructor(){
this.ruleForm = ruleForm
}
get(){
const {type,time,title,status,weight,comment} = this.ruleForm
return{type,time,title,status,weight,comment}
}
}class CreateParam extends CommonParam {
getCreateParam(){
// ...省略一系列操作
return {only: "create"}
}
get(){
const para = super.get()
return {...para,...this.getCreateParam()}
}
}
let creatParam = new CreateParam().get()
createRequest(creatParam).then(res=> ... )class EditParam extends CommonParam {
getEditParam1(){
return {only1: "edit1"}
}
getEditParam2(){
return {only2: "edit2"}
}
get(){
const para = super.get()
return {...para,...this.getEditParam1(),...this.getEditParam2()}
}
}
let editParam = new EditParam().get()
editRequest(editParam).then(res=> ... )class ReviewParam extends CommonParam {
getReviewParam1(){
return {only1: "review1"}
}
getReviewParam2(){
return {only2: "review2"}
}
getReviewParam3(){
return {only3: "review3"}
}
get(){
const para = super.get()
return {...para,...this.getReviewParam1(),...this.getReviewParam2(),...this.getReviewParam3()}
}
}
let reviewParam = new ReviewParam().get()
reviewRequest(reviewParam).then(res=> ... )export const compose = function(...fns) {
return function composed(result) {
// 拷贝一份保存函数的数组
var list = fns.slice()
while (list.length > 0) {
// 将最后一个函数从列表尾部拿出并执行它
result = list.pop()(result)
if (result === 'breakCompose') { // * 任一步骤 renturn "breakCompose" 可以提前结束流程;
break
}
}
return result
}
}/******函数声明部分******/
/*
* 公共参数
*/
const step_getCommonParam = function(ruleForm){
const {type,time,title,status,weight,comment} = ruleForm
return{type,time,title,status,weight,comment}
}
/*
* 创建步骤函数
*/
const step_getCreateParam= function(args){
// ...省略一系列操作
return {...args,only: "create"}
}
const step_createRequest = function(creatParam){
return createRequest(creatParam).then(res=> ... )
}
/*
* 编辑步骤函数
*/
const getEditParam1= function(args){
// ...
return {...args,only: "edit1"}
}
const getEditParam2= function(args){
// ...
return {...args,only: "edit2"}
}
const step_editRequest = function(editParam){
return editRequest(editParam).then(res=> ... )
}
/*
* 审核步骤函数
*/
const getReviewParam1= function(args){
return {...args,only1: "review1"}
}
const getReviewParam2= function(args){
return {...args,only1: "review2"}
}
const getReviewParam3= function(args){
return {...args,only1: "review3"}
}
const step_reviewRequest = function(reviewParam){
return reviewRequest(reviewParam).then(res=> ... )
}
/******函数调用部分******/
const handleCreate = (...args) => {// 创建操作
const steps = [step_createRequest, step_getCreateParam, step_getCommonParam] // 步骤从右自左读
compose(...steps)(...args)
}
handleCreate(ruleForm)
const handleEdit = (...args) => {// 编辑操作
const steps = [step_editRequest, step_getEditParam2,step_getEditParam1, step_getCommonParam]
compose(...steps)(...args)
}
handleEdit(ruleForm)
const handleReview = (...args) => {// 审核操作
const steps = [step_reviewRequest,step_getReviewParam3,step_getReviewParam2,step_getReviewParam1,step_getCommonParam]
compose(...steps)(...args)
}
handleReview(ruleForm)
OK,以上便是本篇分享。点赞关注评论,为好文助力?我是掘金安东尼 ? 100 万人气前端技术博主 ? INFP 写作人格坚持 1000 日更文 ✍ 关注我,安东尼陪你一起度过漫长编程岁月 ?
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来
@作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors 1、什么是behaviors 2、behaviors的工作方式 3、创建behavior 4、导入并使用behavior 5、behavior中所有可用的节点 6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors 1、什么是behaviorsbehaviors是小程序中,用于实现
目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类
查看Ruby代码,它具有以下proc_arity:staticVALUEproc_arity(VALUEself){intarity=rb_proc_arity(self);returnINT2FIX(arity);}更多的是C编码风格问题,但为什么staticVALUE在单独的一行而不是像这样的:staticVALUEproc_arity(VALUEself) 最佳答案 它来自UNIX世界,因为它有助于轻松grep函数的定义:$grep-n'^proc_arity'*.c或使用vim:/^proc_arity
这是我发现自己偶尔想做的事情。假设我有一个参数列表。在Lisp中,我可以像这样`(imaginary-function,@args)为了调用将数组从一个元素转换为正确数量的参数的函数。Ruby中是否有类似的功能?或者我只是在这里使用了一个完全错误的成语? 最佳答案 是的!它被称为splat运算符。a=[1,44]p(*a) 关于Ruby:如何将数组拼接成Lisp风格的列表?,我们在StackOverflow上找到一个类似的问题: https://stackov
深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭9年前。Improvethisquestion首先,我想避免一场关于语言的口水战。可供选择的语言有Perl、Python和Ruby。我想提一下,我对所有这些都很满意,但问题是我不能只专注于一个。例如,如果我看到一个很棒的Perl模块,我必须尝试一下。如果我看到一个不错的Python应用程序,我必须知道它是如何制作的。如果我看到RubyDSL或一些Ruby巫术,我就会迷上Ruby一段时间。目前我是一名Java开发人员,但计划在不久的将来
我感到有点困惑——大约24小时以来,我一直在考虑在我的项目中使用哪种组播技术。基本上,我需要的是:创建组(通过一些后端进程)任意客户端广播消息(1:N,N:N)(可能)直接消息(1:1)(重要)使用我自己的后端(例如,通过某种HTTPAPI)对客户端进行身份验证/授权能够通过后端进程(或服务器插件)踢出特定的客户端这是我要的:Ruby或Haxe中的后端相关流程JS+Haxe(Flash9)中的前端—在浏览器中,因此理想情况下通过80/443进行通信,但不一定。因此,这项技术必须能够在HaxeforFlash中轻松访问,最好是Ruby。我一直在考虑:RabbitMQ(或OpenAMQ)、