一、背景
公司的老项目前端还是用的jquery
,也没有条件引入vue
,所以对于一个实体对象的取值和赋值还是很麻烦的:
例如:
所以想扩展一下
$.val()
函数
二、目标
在html
元素上使用name
结构化数据实体,
然后用val
获取整个实体,可以正确处理子对象和数组对象以及多选select
。
例如:
三、修改方案
找到$().val
的源码;
会用jquery
的同学都很清楚,val
有2个逻辑,不带参是get
,带参是set
;
看源码,有一个JQuery.valHooks
对象,如果当前元素可以匹配到则会直接调用valHooks
中定义好的get
或set
方法;
所以只要在这里加入我们定义好的元素和处理函数就可以了
四、改造Get
先来改造Get
将希望处理的元素全部加进去:
五、改造Set
set方法有一个比较有意思的地方,在数组的操作中,每次都要能取出数组中的下一个元素,有点类似C#中的IEnumerator
使用时,需要将数组转为 Enumerator
再调用 .next()
方法来获取下一个值;
PS:这里有个特殊情况是 <select multiple>
是可以直接用数组赋值的
function Enumerator(array) {
if (array == null) {
return;
}
let index = 0;
this.next = function () {
if (index >= array.length) {
index = 0;
}
return array[index++];
};
this.all = function () {
return array;
};
}
// ...
let val = model[name];
if ($.isArray(val)) {
val = model[name] = new Enumerator(val);
}
if (val instanceof Enumerator) {
if (jq.is("select[multiple]")) {
jq.val(val.all());
} else {
jq.val(val.next());
}
}
但是这样做会改变model对象中的值,所以需要先将model对象拷贝出来使用
function Copied(value) { Object.assign(this, value); }
// ...
const copied = model instanceof Copied ? value : Copied(value);
完整set代码