Dorado客户端JS代码编写规范

2024-03-07 18:37 更新

JavaScript和Java虽然在语法上有些相近,但其实是差别很大的两种编程语言!

Dorado是全新的事物,也必然会带来很多全新的使用方法和最佳实践。当然,最佳实践这种东西原本是需要一些时间和应用来积累和验证的,在目前阶段我只能根据个人的经验来大体总结出一些开发建议。 本文列举了一些我近期在各项目中看到的不够好的JavaScript代码,既有关于JavaScript本身的,也有关于Dorado的。

了解JavaScript中的逻辑判断

JavaScript不是Java!JavaScript是弱类型语言!所有类型的数值都可以用于逻辑判断和逻辑运算。 所以要搞清楚String、Number、Boolean、Object这些类型在用于逻辑判断时都会出现什么样的结果。 例如不要编写如下这么啰嗦的代码来判断一个字符串是否有效:

if (str != null && str != "") {
    ... ...
}

你完全可以这样写:

if (str) {
    ... ...
}

也可以进行逻辑运算:

if (!str) {
    ... ...
}

其他类型的变量同样如此。

熟练运用Dorado对象的get和set

Dorado对象的get和set方法提供了很多实用的小技巧,善用这些技巧可以事半功倍。并且以下的这些技巧可以自由的搭配使用,以便于让get和set在各种复杂的场景中发挥出最大的功效。 使用批量set 当需要对一个对象的多个属性进行连续的赋值时,应尽可能使下面的语法:

foo.set({
    readOnly: true,
    value: "dorado"
})

而下面这种等效的写法是不被推荐的,既罗嗦又低效。

foo.set("readOnly", true);
foo.set("value", "dorado");

使用迭代式的get和set get和set方法都支持迭代式的属性访问,即通过"."来分割一组属性名,交由此方法一层层向下挖掘并返回最终结果或设置目标属性。 当进行迭代式的读取时,系统会自动判断前一个属性返回的对象是dorado.AttributeSupport的实例还是普通JSON对象,并藉此决定如何进一步执行读取操作:

  • 如果碰到的中间对象dorado.AttributeSupport的实例,系统会自动读取它的Attribute
  • 如果碰到的中间对象是普通的JSON对象,系统会直接读取它的属性。

oop.get("address.postCode"); // 迭代式的属性读取
// 如果address的属性值是一个dorado.AttributeSupport的实例,那么此行命令的效果相当于oop.get("address").get("postCode")。
// 如果address的属性值是一个JSON对象,那么此行命令的效果相当于oop.get("address").postCode

 
oop.set("address.postCode", 54733226); // 迭代式的属性赋值
// 相当于oop.get("address").set("postCode",54733226) 或oop.get("address").postCode = 54733226

运用某些对象为get方法提供的特殊扩展 Dorado中的某些对象为get方法提供了特殊的扩展,通过这些扩展我们甚至可以访问一些对象的Attribute之外的功能,这写扩展进一步Dorado的开发体验。 View

  • 当属性名以'#'开头时,Dorado会将其后的内容识别为控件的id。表示根据此id获取相应的控件。
  • 当属性名以'^'开头时,Dorado会将其后的内容识别为对象的tag。表示根据此tag获取相应的对象。
  • 当属性名以'@'开头时,Dorado会将其后的内容识别为DataType的name。表示根据此name获取相应的DataType。

DataType

  • 当属性名以'@'开头时,Dorado会将其后的内容识别为其中某个PropertyDef的name。表示根据此name获取相应的PropertyDef。

DataSet

  • 当属性名以'data:'开头时,Dorado会将其后的内容识别为datapath。表示利用该datapath调用此DataSet的queryData()方法。以上这些特殊的扩展并不妨碍迭代式get和set调用。例如下面的用法是有效的。

// 首先获得id为editorType的控件,然后返回其value属性。
var value = view.get("#editorType.value");

// 首先获得View中拥有advanceButton标签的所有对象,然后批量设置它们的disabled属性。
view.set("^advanceButton.disabled", true);

// 首先获得id为dataSetDepts的DataSet,然后返回其中"#.employees"代表的数据。
var employees = view.get("#dataSetDepts.data:#.employees");

利用set为对象绑定事件 set方法不但可以用于为对象的属性赋值,同时也可以用于为对象中的事件添加事件监听器。

// 使用上文中提及的第一种方法为label属性赋值,同时为onClick事件绑定一个监听器。
oop.set({
    label : "Sample Text",
    onClick : function(self, arg) {
        ... ...
    }
});

学会使用控件的tag属性

通过设置tag属性以便于批量的查找和操作一组控件或对象,这是Dorado中非常有特色的一种功能。该功能可以在很多场景下极大的简化代码。 在利用tag查找对象时Dorado会将所有匹配的对象封装成一个ObjectGroup并返回。通过ObjectGroup,我们可以对其中的所有对象进行批量的属性设置或方法调用。 在使用tag功能时,建议利用View对象对get和set方法所作的"^"前缀扩展,这可以让代码进一步的得到简化。

// 首先获得View中拥有advanceButton标签的所有对象,然后批量设置它们的disabled属性。
view.set("^advanceButton.disabled", true);

