我正在使用Node,Express和MongoDB运行网站。我在ajax调用之后生成容器以获取数据以填充它们,并且每个容器都有一个按钮,该按钮使得另一个ajax调用特定于其获取详细信息的配方。第一次我这样做它完美地工作,但如果我得到第二个的细节它执行功能3次而不是一个,如果我为第三个容器执行它运行它9次,依此类推。我对Jquery很新,也许这是对事件如何运作的误解。 saveRecipe函数也会出现问题。
global.js
$(document).ajaxComplete(function(){
$('.details').popover({"trigger": "manual", "html":"true"});
$('.details').click(get_data_for_popover_and_display);
$('.save-favorite').on('click', saveRecipe );
});
(function ($) {
$('#search').on('click', function (e) {
// remove resultset if this has already been run
$('.recipes').empty();
var recipeName = document.getElementById('recipeName').value;
var recipeNameString = '&q=' + recipeName;
var ingredientHtml = '&allowedIngredient[]=';
var ingredientsArray = document.getElementById('ingredients').value.split(",");
var ingredientsString = '';
if (ingredientsArray[0] !== ""){
for (i = 0; i < ingredientsArray.length; i++){
ingredientsArray[i] = ingredientHtml + ingredientsArray[i].trim();
}
for (i = 0; i < ingredientsArray.length; i++){
ingredientsString += ingredientsArray[i];
}
}
var excludedIngredientHtml = '&excludedIngredient[]=';
var excludedIngredientsArray = document.getElementById('ingredientsExclude').value.split(",");
var excludedIngredientsString = '';
if (excludedIngredientsArray[0] !== ""){
for (i = 0; i < excludedIngredientsArray.length; i++){
excludedIngredientsArray[i] = excludedIngredientHtml + excludedIngredientsArray[i].trim();
}
for (i = 0; i < excludedIngredientsArray.length; i++){
excludedIngredientsString += excludedIngredientsArray[i];
}
}
var dietHtml = '';
if(document.getElementById('lacto-veg').checked){
dietHtml += '&allowedDiet[]=388^Lacto vegetarian';
}
if(document.getElementById('ovo-veg').checked){
dietHtml += '&allowedDiet[]=389^Ovo vegetarian';
}
if(document.getElementById('paleo').checked){
dietHtml += '&allowedDiet[]=403^Paleo';
}
if(document.getElementById('pescetarian').checked){
dietHtml += '&allowedDiet[]=390^Pescetarian';
}
if(document.getElementById('vegan').checked){
dietHtml += '&allowedDiet[]=386^vegan';
}
if(document.getElementById('vegetarian').checked){
dietHtml += '&allowedDiet[]=387^Lacto-ovo vegetarian';
}
var allergyHtml = '';
if(document.getElementById('dairy-free').checked){
allergyHtml += '&allowedAllergy[]=396^Dairy-Free';
}
if(document.getElementById('egg-free').checked){
allergyHtml += '&allowedAllergy[]=397^Egg-Free';
}
if(document.getElementById('gluten-free').checked){
allergyHtml += '&allowedAllergy[]=393^gluten-Free';
}
if(document.getElementById('peanut-free').checked){
allergyHtml += '&allowedAllergy[]=394^Peanut-Free';
}
if(document.getElementById('seafood-free').checked){
allergyHtml += '&allowedAllergy[]=398^Seafood-Free';
}
if(document.getElementById('seseme-free').checked){
allergyHtml += '&allowedAllergy[]=399^Seseme-Free';
}
if(document.getElementById('sulfite-free').checked){
allergyHtml += '&allowedAllergy[]=401^Sulfite-Free';
}
if(document.getElementById('tree-nut-free').checked){
allergyHtml += '&allowedAllergy[]=395^Tree Nut-Free';
}
if(document.getElementById('wheat-free').checked){
allergyHtml += '&allowedAllergy[]=392^Wheat-Free';
}
var apiHtml = 'http://api.yummly.com/v1/api/recipes?_app_id=&_app_key=' +recipeNameString;
if (ingredientsString){
apiHtml += ingredientsString;
}
if (excludedIngredientsString){
apiHtml += excludedIngredientsString;
}
if (dietHtml){
apiHtml += dietHtml;
}
if (allergyHtml){
apiHtml += allergyHtml;
}
apiHtml += '&requirePictures=true';
apiHtml = apiHtml.replace(' ', '%20');
$.getJSON(apiHtml, function (json) {
var recipes = [],
$recipes;
$.each(json, function (key, val) {
if (key === "matches"){
for (i = 0; i < val.length ; i++) {
if (i%3 === 0){
recipes.push('<div class="row">');
}
recipes.push('<div class="col-sm-6 col-md-4">');
recipes.push('<div class="thumbnail">' + '<img src="'+ val[i].imageUrlsBySize[90] + '" alt="' + val[i].recipeName + '" data-holder-rendered="true" style="height: 300px; width: 100%; display: block;"/>');
recipes.push('<div class="caption">' + '<h3 class="caption-text">' + val[i].recipeName + '</h3>');
recipes.push('<p class="caption-text">' + val[i].sourceDisplayName + '</p>');
recipes.push('<p><button type="button" class="btn btn-primary details" data-toggle="popover" title="' + val[i].recipeName + '" value="' + val[i].id + '"> Details </button> ');
recipes.push('<button type="button" class="btn btn-primary save-favorite" method="post" action="saveFavorite" value="' + val[i].id + '"> Favorite </button></p>');
recipes.push('</div></div></div>');
if ((i+1)%3 === 0){
recipes.push('</div>');
}
}
}
});
if (recipes.length < 1) {
recipes.push('<p>No results for parameters, try again!</p>');
}
$recipes = $('<div />').appendTo('.recipes');
$recipes.append(recipes.join(''));
});
e.preventDefault();
});
}(jQuery));
get_data_for_popover_and_display = function() {
var el = $(this);
if(el.hasClass('recipe-loaded')){
}
else {
var _data = $(this).attr('alt');
var recipeUrl = 'http://api.yummly.com/v1/api/recipe/' + this.value + '?_app_id=&_app_key=';
var recipeHtml = '';
var ingredientsHtml = '';
var nutritionHtml = '';
var ratingHtml = '';
var servingsHtml = '';
var sourceHtml = '';
$.getJSON(recipeUrl, function (json) {
$.each(json, function (key, val) {
if (key === "ingredientLines"){
ingredientsHtml = '<h4>Ingredients:</h4><ul>';
for (i = 0; i < val.length ; i++){
ingredientsHtml += ('<li>' + val[i] + '</li>');
}
ingredientsHtml += '</ul>';
}
if (key === "nutritionEstimates"){
if(val.length > 0){
nutritionHtml = 'Cal. per Serving: ' + val[0].value + '<br>';
}
}
if (key === "rating"){
ratingHtml += 'Rating: ' + val + '</p>';
}
if (key === "numberOfServings"){
servingsHtml += '<p>Servings: ' + val + '<br>';
}
if (key === "source"){
sourceHtml += '<p><a type="button" class="btn btn-primary details" href="'+ val.sourceRecipeUrl +'" >Source</a>';
}
})
recipeHtml += ingredientsHtml;
recipeHtml += servingsHtml;
recipeHtml += nutritionHtml;
recipeHtml += ratingHtml;
recipeHtml += sourceHtml;
el.attr('data-content', recipeHtml).success(el.popover('toggle'));
el.addClass('recipe-loaded');
});
}
};
function saveRecipe(){
var recipeUrl = 'http://api.yummly.com/v1/api/recipe/' + this.value + '?_app_id=3e5b7dbe&_app_key=1d681685a57dac07e6df0b1c0df38de6';
var json = $.getJSON(recipeUrl, function (data){
console.log(JSON.stringify(data));
$.ajax({
type: 'POST',
data: data,
url: '/saverecipe',
dataType: 'JSON'
});
});
};
答案 0 :(得分:0)
这一行:
$('.details').click(get_data_for_popover_and_display);
在将调用.detail
的所有get_data_for_popover_and_display
元素上连接一个新事件处理程序,即使该元素已经有一个事件处理程序调用get_data_for_popover_and_display
。与:相同:
$('.save-favorite').on('click', saveRecipe );
因为get_data_for_popover_and_display
(至少)执行另一个ajax调用,它会添加另一个处理程序,随着时间的推移,你会得到越来越多的处理程序。
它完全是这样的:
function clickHandler() {
console.log(+new Date(), "Clicked");
clickComplete();
}
function clickComplete() {
$("#btn").on("click", clickHandler);
}
clickComplete();
&#13;
<input type="button" id="btn" value="Click Me">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
所以:如果你还没有这样做,只能添加一个处理程序。也许在jQuery&#39; data
商店中跟踪:
function clickHandler() {
console.log(+new Date(), "Clicked");
clickComplete();
}
function clickComplete() {
$("#btn").filter(function() {
return !$(this).data("hasClick");
})
.on("click", clickHandler)
.data("hasClick", true);
}
clickComplete();
&#13;
<input type="button" id="btn" value="Click Me">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;