一峰锁、背景
公司的老項目前端還是用的jquery
,也沒有條件引入vue
,所以對于一個實體對象的取值和賦值還是很麻煩的:
例如:
image.png
所以想擴展一下
$.val()
函數(shù)
二幽七、目標
在html
元素上使用name
結(jié)構(gòu)化數(shù)據(jù)實體竟闪,
然后用val
獲取整個實體离福,可以正確處理子對象和數(shù)組對象以及多選select
。
例如:
三炼蛤、修改方案
找到$().val
的源碼妖爷;
會用jquery
的同學(xué)都很清楚,val
有2個邏輯鲸湃,不帶參是get
赠涮,帶參是set
;
看源碼暗挑,有一個JQuery.valHooks
對象笋除,如果當(dāng)前元素可以匹配到則會直接調(diào)用valHooks
中定義好的get
或set
方法;
所以只要在這里加入我們定義好的元素和處理函數(shù)就可以了
四炸裆、改造Get
先來改造Get
將希望處理的元素全部加進去:
五垃它、改造Set
set方法有一個比較有意思的地方,在數(shù)組的操作中烹看,每次都要能取出數(shù)組中的下一個元素国拇,有點類似C#中的IEnumerator
使用時,需要將數(shù)組轉(zhuǎn)為 Enumerator
再調(diào)用 .next()
方法來獲取下一個值惯殊;
PS:這里有個特殊情況是 <select multiple>
是可以直接用數(shù)組賦值的
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代碼