我正在构建一个简单的锻炼程序应用程序,但是我想简化Javascript / Jqwery代码

时间:2018-08-08 22:31:00

标签: javascript jquery arrays function for-loop

这是我的代码

 $('#addmaxes').on('click',function(){
dlMax = $('#dlcurrentmax-input').val().trim();
ftsqMax = $('#ftsqcurrentmax-input').val().trim();
per = 95;
dlTrainingMax = (dlMax * per) / 100;
frsqTrainingMax = (ftsqMax * per) / 100;
per= 75;
var weekDl = (dlTrainingMax * per) / 100;
var rnWeekDl = Math.floor(weekDl);
per2= 60;
var weekDef = (dlTrainingMax * per2) / 100;
var rnDefWeek = Math.floor(weekDef);
var weekSq = (frsqTrainingMax * per2) / 100;
var rnWeekSq = Math.floor(weekSq);
var newDivOne = $('<div>');
var newDivTwo = $('<div>');
newDivOne.addClass('trainingProgram');
newDivTwo.addClass('trainingProgram');
newDivOne.html('<h3>Week 1');
newDivTwo.html('Deadlift (75%): 3x5 at ' + rnWeekDl + '<br/>Deficit Deadlift (60%): 8x3(90sec rest between sets) at ' + rnDefWeek + '<br/>Front Squat (60%): 3x8 at ' + rnWeekSq + '<br/>Stiff-leg deadlift: 3x8 ' + '<br/>Bent over rows: 3x8' + '<br/>Lat pulldowns:  3x12');

$('#program').append(newDivOne);
$('#program').append(newDivTwo);
}); 

因此,基本上,我多次复制并粘贴此函数,并更改每个函数中添加的html以显示该周的锻炼。(因此,每个复制的函数代表一个锻炼周)。 我发现简化代码的一种方法是创建这样的对象数组:

const PERCENT_FOR_MAX = 95;
var percentagesPerWeek = [
{
deadlift: 75,
frontSquat: 50,
},
{
deadlift: 80,
frontSquat: 65,
},
/// etc
];

然后将for循环添加到我的函数中,如下所示:

$('#addmaxes').on('click',function(){
for(var i = 0; i < percentagesPerWeek.length; i++) {
dlMax = $('#dlcurrentmax-input').val().trim();
ftsqMax = $('#ftsqcurrentmax-input').val().trim();
dlTrainingMax = (dlMax * PERCENT_FOR_MAX) / 100;
frsqTrainingMax = (ftsqMax * PERCENT_FOR_MAX) / 100;
var deadliftPercent = percentagesPerWeek[i].deadlift;
var weekDl = (dlTrainingMax * deadliftPercent) / 100;
var rnWeekDl = Math.floor(weekDl);
var frontSquatPercent = percentagesPerWeek[i].frontSquat;
var weekDef = (dlTrainingMax * frontSquatPercent) / 100;
var rnDefWeek = Math.floor(weekDef);
var weekSq = (frsqTrainingMax * frontSquatPercent) / 100;
var rnWeekSq = Math.floor(weekSq);
var newDivOne = $('<div>');
var newDivTwo = $('<div>');
newDivOne.addClass('trainingProgram');
newDivTwo.addClass('trainingProgram');
newDivOne.html('<h3>Week 2</h3>');
newDivTwo.html('Deadlift ('+deadliftPercent+'%): 3x5 at ' + rnWeekDl +
  '<br/>Deficit Deadlift (65%): 8x3(90sec rest between sets) at ' + rnDefWeek +
  '<br/>Front Squat ('+frontSquatPercent+'%): 3x8 at ' + rnWeekSq +
  '<br/>Stiff-leg deadlift: 3x8 ' +
  '<br/>Bent over rows: 3x8' +
  '<br/>Lat pulldowns:  3x12'
);
$('#program').append(newDivOne);
$('#program').append(newDivTwo);
}});

但是我遇到的问题是每个功能中的html每周都会相同,并且由于锻炼方式的变化,我需要每周对其进行自定义。我怎样才能做到这一点。我是Web开发的新手,仅做了一个月。因此,很抱歉,如果我的上下文没有意义,这也是我第一次发布此论坛。提前致谢。 :)

1 个答案:

答案 0 :(得分:0)

如果您只是开始学习JavaScript,请尝试避免使用jQuery-在现代Web浏览器上进行Web开发时确实不需要拐杖。此外,本机浏览器API的性能更高。

您的点击处理程序功能不必显式包含在事件侦听器中。 关注点分离(SoC)原则指出,应避免在设计/代码中共同定位不同的关注点。这意味着您应该将处理事件的功能与触发处理程序的事件侦听器分开。