尽可能使用异步的数据通讯

  • 尽可能使用dataSet.flushAsync()而不是dataSet.flush()
  • 尽可能使用尽可能不要将action的async属性设置为false尽可能使用ajax.request()而不是ajax.requestSync()
  • 尽管异步的数据通讯会带来一定的复杂度,但是出于改变用户界面整体操作效率和提高界面友好度的角度出发。我仍然强烈建议使用异步的通讯机制。要使用异步的通讯机制必须掌握闭包(回调函数的基本用法)。
  • 使用异步的通讯机制至少可以带来以下两方面的好处:
  • 在异步的通讯机制的执行过程中浏览器不会出现假死现象,甚至对于某些异步通讯我们可以运行用户在执行过程中进行其他的页面操作。
  • Dorado中提供了异步通讯的自动合并功能,可以将短时间发出的多次异步通信合并成一个物理请求,降低网络和服务器开销。

减少无谓的dataSet.flush()

我在很多系统都见到过在页面初始化阶段执行一到多次的dataSet.flush(),其实这些操作理论上都是可以避免的。 出现此类操作的主要原因是开发人员在页面初始化阶段通过JavaScript确定DataSet的parameter属性的值,然后再利用dataSet.flush()从服务端提取相应的数据。而这里所说的parameter在很多情况下是可以在服务端的页面准备阶段直接获得的。例如通过在DataSet的parameter属性中填写EL表达式的方式。

善用Argument和EL表达式简化代码

假设你需要根据外部条件来设置界面上的10个TextEditor的readOnly属性,并且这种操作是一次性的,不会在用户的操作过程中再次改变。那么利用控件的tag属性在View的onReady事件中设置并不是最好的选项。这会让代码的可读性变得稍差,更重要的是这会让这10个控件在初始阶段经历两次刷新,对性能造成不显著的损害。 对于这种情况,我们应该考虑直接在服务端设定好这些readOnly属性。例如直接在这10个?控件的readOnly属性中编写 ${req.operation=="edit"} 这样的EL表达式。可是一旦未来此处的判断逻辑面临调整,你又必须再一次把这10个TextEditor全部找出来并一一调整其中的EL表达式。 为了避免这种尴尬,最好的办法是在View中声明一个Argument,将上面的EL表达式定义在这里并且让10个TextEditor的readOnly属性引用该Argument。例如:我们声明一个名为为readOnly的Argument的,其值为 ${req.operation=="edit"},然后在TextEditor的readOnly属性中通过 ${argument.readOnly}来引用它。

掌握each迭代

Dorado中的很多对象都支持each迭代,each迭代可以另代码看起来更加简洁明了。目前支持each迭代的对象包括:

  • Array(即标准的JavaScript数组,Dorado修改了JavaScript中Array的prototype)
  • dorado.EntityList
  • dorado.ObjectGroup
  • dorado.util.KeyedArray
  • dorado.util.KeyedList 例如以下是对Array的each迭代:

var s = '';
['A', 'B', 'C'].each(function(item) {
    s += item;
});
// s == "ABC"

不要总是使用JavaScript注释

JavaScript是解释执行的语言,这一点不同与于Java,所以其对代码注释的处理也有所不同。在Java中,被注释掉的代码不会在运行时产生影响。而在JavaScript中,被注释掉的代码仍然会被输出到客户端。这意味这着这些注释仍然会产生网络开销。 在实际应用的场景中,我甚至见到过很多Client端事件中除了大段的代码注释外没有任何一行有效代码的情况。这意味着Dorado仍会为这些注释生成一个无用的事件监听器。 所以,对于那些已经不再需要的代码,请果断删除而不是使用注释。你可能会觉得的这些代码未来或还会用的到,但实际的情况是,99%的情况下你再也不会用到他们了,而且一个小时你就会把这些注释忘到一干二净。

美化你的JavaScript

编程就像写作。要把一件事情讲清楚,你既可以写一篇流水帐也可以写一篇文章,要怎样做取决于你对待这件事情的态度。 这原本不应该是本文应该讨论的话题,然而我在日常的工作中却见到了太多类似下面这样的糟糕代码:

var sum = this.id("dataSet").get("#.price") * this.id("dataSet").get("#.num");
this.id("dataSet").get("#").set("sum", sum);
... ... ...
if (this.id("checkboxDetail").get("checked") == true) {
    this.id("textEditorHomePage").set("visible", true);
    this.id("textEditorEmail").set("visible", true);
    this.id("textEditorDesc").set("visible", true);
}
else {
    this.id("textEditorHomePage").set("visible", false);
    this.id("textEditorEmail").set("visible", false);
    this.id("textEditorDesc").set("visible", false);
}

如果以写作水平的角度来评价这段代码,大概还处在小学二年级水平。而实际的情况往往比这例子中的更加令人作呕(幸亏浏览器不会吐)!代码里充斥着无用的注释片段、没有基本的缩进格式、定义之后又被废弃的变量...... 我相信写出类似水准代码的同事是知道好的代码应该是什么样子的,之所以仍然会写出这些丑陋的代码,关键还在于态度。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号