Giter Site home page Giter Site logo

ub-ria's Introduction

ub-ria

RIA base for union business

生成文档

npm i -g jsdoc
cd {ub-ria}
jsdoc -c doc/conf.json
open doc/api/index.html

ub-ria's People

Contributors

bobshen avatar curarchy avatar dddbear avatar exodia avatar huayu216312 avatar justineo avatar leeight avatar otakustay avatar srhb18 avatar strwind avatar yanghuabei avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ub-ria's Issues

控件校验min、max和pattern规则时,无法显示用户自定义的errorMessage

初步排查后确认问题出在extention/ui.js以下三个函数中的getErrorMessage.apply(this, arguments);前少了一个return

MaxRule.prototype.getErrorMessage = function (control) {
    if (control.get('maxErrorMessage')) {
        var getErrorMessage = Rule.prototype.getErrorMessage;
        getErrorMessage.apply(this, arguments);
    }
    var rangeErrorMessage = getRangeErrorMessage(control);
    if (rangeErrorMessage) {
        return rangeErrorMessage;
    }
    return Rule.prototype.getErrorMessage.apply(this, arguments);
};

MinRule.prototype.getErrorMessage = function (control) {
    if (control.get('maxErrorMessage')) {
        var getErrorMessage = Rule.prototype.getErrorMessage;
        getErrorMessage.apply(this, arguments);
    }
    var rangeErrorMessage = getRangeErrorMessage(control);
    if (rangeErrorMessage) {
        return rangeErrorMessage;
    }
    return Rule.prototype.getErrorMessage.apply(this, arguments);
};

PatternRule.prototype.getErrorMessage = function (control) {
    var pattern = control.get('pattern') + '';
    if (control.get('patternErrorMessage')
        || !NUMBER_REGEX.hasOwnProperty(pattern)
    ) {
        var getErrorMessage = Rule.prototype.getErrorMessage;
        getErrorMessage.apply(this, arguments);
    }
    var rangeErrorMessage = getRangeErrorMessage(control);
    if (rangeErrorMessage) {
        return rangeErrorMessage;
    }
    return Rule.prototype.getErrorMessage.apply(this, arguments);
};

[ViewModel]深层的对象、数组如何处理change

@Exodia

如题描述,如果一个属性是一个对象/数组,其中的一个属性/某一项变了,我们要怎么做:

  1. 把对象/数组变成ModelCollection,冒泡change等事件。这会导致直接对原对象/数组的变更无法产生效果,外部必须知道“该对象变成了一个Model”这一事实
  2. 无视,即没有change事件。这种策略鼓励使用“不可变值”,即不对一个对象/数组作修改,需要的时候生成新的对象/数组并直接set回去
  3. 设计一个类似$digest的东西,定期去抓变化。累……

我比较建议第2种方案,不可变值能带来其它的一些收益,如代码更易维护不用担心在未知的地方有所变化

添加ActionFactory组装Action

Action的组装从Action逻辑内部抽出来,在外部组装,有助于一个模块跨项目复用,因为可以方便地替换ModelView或其它部件

使用Model来进行检验

原来通过View进行检验,但无论View是否有做校验,Model都应该对自己接收的参数进行严格的检验

原来的顺序是submit -> fillEntity -> validateEntity -> save / update,现在可以改为submit -> save / update,而在save / update中调用validateEntity来确保saveupdate作为一个接口方法的完备性

这种情况下,View可以不进行检验,当saveupdate检验失败时,返回一个类似后端返回的检验错误信息的数据格式即可

关于独立模块的CSS隔离问题

@Exodia @DDDBear

原本CSS隔离的最简单方法就是利用系统自动为Action容器加上的class,默认的逻辑是这样的:

var categories = [];
var category = u.dasherize(this.getCategory());
var entityName = u.dasherize(this.getEntityName());

if (category) {
    categories.push(category + '-page');
}
if (entityName) {
    categories.push(entityName + '-page');
}
if (category && entityName) {
    categories.push(entityName + '-' + this.category + '-page');
}

return categories;

但是这样做的话,需要所有的Action重写getPageCategories方法,且无法用继承实现(各Action类的继承关系本来就不一致),因此这个的成本相当高,且基本断了项目有特殊需求换用Action并且不继承自模块提供的Action的场景