您应该将处理程序设置为您传入的命名函数,

var addMaxesHandler = function(event) {
  // handle the '#addmaxes' click event here

  // assuming you need integer values
  var dlMax = Math.parseInt(document.getElementById('dlcurrentmax-input').value, 10);
  var ftsqMax = Math.parseInt(document.getElementById('ftsqcurrentmax-input').value, 10);
  var presentationData = doTheCalculations(percentagesPerWeek, dlMax, ftsqMax);

  presentTheResults(presentationData);
};

// attach the listener to the HTML element
var el = document.getElementById('addmaxes');
el.addEventListener('click', addMaxesHandler);

这也意味着您以后可以使用removeEventListener()将其删除。您不能使用匿名功能来做到这一点。

还记得单一责任原则(SRP)吗?在您的情况下,您应该让函数仅执行一项任务,而仅执行一项任务-请勿将计算与演示文稿混在一起。不断将问题分解为更小的部分,并将结果组合在一起。

function doTheCalculations(dataArr, dl, ftsq) {

  // need a container for holding the results of calculations
  var calculationResults = [];

  // iterate through the 'percentagesPerWeek' array
  dataArr.forEach(function(values, index){
    // values is the array element e.g. { deadlift: 75, frontSquat: 50 }
    // index is the array index e.g. 0 for the first element of the array
    calculationResults.push(doTheMathsFunc(values, dl, ftsq));
  });

  return calculationResults;
}

我还没有实现它,但是doTheMathsFunc()应该执行计算并返回一个包含要在演示文稿中使用的值的对象或数组。此时,您已经返回了另一个对象数组,可用于创建HTML。

function presentTheResults(resultsArr) {
  // this function will iterate through the array and build the HTML

  // use DocumentFragment object for efficiency
  var fragment = document.createDocumentFragment();

  // get some HTML content
  resultsArr.forEach(function(result, index){
    var weekFragment = getWeekHtmlBlock(result, (index + 1));
    fragment.appendChild(weekFragment);
  });

  // get a handle on the DOM container element
  var container = document.getElementById('program');

  // add the DocumentFragment to the DOM
  container.appendChild(fragment);
}

该功能只是将HTML片段拼接在一起,然后将结果附加到DOM。 HTML片段是由另一个函数getWeekHtmlBlock()创建的。

// build the block of HTML content for the week
function getWeekHtmlBlock(content, week) {
  // content : object containing the information
  // week : the week number
  var fragment = document.createDocumentFragment();
  // create HTML elements
  var outerDiv = document.createElement('div');
  var innerDiv = document.createElement('div');
  // add the CSS class
  outerDiv.classList.add('trainingProgram');
  // add the H3 tag : e.g. 'Week 1'
  var h3 = document.createElement('h3');
  h3.textContent = "Week " + week;
  outerDiv.appendChild(h3);
  // iterate through the 'content' object and build the HTML elements
  // these should be appended to 'innerDiv'

  // TO DO !
  innerDiv.appendChild( getInstructionsHtml(content, week) );

  // append the HTML elements
  outerDiv.appendChild(innerDiv);
  fragment.appendChild(outerDiv);
  // return the HTML
  return fragment;
}

希望到现在为止您已经有了主意-继续使用函数来解决较小的问题。

如果您需要更改每周要显示的说明,那么最好创建一个包含每个说明的对象的数组。数组的第一个元素将包含第一周的说明,依此类推。

Template literals/Template strings是ES2015的功能,因此您现在应该可以利用它们。 Deconstructing assignment也是ES2015中添加的JavaScript功能。

// example array of instructions
var weeklyInstructionsArray = [
  [`Deadlift (${deadliftPercent}%): 3x5 at ${rnWeekDl}`,
  `Deficit Deadlift (65%): 8x3 (90sec rest between sets) at ${rnDefWeek}`,
  `Front Squat (${frontSquatPercent}%): 3x8 at ${rnWeekSq}`,
  `Stiff-leg deadlift: 3x8`,
  `Bent over rows: 3x8`,
  `Lat pulldowns: 3x12`]
];

function getInstructionsHtml(data, weekNum) {

  var instructions = weeklyInstructionsArray[weekNum-1];

  // Using deconstructing assignment
  // NOTE: The variable names must match those in the template literals above
  var {deadliftPercent, rnWeekDl, rnDefWeek, frontSquatPercent, rnWeekSq} = data;

  // stitch the array of template literals together in a single text node
  var htmlContent = document.createTextNode( instructions.join('<br/>') );

  return htmlContent;

}

希望这个答案足够详细,可以向您展示如何解决该问题。