2014-01-15 25 views
-1

这个问题很简单,但也有点理论。JQuery:如何重构JQuery与界面的交互?

让我们假设你有一个长的JQuery脚本,它修改和动画化网站的图形。目标是处理用户界面。用户界面必须具有响应能力,因此对这个JQuery的真正需求是将一些可视化状态(体育列表可见/不可见)与一些需求相结合,这是由于响应式用户界面。

从MVC/AngularJS的角度思考。程序员应该如何处理? 如何重构JS/JQuery代码来实现MVC/AngularJS描述的问题的分离?

我提供了一个JQuery代码的例子来讲一些具体的东西。

$.noConflict(); 
jQuery(document).ready(function ($) { 
    /*variables*/ 
    var sliderMenuVisible = false; 

    /*dom object variables*/ 
    var $document = $(document); 
    var $window = $(window); 
    var $pageHost = $(".page-host"); 
    var $sportsList = $("#sports-list"); 
    var $mainBody = $("#mainBody"); 
    var $toTopButtonContainer = $('#to-top-button-container'); 

    /*eventHandlers*/ 

    var displayError = function (form, error) { 
     $("#error").html(error).removeClass("hidden"); 
    }; 
    var calculatePageLayout = function() { 
     $pageHost.height($(window).height()); 
     if ($window.width() > 697) { 
      $sportsList.removeAttr("style"); 
      $mainBody 
       .removeAttr("style") 
       .unbind('touchmove') 
       .removeClass('stop-scroll'); 
      if ($(".betslip-access-button")[0]) { 
       $(".betslip-access-button").fadeIn(500); 
      } 
      sliderMenuVisible = false; 
     } else { 
      $(".betslip-access-button").fadeOut(500); 
     } 
    }; 
    var formSubmitHandler = function (e) { 
     var $form = $(this); 

     // We check if jQuery.validator exists on the form 
     if (!$form.valid || $form.valid()) { 
      $.post($form.attr("action"), $form.serializeArray()) 
       .done(function (json) { 
        json = json || {}; 

        // In case of success, we redirect to the provided URL or the same page. 
        if (json.success) { 
         window.location = json.redirect || location.href; 
        } else if (json.error) { 
         displayError($form, json.error); 
        } 
       }) 
       .error(function() { 
        displayError($form, "Login service not available, please try again later."); 
       }); 
     } 

     // Prevent the normal behavior since we opened the dialog 
     e.preventDefault(); 
    }; 

    //preliminary functions// 
    $window.on("load", calculatePageLayout); 
    $window.on("resize", calculatePageLayout); 

    //$(document).on("click","a",function (event) { 
    // event.preventDefault(); 
    // window.location = $(this).attr("href"); 
    //}); 

    /*evet listeners*/ 

    $("#login-form").submit(formSubmitHandler); 

    $("section.navigation").on("shown hidden", ".collapse", function (e) { 
     var $icon = $(this).parent().children("button").children("i").first(); 
     if (!$icon.hasClass("icon-spin")) { 
      if (e.type === "shown") { 
       $icon.removeClass("icon-caret-right").addClass("icon-caret-down"); 
      } else { 
       $icon.removeClass("icon-caret-down").addClass("icon-caret-right"); 
      } 
     } 
     toggleBackToTopButton(); 
     e.stopPropagation(); 
    }); 

    $(".collapse[data-src]").on("show", function() { 
     var $this = $(this); 
     if (!$this.data("loaded")) { 
      var $icon = $this.parent().children("button").children("i").first(); 
      $icon.removeClass("icon-caret-right icon-caret-down").addClass("icon-refresh icon-spin"); 
      console.log("added class - " + $icon.parent().html()); 
      $this.load($this.data("src"), function() { 
       $this.data("loaded", true); 
       $icon.removeClass("icon-refresh icon-spin icon-caret-right").addClass("icon-caret-down"); 
       console.log("removed class - " + $icon.parent().html()); 
      }); 
     } 
     toggleBackToTopButton(); 
    }); 

    $("#sports-list-button").on("click", function (e) 
    { 
     if (!sliderMenuVisible) 
     { 
      $sportsList.animate({ left: "0" }, 500); 
      $mainBody.animate({ left: "85%" }, 500) 
       .bind('touchmove', function (e2) { e2.preventDefault(); }) 
       .addClass('stop-scroll'); 
      $(".betslip-access-button").fadeOut(500); 
      sliderMenuVisible = true; 
     } 
     else 
     { 
      $sportsList.animate({ left: "-85%" }, 500).removeAttr("style"); 
      $mainBody.animate({ left: "0" }, 500).removeAttr("style") 
       .unbind('touchmove').removeClass('stop-scroll'); 
      $(".betslip-access-button").fadeIn(500); 
      sliderMenuVisible = false; 
     } 
     e.preventDefault(); 
    }); 

    $mainBody.on("click", function (e) { 
     if (sliderMenuVisible) { 
      $sportsList.animate({ left: "-85%" }, 500).removeAttr("style"); 
      $mainBody.animate({ left: "0" }, 500) 
       .removeAttr("style") 
       .unbind('touchmove') 
       .removeClass('stop-scroll'); 
      $(".betslip-access-button").fadeIn(500); 
      sliderMenuVisible = false; 
      e.stopPropagation(); 
      e.preventDefault(); 
     } 
    }); 

    $document.on("click", "div.event-info", function() { 
     if (!sliderMenuVisible) { 
      var url = $(this).data("url"); 
      if (url) { 
       window.location = url; 
      } 
     } 
    }); 

    function whatDecimalSeparator() { 
     var n = 1.1; 
     n = n.toLocaleString().substring(1, 2); 
     return n; 
    } 

    function getValue(textBox) { 
     var value = textBox.val(); 
     var separator = whatDecimalSeparator(); 
     var old = separator == "," ? "." : ","; 
     var converted = parseFloat(value.replace(old, separator)); 
     return converted; 
    } 

    $(document).on("click", "a.selection", function (e) { 
     if (sliderMenuVisible) { 
      return; 
     } 
     var $this = $(this); 
     var isLive = $this.data("live"); 
     var url = "/" + _language + "/BetSlip/Add/" + $this.data("selection") + "?odds=" + $this.data("odds") + "&live=" + isLive; 
     var urlHoveringBtn = "/" + _language + '/BetSlip/AddHoveringButton/' + $this.data("selection") + "?odds=" + $this.data("odds") + "&live=" + isLive; 

     $.ajax(urlHoveringBtn).done(function (dataBtn) { 
      if ($(".betslip-access-button").length == 0 && dataBtn.length > 0) { 
       $("body").append(dataBtn); 
      } 
     }); 

     $.ajax(url).done(function (data) { 
      if ($(".betslip-access").length == 0 && data.length > 0) { 
       $(".navbar").append(data); 
       $pageHost.addClass("betslipLinkInHeader"); 
       var placeBetText = $("#live-betslip-popup").data("placebettext"); 
       var continueText = $("#live-betslip-popup").data("continuetext"); 
       var useQuickBetLive = $("#live-betslip-popup").data("usequickbetlive").toLowerCase() == "true"; 
       var useQuickBetPrematch = $("#live-betslip-popup").data("usequickbetprematch").toLowerCase() == "true"; 
       if ((isLive && useQuickBetLive) || (!isLive && useQuickBetPrematch)) { 
        var dialog = $("#live-betslip-popup").dialog({ 
         modal: true, 
         dialogClass: "fixed-dialog" 
        }); 
        dialog.dialog("option", "buttons", [ 
         { 
          text: placeBetText, 
          click: function() { 
           var placeBetUrl = "/" + _language + "/BetSlip/QuickBet?amount=" + getValue($("#live-betslip-popup-amount")) + "&live=" + $this.data("live"); 
           window.location = placeBetUrl; 
          } 
         }, 
         { 
          text: continueText, 
          click: function() { 
           dialog.dialog("close"); 
          } 
         } 
        ]); 
       } 
      } 
      if (data.length > 0) { 
       $this.addClass("in-betslip"); 
      } 
     }); 
     e.preventDefault(); 
    }); 

    $(document).on("click", "a.selection.in-betslip", function (e) { 
     if (sliderMenuVisible) { 
      return; 
     } 
     var $this = $(this); 
     var isLive = $this.data("live"); 
     var url = "/" + _language + "/BetSlip/RemoveAjax/" + $this.data("selection") + "?odds=" + $this.data("odds") + "&live=" + isLive; 

     $.ajax(url).done(function (data) { 
      if (data.success) { 
       $this.removeClass("in-betslip"); 

       if (data.selections == 0) { 
        $(".betslip-access").remove(); 
        $(".betslip-access-button").remove(); 
        $(".page-host").removeClass("betslipLinkInHeader"); 

       } 
      } 
     }); 
     e.preventDefault(); 
    }); 

    $("section.betslip .total-stake button.live-betslip-popup-plusminus").click(function (e) { 
     if (sliderMenuVisible) { 
      return; 
     } 
     e.preventDefault(); 
     var action = $(this).data("action"); 
     var amount = parseFloat($(this).data("amount")); 
     if (!isNumeric(amount)) amount = 1; 

     var totalStake = $("#live-betslip-popup-amount").val(); 
     if (isNumeric(totalStake)) { 
      totalStake = parseFloat(totalStake); 
     } else { 
      totalStake = 0; 
     } 
     if (action == "decrease") { 
      if (totalStake < 1.21) { 
       totalStake = 1.21; 
      } 
      totalStake -= amount; 
     } else if (action == "increase") { 
      totalStake += amount; 
     } 
     $("#live-betslip-popup-amount").val(totalStake); 
    }); 

    toggleBackToTopButton(); 

    function toggleBackToTopButton() { 
     isScrollable() ? $toTopButtonContainer.show() : $toTopButtonContainer.hide(); 
    } 

    $("#to-top-button").on("click", function() { $("#mainBody").animate({ scrollTop: 0 }); }); 

    function isScrollable() { 
     return $("section.navigation").height() > $(window).height() + 93; 
    } 


    var isNumeric = function (string) { 
     return !isNaN(string) && isFinite(string) && string != ""; 
    }; 

    function enableQuickBet() { 

    } 

}); 
+0

你是说你的代码”已经显示的作品,但你想知道是否有一种方法来重构它,使其“更好”(“更好”的意思是“MVC”)? – nnnnnn

+0

德黑德代码已经工作。我在问如何在MVC/Angular JS范例中重构它。我会修改这个问题来更好地解释这个概念。 – Revious

+0

如果这只是UI,为什么你会考虑MVC? –

回答

1

我在这种情况下,步骤是:

  • 所有写入(至少)一个控制器
  • 首先替换NG-指令所有事件处理(NG-点击最重要的)
  • 用ng-style和ng-class将视图状态从控制器中取出。在大多数情况下,ng-show和ng-hide将被满足
  • 如果有代码将被多次使用,请考虑编写一个指令。有没有待办事项与视图状态
  • 和代码 - 将代码放在一个服务
  • 编写单元测试(我想没有一个到现在为止:))