如何保持数据function和变量DRY?

如何让这个Jquery变干?

// Adding data to input depending on what div is clicked $('#navninfoDiv').click(function() { $('input#webhost_navninfo').data('myData', null); }); $('#navninfoDivP').click(function() { $('input#webhost_navninfo').data('myData', 'p'); }); $('navninfoDivV').click(function() { $('#inputwebhost_navninfo').data('myData', 'V'); }); // Adding data to input depending on what div is clicked $('#prisinfoDiv').click(function() { $('#inputwebhost_prisinfo').data('myData2', null); }); $('#prisinfoDivP').click(function() { $('#inputwebhost_prisinfo').data('myData2', 'p'); }); $('#prisinfoDivV').click(function() { $('#inputwebhost_prisinfo').data('myData2', 'V'); }); // Adding data to input depending on what div is clicked $('#cableinfoDiv').click(function() { $('#inputwebhost_cableinfo').data('myData3', null); }); $('#cableinfoDivP').click(function() { $('#inputwebhost_cableinfo').data('myData3', 'p'); }); $('#prisinfoDivV').click(function() { $('#inputwebhost_cableinfo').data('myData3', 'V'); }); // Adding data to input on submit $('#smt').click(function() { // for input#webhost_navninfo var myData = $('#webhost_navninfo').data('myData'), val = $('#webhost_navninfo').val(); if (myData) { $('#webhost_navninfo').val(myData + val); } // for input#webhost_prisinfo var myData2 = $('#webhost_prisinfo').data('myData2'), val2 = $('#webhost_prisinfo').val(); if (myData2) { $('#webhost_prisinfo').val(myData2 + val2); } // for input#webhost_cableinfo var myData3 = $('#webhost_cableinfo').data('myData3'), val3 = $('#webhost_cableinfo').val(); if (myData3) { $('#webhost_navninfo').val(myData3 + val3); } }); 

如何干掉所有这些代码? 我有更多的输入字段约50。

这是我的HTML和jQuery没有数据函数: http : //jsfiddle.net/z5qeX/2/

我在这个例子中给出的代码示例只是为了说明我想要的function。 它与jsfiddle中的HTML不匹配,但它是我想要稍后添加它的代码。

这是我的简单解决方案,脚本非常少,只要您将所有3种类型的div添加几个数据属性,如下所述。 而不是使用mydatamydata2mydata3我们可以使用mydata作为所有类型输入的数据属性名称。

这是工作演示

标记

    
prisinfo
prisinfop
prisinfoV
cableinfo
cableinfop
cableinfoV

JS

 $(function(){ //Adding data to input //This will attach click event handler to all the divs //whose id contains 'infoDiv' $('div[id*=infoDiv]').click(function() { $('#webhost_'+$(this).data('type')).data('myData', $(this).data('info')); }); // Setting value to input on submit $('#smt').click(function() { var $this; //This will loop through all the input fields whose id starts ' //with 'webhost and prepend data('myData') to its value $("input[id^=webhost]").each(function(){ $this = $(this); $this.val(($this.data("myData") || '') + $this.val()); }); }); }); 

我希望这可以帮助你。

这是您提供的代码的完美改进。 还有其他解决方案(如ShankarSangoli)为您提供了需要修改HTML的良好替代方案,但这应该与您现在拥有的完全一致。

这将在多次通过中完成,因此我可以解释发生了什么。

 // pass 1 you have three sets of information, the difference is the // div which has the listener, and the default data. (I've taken the liberty to // make all of the names consistent. $('#navninfoDiv').click(function() { // based on your HTML, I believe that the input# is superfluous $('#webhost_navninfo').data('myData', null); }); $('#navninfoDivP').click(function() { $('#webhost_navninfo').data('myData', 'p'); }); $('navninfoDivV').click(function() { $('#webhost_navninfo').data('myData', 'V'); }); $('#prisinfoDiv').click(function() { $('#webhost_prisinfo').data('myData2', null); }); /* ... */ $('#cableinfoDiv').click(function() { $('#webhost_cableinfo').data('myData3', null); }); /* ... */ 

由于您使用的是命名约定,因此实际上很简单。 首先,我们将“数据”部分放在一个循环中:

 var defaults = [null, "P", "V"] for( var i = 0; i < defaults.length; i++ ) { var divID = '#navninfoDiv' + ( defaults[i]?defaults[i]:"" ); $(divID).click(function() { $('#webhost_navninfo').data('myData', defaults[i]); }); } for( i = 0; i < defaults.length; i++ ) { var divID = '#prisinfoDiv' + ( defaults[i]?defaults[i]:"" ); $(divID).click(function() { $('#webhost_prisinfo').data('myData2', defaults[i]); }); } for( i = 0; i < defaults.length; i++ ) { var divID = '#cableinfoDiv' + ( defaults[i]?defaults[i]:"" ); $(divID).click(function() { $('#webhost_cableinfo').data('myData3', defaults[i]); }); } 

基于此,看起来我们仍然有一些已重复的代码,如果我们也对div的ID进行循环怎么办?

 var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ]; var defaults = [null, "P", "V"] for( var j = 0; j < baseIDs.length; j++ ) { for( var i = 0; i < defaults.length; i++ ) { var divID = '#'+baseIDs[j]+'Div' + ( defaults[i]?defaults[i]:"" ); $(divID).click(function() { var dat = i? 'myData': 'myData' + String( i + 1 ); $('#webhost_'+baseIDs[j]).data(dat, defaults[i]); }); } } 

这看起来不太干净。 我敢打赌,把所有这些中心的东西都放到它自己的小function中并不难,这将使调试变得更容易,更清洁:

 var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ]; var defaults = [null, "P", "V"] for( var j = 0; j < baseIDs.length; j++ ) { for( var i = 0; i < defaults.length; i++ ) { var datLab = 'myData' if( i ) datLab += String( i + 1 ); assignClickListener(baseIDs[j], defaults[i], datLab); } } function assignClickListener(base, defaults, datLab) { var divID = '#'+base+'Div' + ( defaults?defaults:"" ); $(divID).click(function() { $('#webhost_'+base).data(datLab, defaults); }); } 

