浅谈Jquery实现简单的双向绑定

 1 var dom = toddyDetailObj.GetDom();
 2                     var formObj = dom.find("input,textarea,select");
 3 
 4                     formObj.each(function () {
 5                         $(this).on("keyup", function () {
 6                             if ($(this).attr("name") !== undefined) {
 7                                 toddyDetailObj.AddDataObj($(this));
 8                             }
 9                         });
10 
11                         $(this).on("change", function () {
12                             if ($(this).attr("name") !== undefined) {
13                                 toddyDetailObj.AddDataObj($(this));
14                             }
15                         });
16 
17                         $(this).on("blur", function () {
18                             if ($(this).attr("name") !== undefined) {
19                                 toddyDetailObj.AddDataObj($(this));
20                             }
21                         });
22                     });
View Code

先上一个代码,主要是双向绑定的基本概念就是在js里面有个缓存的model,当model发生变化,我们的页面上对应的节点应该发生对应的变化,所以,依据这个点,我们在需要做的在页面上面打下标识。

 1 <dl class="dl-horizontal" toddy-data="default" style="position:relative;">
 2     <dt><b class="textwarning">*</b>任务ID:</dt>
 3     <dd>
 4         <input type="text" class="w200" name="ReasonID" value=""/>
 5         <em>系统自动生成.</em>
 6     </dd>
 7     <dt><b class="textwarning">*</b>任务名称:</dt>
 8     <dd>
 9         <input type="text" class=" w200" name="ReasonName" value=""/>
10         <em>可设置该任务的名称.</em>
11     </dd>
12 
13     <dt><b class="textwarning">*</b>出票时间段:</dt>
14     <dd>
15         <input type="text" class="w150" name="OutTicketTimeStart" value=""/>
16 17         <input type="text" class="w150" name="OutTicketTimeEnd" value=""/>
18         <em>请选择需要获取票号状态的出票时间段</em>
19     </dd>
20     <dt><b class="red">*</b>起飞时间段:</dt>
21     <dd>
22         <span style=" color:#cdcdcd; margin-top:10px;">
23             <input type="text" class=" w150" value=""/>
24 25             <input type="text" class=" w150" value=""/>
26             <em>请选择需要获取票号状态的起飞时间段</em>
27         </span>
28     </dd>
29     <dt>可退款客票状态:</dt>
30     <dd>
31         <label><input name="nationality[]" type="checkbox" value="VOID">VOID</label>
32         <label><input name="nationality[]" type="checkbox" value="REFUNDED">REFUNDED</label>
33         <label><input name="nationality[]" type="checkbox" value="OPEN FOR USE">OPEN FOR USE</label>
34         <label><input name="nationality[]" type="checkbox" value="SUSPENDE">SUSPENDE</label>
35         <label><input name="nationality[]" type="checkbox" value="EXCHANGED">EXCHANGED</label>
36         <label><input name="nationality[]" type="checkbox" value="USED/FLOWN">USED/FLOWN</label>
37         <label><input name="nationality[]" type="checkbox" value="LIFT/BOARDED">LIFT/BOARDED</label>
38         <label><input name="nationality[]" type="checkbox" value="CHECKED IN">CHECKED IN</label>
39     </dd>
40     <dt>备注:</dt>
41     <dd>
42         <textarea name="Remark" style="width:300px; height:100px;"></textarea>
43     </dd>
44 
45     <dd toddy-data="PersonList">
46         <table width="500" border="0" cellspacing="0" cellpadding="0" class="wintable">
47             <tbody>
48             <tr>
49                 <th align="left"><span>判断条件</span></th>
50                 <th align="right"><span>操作</span></th>
51             </tr>
52             <tr>
53                 <td align="left"><span>
54               <select class="w180">
55                   <option>买入卖出退票手续费一致</option>
56                   <option>行程单取消或未打印</option>
57               </select>
58               </span></td>
59                 <td align="right"><span>
60               <input type="button" class="add" style="width: 20px;" value="+">
61               </span></td>
62             </tr>
63             <tr>
64                 <td align="left"><span><input type="text" class="w150" name="Condition" value=""/></span></td>
65                 <td align="right"><span>
66               <input type="button" class="reduce" style="width: 20px;" value="-">
67               </span></td>
68             </tr>
69             <tr>
70                 <td align="left"><span><input type="text" class="w150" name="Condition" value=""/></span></td>
71                 <td align="right"><span>
72               <input type="button" class="reduce" style="width: 20px;" value="-">
73               </span></td>
74             </tr>
75             </tbody>
76         </table>
77     </dd>
78 </dl>
View Code

 