为此,我希望实现一个更透明的方法,大致如下:

  1. css/fooMain.less中添加一个变量,控制整个Scope

    @ssp-foo-container-class: ssp-foo-package;
  2. 所有的CSS在这个作用域下

    .@{ssp-foo-container-class} {
        .esui-label { color: red; }
    }
  3. 更新ub-ria,给Action增加一个package属性

  4. 修改getPageCategories,自动为容器生成{package}-package的class,如ssp-foo-package

  5. IoC管理package属性,可以有自动规则(同remoteModule

  6. 如果package属性有变化,在less中相应重写变量值

从业务上来说,package是“将一类业务模块打包”的概念,打包后的各页面有相同的class

是否合理?

迁移控件

需要控件如下:

  • Uploader
  • RichSelector系列
  • ToggleButton
  • TogglePanel
  • Chart系列

以上控件均需按基础库的**重新审视一下并重构

RequestStrategy

RequestManager里,有几个方法是用来处理请求的参数统一化的,比如URL的规则等

在不同系统里,这个规则可能是不同的,但RequestManager的子类实现中方法的主体是相同的,因此要把这个可变的点抽出来

因此添加一个RequestStrategy,把一系列formatXxx方法转到上面去,形成组合关系

TogglePanel 将 title 装入 Label中

现在的实现是独立的h3结构,导致了内部在 titleElement 上的处理比较杂乱,放入 label 中正好利用了 esui 自身的控件树实现进行元素定位

关于通用409与500响应格式

通用409的格式,可能难以应付所有的错误情况。有些错误与所传字段无关,纯粹因为该数据正审核中不能修改 或 用户无权限。

为此可能需要增强通用409格式
如:
{
fields:[ ................ ],
message: {string},
errorId: {number}
}

fields用来处理有关所传输字段相关的错误,外围的message和errorId用以处理与字段无关的错误信息。

我认为所有的表示错误的返回信息,包括500,结构都应该包含message和errorId,当然404除外啦。

BESC到UB-RIA的merge汇总

布局,样式

标题栏

header

导航展开收起开关

collapseicon

主页面容器

1. 列表

2  表单

带箭头的panel

arrowpanel

筛选器容器

filter

进度加载

loading

控件

Sidebar

叫做SideMenu更合适。垂直菜单栏。

sidenav

DropDown

功能与TogglePanel有所重合,不同只是DropDown增加了其它区域点击收起容器的事件。可以考虑扩展TogglePanel,增加配置开关。

dropdown

AbstractBoxGroup

选择框组,比BoxGroup支持的样式更灵活,支持通过skin定义了各种不同样式的选择展示。

skin-cloud

skin-cloud

skin-flat-radio

skin-flat-radio

skin-size

skin-size

skin-switch-button

skin-switch-button

UB-RIA需要新增控件

  1. ToggleSingleSelector

未完,待续。。。

Form支持复制功能

使用场景和功能规则描述:

点击复制进入复制页面,将被复制的内容填充至表单页面对应位置。

提交和验证规则与新建流程一致。

提取表单提交处理逻辑

相关pull request #97
表单提交后有两种结果需要处理,成功和失败:

  • 失败:提交失败的处理逻辑可以视为不变的,几乎没有被重写过
  • 成功:目前有以下几种处理方式
    • toast提醒
    • 跳转到中间页
    • 返回到前一页
    • 跳转到其他页面(业务类重写)

现在的ub-ria.FormAction提交成功的处理逻辑是:

  • notifySubmitSuccess:空函数
  • fire('entitysave')
  • fire('handlefinish')
  • back();

为了应对将来可能出现更多不同的提交成功后的处理逻辑,pr #97 对现有的handleSubmitResult的逻辑进行了修改,提取出两个submitHandlersubmitHandler.handle是真正的处理逻辑:

  • ToastSubmitHandler
    • template''
    • setTemplate(template): 设置toast模版
    • getToastMessage:获取toastMessage
    • showToastBaseView不在提供showToast方法
    • handle:显示toast
  • RedirectSubmitHandler
    • template:默认值'/${entityName}/list'
    • setTemplate():设置跳转url的模版
    • redirect():返回到前一页或指定url
    • getData:获取url模版的数据
    • handlefire('entitysave') > fire('handlefinish') > redirect

另外提供CompositeSubmitHandler,将多个handler组合起来

  • CompositeSubmitHandler
    • setChildHandlers(handlers)hanlders为数据
    • handle():调用childHandlerhandle

ub-ria.FormAction提供setSubmitHandlerhandleSubmitResult方法调用submitHandlerhandle方法。ub-ria.FormAction未设定任何handler,需使用者setSubmitHandler
业务层可以继承或定义新的hanlder,通过CompositeSubmitHandler组合使用。

错误返回机制

  1. 我们将一些错误以httpcode的方式返回,这个做法是否权威(不太清楚,只是提个问题)?
    如果定义的httpcode与web server默认返回的httpcode冲突,这就不太好了
  2. 业务上的错误以一个错误字段返回,这是否能和定义的httpcode的错误统一起来?无论任何错误,都返回错误代码和错误信息,这是不是更简单。

关于View层的校验

把校验移到Model后,理论上我们View层不需要这么多的检验逻辑,但是View上不进行校验的话,任何时候都可以成功提交,提交的过程会经过getEntity() -> fillEntity(),这2个方法是否能在View没有校验提交了不完整的表单时保持不出问题呢?

因此,到底在不在View上再加一个检验,需要讨论一下:

  1. View不检验,那么getEntity()fillEntity()需要重写实现时,要关注表单不完整的情况以避免出错
  2. View加上检验,那么getEntity()至少不需要关注表单不完整,但fillEntity()从设计的理念上来说,不应该知道View会检验,所以还是要加相关逻辑

前后端接口规范 获取用户登录状态 -- 是否增加用户基础信息

在用户在登录状态时( /users/current/status),是否获取用户的基础信息
为了安全,建议公开的信息越少越好,

现在想到的是
userName 用户名(非登录帐号)
newMessageCount 未读信息数

这在有些情况下用得着,
一般在用户登陆后右上角都会显示用户名及显示是否有未读信息。

前后端接口规范 分页列表

所传的参数中只有 page 没有 pageSize
有的系统每页显示多少条是用户可以实时选的,所以还是得有pageSize

在返回的数据中 有pageNo,与所传的参数page意义相同,却用不同的写法,建议统一

添加常用的模板块

可以把文本框等做成模板块来供使用,如:

<!--
    use: textbox(
        prefix = 'slot-form',
        id = 'name',
        title = '广告位名称',
        required = true
        maxLength = ${rule.maxLength},
        pattern = ${rule.charaterOnly}
    )
-->

进一步也可直接生成表单中的一行:

<!--
    use: textboxField(
        prefix = 'slot-form',
        id = 'name',
        title = '广告位名称',
        field = '名称',
        required = true
        maxLength = ${rule.maxLength},
        pattern = ${rule.charaterOnly}
    )
-->

要考虑的是类似这样的要抽出多少,现在管家中至少有:

  • listSearchBox(placeholder):列表的搜索框
  • batchButton(statusName, status, command):批量操作按钮

Toast移到ESUI

当前第一要务,让ub-ria能正确跑起来的基础,我会再去看下浩寅的实现,进行一些优化后更新esui版本

通过后端配置的通用Action

此功能的基本**是针对一些比较简单,但是多变的应用模块,可以采用由后端返回Action配置信息,前端通用的Action处理解析并提供相关的功能。

应用过程如下:

  1. 用户通过点击或输入,进入了#/module/action;
  2. Router无法在本地找到该Path所对应的Action文件,故将处理转向该通用Action(当前逻辑为转向404处理Action);
  3. 该通用Action拿到path后作为参数向后端发起请求该path的配置的请求;
  4. 如果后端返回了该path的请求,通用Action就按照该配置渲染前端tpl、view、model等各个模块,并最终达到可供用户正常使用的状态;
  5. 否则转到404处理Action;

基本流程如下:
action

后端返回配置的描述:

"path": "module/entity/page",
"type": "form",
"model": {
    "fieldName": "value",
    "fieldName2": 123,
    ......
},
"view": {
    "title": "模块描述",
    "fieldSections": [
        {
            "name": "basicInfo",
            "title": "基本信息",
            "toggleable": false,
            "fields": [
                {
                    "name": "filedName",
                    "desc": "字段描述",
                    "ctrl": "textbox",
                    "option": {
                        "defaultValue": "请输入内容"
                    },
                    "rule": {
                        "maxLength": 100,
                        "required": true,
                        "pattern": "@rule.xxx"
                    },
                    "condition": { "${abc}=='1' && ${def}!= 'left' || ${ghi}== 'normal'" }
                },
                ......
            ]
        },
        ......
    ]
}

需要讨论的问题是:
1、关于配置中信息的组织,尤其Model字段中的信息,是否用Field字段中的value来表示,还是独立放在Model中?

2、模板类型和控件的需要支持到什么程度?
初步希望的模板类型包括了常见的基类控件,Textbox、Textarea、RadioButton、Checkbox、Selector以及其扩展类型;中期会根据需求支持Uploader、ColorPicker、ToggleSelector等类型;

3、condition个字段的支持程度?
当前设计仅支持到== != && ||四种逻辑,不支持其它逻辑和括号

多层继承的datasource合并问题

当继承关系较深时,可能每个父类都会有自己的datasource配置,比如:

- SingleEntityModel - 根据id加载单个
    - DetailModel - 加载summary信息
        - XxxDetailModel - 加载一些查询域信息和权限

类似这处多级的datasource,都要在load的时候进行合并后一起加载,但合并并非简单的扩展,需要考虑到并行还是串行的问题,并不简单

需要仔细地设计这一块

[ViewModel]计算属性如何处理

@Exodia

有些属性是依赖其它一些属性计算的,典型的就是fullName = lastName + firstName这一场景,会有几种做法:

  1. 使用普通的属性,并通过change事件自行关注依赖的其它属性完成更新。这么做的好处是整个change事件非常统一
  2. 使用Computed Properties,即某个属性只是一个方法。这么做比较清晰,但在自理change事件的时候会存在一些问题,主要问题是当其依赖的属性更新时,这个属性的值会立即变化,此时的change事件无法得到oldValue

EmberJS是使用第2种方法的,WPF因为属性本身就有getter所以也相当于是第2种方法,都是丢失了oldValue的,Angular现在不明……

关于模板中控件的主元素类型

现在我们有不少选择:

  1. 使用常见元素,如<div>作主元素,简单粗暴,代价是小心看花眼
  2. 针对输入控件和<input />元素,这本意是为了让模板在无ESUI的时候也能用,一种奇怪的执着我也不知道为啥从 @errorrik 时代就传到我这了……
  3. 使用自定义元素,但有些元素有特殊作用,比如<label>,使用自定义元素的时候就会失效,毕竟我们没有registerElement这种API

大家讨论一下,怎么样的情况下用什么,有个最佳的实践和规范出来

CSS书写规范

图标

  1. 最小尺寸,边缘包裹。即,不要有多余的留白。
  2. 不要局部的雪碧图,即便是同一个控件图标的不同状态。
  3. 同一控件不同状态的图标大小要保持一致。
  4. 不要跨模块引用图标,即A模块和B模块之间的图标不可互用,如果有这种需求,图标应放于common下,并定义common下的css,供模块引用。
  5. 图标命名增加文件目录前缀,如common下的叫 common-xxx.png,ui下叫ui-xxx.png(此规范待考察,主要是避免命名冲突)。

CSS

  1. 书写时要注意复用性,不要不同模块出现同样样式但是不同class的定义。
  2. 对于模块内可能多处使用的css属性值,应使用变量统一配置。
  3. 使用伪元素给控件加图标。(这个的详细解决方案我稍后给出)

待补充。。。

Uploader增加可清除已上传记录的接口

现在控件中没有接口支持将已经上传的图片清除功能。
讨论一下这两个情景:

  1. 当图片上传控件作为表单可选字段时,支持可以将已经上传的图片清除
  2. 当一个表单有至少一个上传图片为必选,其他更多图片为可选的情况,对于图片清除之后的validity初始化操作

[ViewModel]关于ViewModel中数据的约束

@Exodia

由于新增了ViewModel这一概念,那么其中存放怎么样的数据我们应该有一个规范和约束,我大致觉得有几种可选:

  1. 不作限制,随场景自行设计
  2. 要求ViewModel的数据结构和视图一致,如果一个控件要一个对象,VM中对应的属性也是一个对象,数组也一样

另外还涉及一个问题,一些字符串的拼接,比如加个前缀之类的,应该在ViewModel还是View中处理,我更倾向于在ViewModel中处理以提高可测性

EntityDefine实体定义,用于Model校验和脚手架生成代码

以下是一个典型的用于Model做数据校验和脚手架生成相关代码时使用的对实体的定义格式,大家看一下,是否有补充的?
关于脚手架相关的内容可以参考:ecomfe/ub-ria-tool#6

    /**
     * <%-: project.alias %>
     * Copyright 2014 Baidu Inc. All rights reserved.
     *
     * @ignore
     * @file <%-: description %>实体定义模块
     * @author <%-: developer.name %>(<%- developer.email %>)
     */
    define(
        function (require) {
            /*
             * Entity对象用于描述这个模块的实体,主要包括:
             * 字段:{key}、字段类型:{type}、字段描述:{字段描述} 和 字段配置:{TypeOption}
             *
             * 一个典型的实体字段定义描述如下:
             * {key}: [{Type}<string>, {字段描述}<string>, {TypeOption}<object>]
             *
             * Type: 'string' | 'enum' | 'number' | 'bool' | 'array' | 'object' | 'reference' | 'reference-set'
             * 说明:字符串   | 枚举   | 数字     | 布尔值 | 数组    | 对象     | 外键        | 外键集
             *
             * 当Type为'string'时,TypeOption属性有:
             * 字  段  required | maxLength | pattern
             * 说  明  是否必填 | 最大长度  | 正则
             * email: ['string', '邮件', { required: true, maxLength: @rule.mail.maxLength, pattern: @rule.mail.pattern }]
             *
             * 当Type为'enum'时,TypeOption属性有:
             * 字  段  required | datasource
             * 说  明  是否必填 | 枚举数据源
             * 其中datasource为对应的enum.js中枚举变量的路径,同require规则,如:
             * 引用本模块的Enum模块,则为'./enum/{EnumName}'
             * 引用其它模块,如role模块下的的枚举量,则为'role/enum/{EnumName}'
             * 两个典型的例子如下:
             * status: ['enum', '状态',  { datasource: './enum/Status' }],
             * roles: ['enum', '角色', { datasource: 'role/enum/Roles' }]
             *
             * 当Type为'number'时,TypeOption属性有:
             * 字  段  required | max    | min    | pattern
             * 说  明  是否必填 | 最大值 | 最小值 | 正则
             *
             * 当Type为'bool'时,默认对应了Checkbox控件,TypeOption属性有:
             * 字  段  required
             * 说  明  是否必填
             *
             * 当Type为'array'时,TypeOption属性有:
             * 字  段  required | item
             * 说  明  是否必填 | 数组元素的定义
             * item字段为对数组每一项的实体定义,可嵌套,如字符串数组:
             * authorities: [
             *     'array', '权限列表',
             *     {
             *         item: ['string', '权限项', { maxLength: 50 }],
             *         required: true  // 不填默认为Ture
             *     }
             * ]
             *
             * 当Type为'object'时,TypeOption属性有:
             * 字  段  required | content
             * 说  明  是否必填 | 对象的定义
             * content为对象的定义,key为该对象展开后的各项key,value为每项的实体定义,可嵌套,如:
             * authorities: [
             *     'object', '权限集',
             *     {
             *         content: {
             *             slotView: ['string', '查看广告位', { maxLength: 50 }],
             *             slotModify: ['string', '修改广告位', { maxLength: 50 }],
             *             creative: [
             *                 'object', '创意权限集',
             *                 {
             *                     creativeView: ['string', '查看创意', { maxLength: 50 }],
             *                     ......
             *                 }
             *             ],
             *             ......
             *         },
             *         required: true  // 不填默认为Ture
             *     }
             * ]
             *
             * 当Type为'reference'时,默认对应ToggleSelector控件, TypeOption属性有:
             * 字  段  required | datasource
             * 说  明  是否必填 | 对应的实体名,一般用复数
             *
             * 当Type为'reference-set'时,默认对应CascadingSelector, TypeOption属性有:
             * 字  段  required | datasource
             * 说  明  是否必填 | 对应的实体名,一般用复数
             */
            var entity = {
                id: ['number', 'ID'],
                name: ['string', '广告位名称', { maxLength: 200 }],
                status: ['enum', '状态', { datasource: './enum/Status' }],
                displayOrder: ['number', '显示顺序', { min: 1, max: 10000 }],
                description: ['string', '说明备注', { maxLength: 4000 }]
                // TODO: 添加或修改实体定义,完成后请删除该注释内容
            };

            return entity;
        }
    );

改进表单取消时的检验

改为:

  1. FormView第一次渲染完后,使用form.getData()保存一份表单的数据
  2. 当取消时,再使用form.getData()获取数据,与第1步的数据进行比对

@yanghuabei

[ViewModel]如何绑定View和ViewModel之间的事件

@Exodia

从设计上来看,View会拥有ViewModel的引用,但反之不应该有,因此ViewModel没有办法去监听View的事件

在这种情况下,我们的交互不像Action注册View的事件这种方式,要如何进行?

一个方案是View直接通过set方法来改变ViewModel的数据,再引起change事件刷新View,这样是不是一个合理或者大众化的方式?

几个Selector的重构

  • TableRichSelector的设计应该尽可能地像Select
  • TreeRichSelector的设计应该尽可能地像Tree

类的写法?

第一种:

var proto = {
    constructor: function () {
    },

    foo: 1,

    bar: function () {
    }
};
var Child = Class.create(Parent, proto);
  • 优点:看起来很舒服,符合大部分人的逻辑
  • 缺点:因为proto有个对象语法,多用了4个空格的缩进;不能把私有方法混在中间,因为对象字面量不能断开

第二种:

var proto = {};

proto.contructor = function () {
};

proto.foo = 1;

proto.bar = function () {
};

var Child = Class.craete(Parent, proto);
  • 优点:不浪费缩进
  • 缺点:看到一个方法体之类的,因为没有缩进的区别感觉不出是proto上的还是闭包内部函数

抽象出前后端接口

前后端接口的URL和数据、响应格式各系统均不同,因此把原来BaseData中的东西再拿回去

关于Data的管理

现在的设计中,一个Model可能持有多个Data,但是在销毁时,只会销毁一个主Data,其它的几个没办法销毁,根本原因就是BaseModel并不知道自己到底关联了几个Data

几个解决方案:

第一是把Data完全作为一个模块来管理,构造函数中:

this.data.init({ slot: new SlotData(), creative: new CreativeData() });

使用:

this.data('slot').search(...)
this.data.slot.search(...)

第二是创建时注册,构造函数中:

this.slotData = this.addData(new SlotData());
this.creativeData = this.addData(new CreativeData());

使用:

this.slotData.search(...)

API接口URL规范问题

URL中对于实体名称是否要+s
这会带来困扰,例如:实体名称以s结尾,是否要+es?如果实体是man,复数是men?
不如都不+s

Uploader增加对于提交文件的名称判断

Uploader是基于 type="file" 类型input控件基础上开发的。

原生HTML文件上传控件,当选中文件后,控件value变为文件地址,当取消提交文件时,会将value置空。当value变化时触发change事件。

Uploader.js的receiveFile作为change事件的监听函数,当已经上传图片后,再次选择文件但选择取消,会重复触发。

这边需要做一层判断,对于不选择文件的情况进行抛弃。

抽屉式交互

如BES-C项目,在列表中单击“新建”后是自右向左出现一个抽屉式的层(离左边留一些空间),在其中加载表单页

这种方式和管家中的弹层其实是一个概念,只是视觉效果不同,因此我们需要做的是:

  1. 不要再叫popActionDialog,改叫openActionLayer,用 layer 这样通用化的词来表达“这和主Action不是一个东西”的概念
  2. 新建按钮需要有事件,先preventDefault()阻止默认跳转然后打开层

一个关键的问题是,管家依旧是直接跳转的,要如何去做兼容?

  1. 设一个开关自然可以但肯定是一个丑陋的方案
  2. 如果把抽屉弹层交给业务作为一个扩展会影响重用性
  3. 默认实现掉的话业务系统有机会重写但会比较绕(必须在框架之前注册按钮事件,用stopImmediatePropagation()不让框架的执行,然后自己跳转
  4. 把抽屉的功能独立一个模块业务端自己引用,问题就是如果以后大家都统一了,这个模块删也不是不删也不是

为了复用模块需要做的变更

发现什么就到这里记一下:

  1. Action中的entityDescription之类的字段,不再依赖config模块。进一步说,所有的类都不要依赖config模块,复用时config是不打包走的
  2. 权限的问题,在A系统中的权限名和B系统中不一样,不能在Model中写死,或者需要抽象一层出来做转换
  3. 原本引用underscore的统一改为common/util,此模块继承underscore
  4. RequestManager理论上不需要entityNamebackendEntityName了,这2个属性在RequestStrategy中体现,但这并不是必须的,因此在ub-ria中不再使用,仅作为一种最佳实践,项目需要的话自己继承
  5. config中的type不配模块id,改用ActionFactory实现,工厂要负责组装的东西有:ActionModelViewData(可能有多个)、RequestStrategy(这里需要entityNamebackendEntityName),这导致ActionFactory可能的构造函数参数会很复杂,因此干脆不用构造函数兼容各种情况了,使用属性来解决,未来会移交给IoC
  6. Data依赖于ajax,但ajax的配置是全局的,是否要做成模块级,有待根据需求决定,在两种方式间切换成本并不高
  7. Actiongroup参数也由外部组装,这并不属于Action内部的业务逻辑,仅仅是Action的一种标识,是由所在系统决定的

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.