所以,现在我们已经完成了脚本的第一部分。 让我们看看是否有类似的方式来查看脚本的第二部分。

 // I'm going to omit this until we re-unite all of the code at the end. $('#smt').click(function() { // so you have the same looping structure here: var myData = $('#webhost_navninfo').data('myData'), val = $('#webhost_navninfo').val(); if (myData) { $('#webhost_navninfo').val(myData + val); } var myData2 = $('#webhost_prisinfo').data('myData2'), /* ... */ var myData3 = $('#webhost_cableinfo').data('myData3'), val3 = $('#webhost_cableinfo').val(); if (myData3) { // this looks like a mistake. I will assume that it is supposed // to be webhost_cableinfo. $('#webhost_navninfo').val(myData3 + val3); } }); 

好吧,既然循环上次工作得很好,为什么我们不再尝试做同样的事情呢?

 var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ]; for( var i = 0; i < baseIDs.length; i++ ) { var datLab = 'myData' if( i ) datLab += String( i + 1 ); var currentBase = baseIDs[i]; var myData = $('#webhost_'+currentBase).data(datLab), val = $('#webhost_'+ currentBase).val(); if (myData) { $('#webhost_' + currentBase).val(myData + val); } } 

哎呦。 看起来我错过了那里的东西 - 我可以重复使用那个ID:

 var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ]; for( var i = 0; i < baseIDs.length; i++ ) { var datLab = 'myData' if( i ) datLab += String( i + 1 ); // since this is actually the ID now, I've renamed the variable. var currentID = '#webhost_'+baseIDs[i]; var myData = $(currentID).data(datLab), val = $(currentID).val(); if (myData) { $(currentID).val(myData + val); } } 

嗯......我打赌我可以缓存更多:

 var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ]; for( var i = 0; i < baseIDs.length; i++ ) { var datLab = 'myData' if( i ) datLab += String( i + 1 ); // I can actually cache this entire element. I'll do that: var currentElem = $('#webhost_'+baseIDs[i]); var myData = currentElem.data(datLab), // val = currentElem.val(); 

你的代码似乎有些不一致,所以我做了一些假设。 例如,我不确定你是否总是指$('input#webhost_navninfo')$('#inputwebhost_navninfo')

 var infoDivs = ['navninfo', 'prisinfo', 'cableinfo']; // Adding data to input depending on what div is clicked $.each(infoDivs, function(index, divBaseName) { var dataIndex = index + 1; $('#' + divBaseName).click(function() { $('#inputwebhost_' + divBaseName).data('myData' + dataIndex, null); }); $('#' + divBaseName + 'P').click(function() { $('#inputwebhost_' + divBaseName).data('myData' + dataIndex, 'p'); }); $('#' + divBaseName + 'V').click(function() { $('#inputwebhost_' + divBaseName).data('myData' + dataIndex, 'v'); }); }); $('#smt').click(function() { $.each(infoDivs, function(index, divBaseName) { var myDataIndex = index + 1; var elem = $('#webhost_' + divBaseName); var myData = elem.data('myData' + myDataIndex); var val = elem.val(); if(myData) { elem.val(myData + val); } }); }); 

如果您不关心myData的编号方式,只要信息全部正确关联,那么您可以摆脱变量dataIndex并在两种情况下都使用index

你可以尝试:

 var config = { "prefix" : { "navinfo": "", "prisinfo": "2", "cableinfo": "3" }, "map" : { "": null, // Not a 100% sure about this. Worked on Chrome for me, but should try it in IE see if it works or chokes. "P": "p", "V": "v" } }; for (section in config['prefix']) { for (m in config['map']) { $('#' + section+ 'Div' + m ).click(function() { $('input#webhost_navninfo').data('myData' + config['prefix'][section], null); }); } } 

并为其余部分做类似的事情。 在$(“#smt”)中。点击位。

一次只定义所有这些文字是个好主意。

 var divP = 'P'; var divV = 'v'; 

对DOM元素引用执行相同操作可以避免jQuery一次又一次地识别元素。 所以它运行得更快。

 var webHostNavInfo = $('#webhost_navninfo'); var inputWebHostNavInfo = $('#inputwebhost_navninfo'); 

以下是第一关。 我不确定你想要走多远,但正如arunkumar指出的那样,它可能都是数据驱动的。

一些可能有用的问题:

  • 您是否需要为每个数据值使用不同的数据键? 如果没有,这可以压缩。
  • 你可以使用类(而不是ID)来识别这些元素吗? 如果是这样,一切都可以立即检测,并且(可能)消除了循环。
  • 你可以在这里命名这个行为,并将其封装到一个插件中吗? 如果是这样,那将澄清代码和因果关系。 我不明白whta navninfo与prisinfo对比cableinfo是什么,所以我无法在逻辑上做任何事情来共享代码。

以下是较小的代码。 它当然可以更干(一个创建点击处理程序的函数吗?),但是如果不了解上下文,我会犹豫不决:

 var infoDivs = ['navninfo', 'prisinfo', 'cableinfo']; // Adding data to input depending on what div is clicked $.each(infoDivs, function(index, divBaseName) { var key = 'myData' + (index + 1); var $elem = $('#inputwebhost_' + divBaseName); $('#' + divBaseName).click(function() { $elem.data(key, null); }); $('#' + divBaseName + 'P').click(function() { $elem.data(key, 'p'); }); $('#' + divBaseName + 'V').click(function() { $elem.data(key, 'v'); }); }); $('#smt').click(function() { $.each(infoDivs, function(index, divBaseName) { var $elem = $('#webhost_' + divBaseName); var myData = $elem.data('myData' + (index + 1)); var val = $elem.val(); if(myData) { $elem.val(myData + val); } }); }); 

这里的想法是对标记进行最小的更改,并以最少的代码实现目标。

假设你有像这样的标记:

    
prisinfo
prisinfop
...

我在容器div中重新排列它:

  • 利用非常有效的.delegate()
  • 使选择代码更容易阅读

HTML:

  
prisinfo
prisinfop
prisinfoV
cableinfo
cableinfop
cableinfoV

JS:

 // if all we need is to access the data during submit, // we can store it in an object for faster access var submitData = submitData || {}; $(function(){ $('#container').delegate('div', 'click', function(){ // figure out our delimiter var delimiter = 'Div', delimiterIndex = this.id.indexOf(delimiter); // extract type var type = this.id.substring(0, delimiterIndex); // extract data var data = this.id.substring(delimiterIndex + delimiter.length); // optional - uncomment to store null in place of empty string // data = (data == "") ? null : data; // assign data to appropriate type (navinfo, prisinfo etc.) // overwrite if already there submitData[type] = { selector: '#webhost_' + type, data: data}; }); $('#smt').click(function() { $.each(submitData, function(key, info){ // get the input selector and its value var $inp = $(info.selector) val = $inp.val(); // append to existing value $inp.val(info.data + val); }) // comment out to perform submit return false; }); }); 

点击直播演示

试图保持简单和可读,并做出所有这些假设。 我希望这会让你朝着正确的方向前进。

我很喜欢Shankar的答案因为使用了数据属性。 但是,我不喜欢那些讨厌的选择者。 加上太多的.data包调用,这是我试图避免的开销。