我们这里推荐使用的toddy-data来判断,所以只要在页面上面写上这个一个标识这样的一个标识的概念其实和Angular的想法有点类似,这样我们在js里面只需要通过查询这样的一个标识就可以了。只需要获取body里面所有的标签上面有标识的即可,就可以把对应最外层的dom保存下面,后面可以使用,我们一般写一个公用的方法来获取。

                /**
                 * 获取整个DOM,默认获取第一个
                 */
                GetDom: function () {
                    var domObj = $(config.tagName), dom, num = 0;
                    for (var i = 0; i < domObj.length; i++) {
                        if ($(domObj[i]).attr(tagPrefix + "-data") !== undefined && $(domObj[i]).attr(tagPrefix + "-data") !== "" && num === 0) {
                            dom = $(domObj[i]);
                            num++;
                        }
                    }

                    return dom;
                },                    

 接下来就是很简单的给每一个内部的标签上面的表单含有name的加上keyup事件和blur事件,blur是防止中文输入法离开的时候不触发keyup事件,这样可以保证拿到的是对应的值。接下来就是把对应的值放到对应的json对象里面,可以根据自己的想法来处理。

我这里是根据发现标识的层级确定json格式的。其实一般的页面也就2层。多的页面就过于复杂了。这个时候需要使用者自行处理,所以一般会留下一个回调函数。下面贴上js和html。

  1 /**
  2  * Created by luocheng on 2015/10/20.
  3  */
  4 ;
  5 (function ($) {
  6     $.extend({
  7         toddy: function (data) {
  8 
  9             var tagPrefix = "toddy", nowObj, dataTemp = {};
 10 
 11             /**
 12              * 初始化参数
 13              * @type {{callBack: null}}
 14              */
 15             var config = {
 16                 tagName: "form",
 17                 data: {},
 18                 callBack: null
 19             };
 20 
 21             /**
 22              * 公布参数
 23              */
 24             $.extend(config, data);
 25 
 26             /**
 27              *
 28              * @type {{getDom: getDom}}
 29              */
 30             var toddyDetailObj = {
 31                 /**
 32                  * 获取整个DOM,默认获取第一个
 33                  */
 34                 GetDom: function () {
 35                     var domObj = $(config.tagName), dom, num = 0;
 36                     for (var i = 0; i < domObj.length; i++) {
 37                         if ($(domObj[i]).attr(tagPrefix + "-data") !== undefined && $(domObj[i]).attr(tagPrefix + "-data") !== "" && num === 0) {
 38                             dom = $(domObj[i]);
 39                             num++;
 40                         }
 41                     }
 42 
 43                     return dom;
 44                 },
 45                 /**
 46                  * 同步加载对象
 47                  * @param obj
 48                  * @constructor
 49                  */
 50                 AddDataObj: function (obj) {
 51                     var $this = $(obj), isParent = toddyDetailObj.IsParentDom($this, true);
 52                     if (isParent !== "") {
 53                         /**
 54                          * 循环获取当前对象的所有名称不为空的表单,不管什么把所有相同名字的放在一起
 55                          */
 56                         var name = $this.attr("name"), dataArr = [];
 57                         nowObj.find("[name=" + name + "]").each(function () {
 58                             if (toddyDetailObj.GetDomValue($(this)) !== "") {
 59                                 var dataObj = {};
 60                                 dataObj[name] = toddyDetailObj.GetDomValue($(this));
 61                                 dataArr.push(dataObj);
 62                             }
 63                         });
 64 
 65                         if (isParent.indexOf(".") > -1) {
 66                             var isParentArr = isParent.split("."),
 67                                 isParentLen = isParentArr.length,
 68                                 dataName = isParentArr[isParentLen - 1];
 69                             if (dataName !== "") {
 70                                 dataTemp[dataName] = dataArr;
 71                                 config.data[isParentArr[isParentLen - 2]] = dataTemp;
 72                             } else {
 73                                 /**
 74                                  * 配置信息有误提示使用者
 75                                  * @type {string}
 76                                  */
 77                                 var tagName = nowObj.get(0).tagName.toLowerCase(),
 78                                     alertTip = "<" + tagName + " " + tagPrefix + "-data=\"" + isParent + "\"></" + tagName + ">";
 79                                 alert("配置信息有误!\r\n" + alertTip);
 80                             }
 81                         } else {
 82                             config.data[isParent] = dataArr;
 83                         }
 84 
 85                     } else {
 86                         if ($this.attr("name") !== undefined) {
 87                             var isHaveDataName = toddyDetailObj.IsParentDom($this, false);
 88                             if (isHaveDataName !== "" && isHaveDataName.toLowerCase() !== "default") {
 89                                 dataTemp[$this.attr("name")] = toddyDetailObj.GetDomValue($this);
 90                                 config.data[isHaveDataName] = dataTemp;
 91                             } else if (isHaveDataName.toLowerCase() === "default") {
 92                                 config.data[$this.attr("name")] = toddyDetailObj.GetDomValue($this);
 93                             }
 94                         }
 95                     }
 96 
 97                     /**
 98                      * 回调函数
 99                      */
100                     if (typeof config.callBack === "function") {
101                         config.callBack(config.data);
102                     }
103                 },
104                 /**
105                  * 绑定所有表单对象
106                  * @constructor
107                  */
108                 BindEvent: function () {
109                     var dom = toddyDetailObj.GetDom();
110                     var formObj = dom.find("input,textarea,select");
111 
112                     formObj.each(function () {
113                         $(this).on("keyup", function () {
114                             if ($(this).attr("name") !== undefined) {
115                                 toddyDetailObj.AddDataObj($(this));
116                             }
117                         });
118 
119                         $(this).on("change", function () {
120                             if ($(this).attr("name") !== undefined) {
121                                 toddyDetailObj.AddDataObj($(this));
122                             }
123                         });
124 
125                         $(this).on("blur", function () {
126                             if ($(this).attr("name") !== undefined) {
127                                 toddyDetailObj.AddDataObj($(this));
128                             }
129                         });
130                     });
131                 },
132                 /**
133                  * 判断是否父级有标识
134                  * @param obj 当前对象
135                  * @param isMain true标识为子级标签,false获取最上级标识名称
136                  * @returns {string} 如果有标识返回标识
137                  */
138                 IsParentDom: function (obj, isMain) {
139                     var parents = $(obj).parents(), num = 0, data = "";
140                     parents.each(function () {
141                         if ($(this).attr(tagPrefix + "-data") !== undefined) {
142                             if (num === 0) {
143                                 nowObj = $(this);
144                                 data = $(this).attr(tagPrefix + "-data");
145                             }
146                             num++;
147                         }
148                     });
149 
150                     if (num <= 1 && isMain) {
151                         data = "";
152                     }
153 
154                     return data;
155                 },
156                 /**
157                  * 获取对应的表单的值
158                  * @param obj
159                  * @returns {*|defaultGetter}
160                  * @constructor
161                  */
162                 GetDomValue: function (obj) {
163                     var startsWith = function (str, starts) {
164 
165                         if (starts === "") {
166                             return true;
167                         }
168                         if (str === null || starts === null) {
169                             return false;
170                         }
171                         str = String(str);
172                         starts = String(starts);
173                         return str.length >= starts.length && str.slice(0, starts.length) === starts;
174                     };
175 
176                     var endsWith = function (str, ends) {
177 
178                         if (ends === "") {
179                             return true;
180                         }
181                         if (str === null || ends === null) {
182                             return false;
183                         }
184                         str = String(str);
185                         ends = String(ends);
186                         return str.length >= ends.length && str.slice(str.length - ends.length, str.length) === ends;
187 
188                     };
189 
190                     var contains = function (obj, target) {
191                         var flag = false;
192                         if (obj == null) {
193                             return false;
194                         }
195 
196                         if ($.isArray(obj)) {
197                             for (var i = 0; len = obj.length, i < len; i++) {
198                                 if (obj[i] === target) {
199                                     flag = true;
200                                 }
201                             }
202                         }
203                         return flag;
204                     };
205 
206                     var getters = {
207                         "SELECT": function () {
208                             return $(obj).val();
209                         },
210                         "INPUT": function () {
211                             var type = $(obj).attr("type").toLowerCase();
212                             if (contains(["text", "password"], type)) {
213                                 return $(obj).val();
214                             }
215                             if (contains(["checkbox", "radio"], type)) {
216                                 return $(obj).attr("checked") ? $(obj).val() : null;
217                             }
218                         },
219                         "TEXTAREA": function () {
220                             return $(obj).val();
221                         }
222                     };
223 
224                     var defaultGetter = function () {
225                         return $(obj).html();
226                     };
227 
228                     var elementType = $(obj).get(0).tagName.toUpperCase();
229                     var getter = getters[elementType] || defaultGetter;
230                     return getter();
231                 },
232                 dealDomObj: function () {
233                     var dom = toddyDetailObj.GetDom();
234                     console.log(dom.find("[toddy-data]"));
235                     for (var item in config.data) {
236                         var temp = config.data[item];
237                         if ($.isArray(temp)) {
238                         } else {
239                             toddyDetailObj.dealDomValue(dom.find("[name='" + item + "']"), temp);
240                         }
241                     }
242                 },
243 
244                 dealDomValue: function (dom, data) {
245                     var domName = toddyDetailObj.getDomTagName(dom);
246                     var setter = {
247 
248                     };
249 
250 
251                 },
252                 getDomTagName: function (dom) {
253                     var $dom = $(dom);
254                     return $dom.get(0).tagName.toUpperCase();
255                 },
256                 initEvent: function () {
257                     var dom = $("[" + tagPrefix + "-data]"), flag = true, num = 0, nowObjTemp, isParent = "";
258                     dom.each(function () {
259                         var data = $(this).attr(tagPrefix + "-data");
260                         if (data.split(".").length > 2) {
261                             if (num === 0) {
262                                 nowObjTemp = $(this);
263                                 isParent = data;
264                             }
265 
266                             flag = false;
267                             num++;
268                         }
269                     });
270 
271                     if (flag) {
272                         toddyDetailObj.BindEvent();
273                     } else {
274                         /**
275                          * 配置信息有误提示使用者
276                          * @type {string}
277                          */
278                         var tagName = nowObjTemp.get(0).tagName.toLowerCase(),
279                             alertTip = "<" + tagName + " " + tagPrefix + "-data=\"" + isParent + "\"></" + tagName + ">";
280                         alert("目前我们只支持2级Model,配置信息有误!\r\n" + alertTip);
281                     }
282                 }
283             };
284 
285             toddyDetailObj.initEvent();
286             return config.data;
287         }
288     });
289 })(jQuery);

 

转载于:https://www.cnblogs.com/toddyinchina/p/4901291.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值