有状态的javascript对象介绍

引言

我相信,赏脸阅读我这篇文档的客官,你或者已经有过照顾不到一两岁小孩的经历(没有的不要紧,假装自己有小孩,或者赶紧找个异性结婚new一个出来)。以下我将对小孩子的几个行为进行罗列分析:

行为分析大人的反馈行为
发现新奇的事物,或看到奶瓶正在向它接近继续这种正向刺激
饥饿;身体不舒服;确认哭的原因,选择喂食或就医
夜间睡梦中哼哼,踢被子,翻来翻去这是正常的人类 睡眠模式不必太在意

可以看到,当小孩做出不同的行为时,大人总能根据行为正确地判断,做出正确的应对行为。是一种存在因果关系的逻辑。
不可避免地,这种因果关系是无处不在的,包括在我们在前端业务设计时也会遇到。

电子称功能

某物品的单价是m元/千克,重量为n千克,自动计算应支付金额p。
解决的过程可能是这样子的

  1. 创建一个js方法
function fnCalResult_xm(){
    var m = document.getElementsByName("m")[0].value;
    var n = document.getElementsByName("n")[0].value;
    /*这里省略m,n的数据有效性校验*/
	document.getElementsByName("p")[0].value = m * n;
}
  1. 把这个方法加到组件的onblur(或onchange)事件上去
<html>
	<head>
	</head>
	<body>
		<form>
			单价:<input name="m" type="text" onblur="javascript:fnCalResult_xm();"/> <br/>
			重量:<input name="n" type="text" onblur="javascript:fnCalResult_xm();"/> <br/>
			应付金额:<input name="p" type="text" readonly="readonly"/>
		</form>
	</body>
</html>

你可以看到,通过在input组件上添加onblur属性就可以完成这个电子称的功能,so easy。

再看另一种实现方式

同样,是上一节的例子,我们通过javascript对象,来建立一个模型:

var objOrigin = {
	m:0,	//单价
	n:0		//重量
};

可以发现,通过 objOrigin.m * objOrigin.n就可以计算出来应付金额。但问题显而易见,objOrigin是一个静态的对象,它的属性m,n值在发生变化时无法及时捕捉。

所以经过考虑,最好是能建立一种 连锁机制

首先,这个对象的属性可以被改变;
其次,每种属性在被改变时可以触发相应的函数完成逻辑计算。

在dojo中有个dojo.Stateful类,通过它我们可以实现前边所构思的 连锁机制 ,我先把调试好的代码贴上来。

var objOrigin = {
	m:0,
	n:0
};
//下边这行创建了一个有状态的对象
var objCal = new dojo.Stateful(objOrigin); 
var watching_m = objCal.watch("m", function(name, oldValue, value){ 
	dojo.query("input[name='p']")[0].value = this.m * this.n; 
});
var watching_n = objCal.watch("n", function(name, oldValue, value){ 
	dojo.query("input[name='p']")[0].value = this.m * this.n;  
});

第1-4行是普通的javascript对象
第6行生成了一个有状态对象objCal
第7、10行,通过.watch方法,对对象的m、n属性状态在发生变化时,绑定了回调函数(用于处理我们的计算逻辑)。其中回调函数中的name、oldValue、value分别表示被监听的状态的属性名、变化之前的值和变化后的值。

html页面也需要做一些调整,代码如下:

<html>
	<head>
	</head>
	<body>
		<form>
			单价:<input name="m" type="text" onblur="javascript:objCal.set({'m':this.value});"/> <br/>
			重量:<input name="n" type="text" onblur="javascript:objCal.set({'n':this.value});"/> <br/>
			应付金额:<input name="p" type="text" readonly="readonly"/>
		</form>
	</body>
</html>

html代码段中忽略dojo资源的引入,需要实践的同学可以直接在head标签中加入一下代码即可。
<script src=“https://cdn.bootcss.com/dojo/1.6.2/dojo.js”></script>

没有看到dojo.Stateful的优势呀?

是的,上边写了这么多,感觉它与传统的实现方式对比一下,没有觉得它更灵活、功能更强大。
接下来我们再聊一个需求。
某企业财务报账,每个报销人可以通过填写动态表格的方式提交自己的报销记录(可以是一条,也可以是多条),表格的样式可能如下:

序号费用类别费用产生日期含税金额税率不含税金额应付金额备注
1交通费2019/03/01468.0017%400.00468.00西安-大同大巴
2住宿费2019/03/06900.0017%769.23900.005晚汉庭协议价
3交通费2019/03/01293.507%274.30293.50市内+外省出租车费
4招待费2019/03/02525.507%491.10525.50与甲方政委及
信息技术大队干事
5

应付金额总计: 2187.00 元
交通费用总计: 763.50 元 住宿费用总计: 900.00 元 其它费用总计: 525.50 元

考虑到动态表格的特点:行数不定,可以随时增加(删除),随机地对某一行数值进行编辑;当我们完成表格下方的分类统计时,难度会有所增加。
是不是有点惊慌呢?在这里插入图片描述
这里,我就说一说强大的dojox.grid.DataGrid,它就是我们上边所说的动态表格。它的实例对象(可以理解为一个js Object,我们暂时把这个对象的命名为pp吧,就像上一章节中的objOrigin对象一样)有一个context属性,是json格式(如{items:[{“fylx”:“交通费”,“fycsrq”:“2019/03/01”,“hsje”:“468.00”,“sl”:“17%”,“bhsje”:“400.00”,“yfje”:“468.00”,“bz”:“西安-大同大巴”},…]}
而且实现了dojo.Stateful类,这个时候,与上一节的内容结合起来,是不是可以想到,以.watch方法去监控pp对象的context属性值的变化。可能代码会像下边这样:

/* some code, get object of grid*/

var watching_pp = pp.watch("context", function(name, oldValue, value){ 
	/*  注意,这里的value 参数就是动态表格发生更新之后的json文本 */
	/*  将文本内容转化为json 对象 */

   var objJson = dojo.fromJson(value);
	/*  开始进行遍历然后分类统计 */
	dojo.forEach(objJson.items, function(item,index){
        /*  分类统计的代码 */
    });

     /*完成统计后将值填写到页面指定的dom中*/
});

个人认为,通过以上方式完成统计功能,可以免去在input组件上增加onchange(或onblur)事件的事务。而且html代码也显得会比较精简。

ஜ:为了更好地让知识传播分享,希望大神们多提宝贵意见,我会及时改善。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值