2012-11-27 19 views
6

Đây là câu hỏi hơi khó đối với người có kinh nghiệm phát triển web vài năm, nhưng sau khi không tìm thấy câu trả lời trên Ngăn xếp lập trình Stack hoặc Google, tôi đã quyết định hỏi tại đây.Làm cách nào để tách javascript nội tuyến khỏi nội dung được tạo động trong Express/Node.js?

Tôi đang sử dụng tốc khuôn khổ web cho Node.js, nhưng câu hỏi này là không cụ thể cho bất kỳ khuôn khổ web hoặc ngôn ngữ lập trình.

Dưới đây là danh sách các trò chơi được truy vấn từ cơ sở dữ liệu. Mỗi thực thể trò chơi là một dòng của bảng duy nhất, được tạo ra bằng cách sử dụng cho vòng:

table.table 
     tbody 
     for game in games 
      tr 
      td.span2 
       img.img-polaroid(src='/img/games/#{game.largeImage}') 
       // continues further 

enter image description here

Mỗi Đánh giá khối, cũng như mỗi Mua nút/hộp thoại modal được tạo ra bởi for-loop với id phù hợp với trò chơi. Ví dụ: nút Mua cho tín ngưỡng của Assassin sẽ có id = "price-assassins-creed". # {variable} - là cách bạn tham chiếu biến trong Jade, được truyền từ máy chủ.

button.btn.btn-primary.btn-mini(id='price-#{game.slug}', href='#buyModal', role='button', data-toggle='modal') 

.modal.hide.fade(id='modal-#{game.slug}', tabindex='-1', role='dialog', aria-labelledby='myModalLabel', aria-hidden='true') 
      .modal-header 
       span.lead Game Checkout 
       img.pull-right(src='/img/new_visa_medium.gif') 
      .modal-body 
       label 
       i.icon-user 
       | Name on Card 
       input.input-medium(type='text') 
       label 
       i.icon-barcode 
       | Card Number 
       input.input-medium(type='text', placeholder='•••• •••• •••• ••••', maxlength=16) 

       label 
       i.icon-time 
       | Expiration Date 
       input.input-mini(type='text', placeholder='MMYY', maxlength=4) 
       label 
       i.icon-qrcode 
       | Card Code 
       input.input-mini(type='text', placeholder='CVC', maxlength=4) 
      .modal-footer 
       button.btn(data-dismiss='modal', aria-hidden='true') Cancel 
       button.btn.btn-primary(id='#{game.slug}') Buy 

script(type='text/javascript') 
    $('#_#{game.slug}').raty({ 
    path: '/img', 
    round : { down: .25, full: .6, up: .76 }, 
    score: #{game.rating}/#{game.votes}, 
    readOnly: true 
    }); 

Multiply rằng bằng số lượng trò chơi và đó là bao nhiêu kịch bản inline Tôi có trên một trang.

chưa

Tệ hơn nữa, tôi phải giải thích cho các trường hợp sau:

  • tài khoản không đăng nhập: hiển thị ở trên kịch bản giá trong chế độ read-only.
  • của người sử dụng đăng nhập, nhưng vẫn chưa bình chọn chưa:

... trong trường hợp đó, sử dụng kịch bản sau đây:

script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
         path: '/img', 
         round : { down: .25, full: .6, up: .76 }, 
         score: #{game.rating}/#{game.votes}, 
         readOnly: false, 
         click: function (score, event) { 
         var self = this; 
         $.meow({ 
          message: 'Thanks for voting. Your rating has been recorded.', 
          icon: 'http://png-3.findicons.com/files/icons/1577/danish_royalty_free/32/smiley.png' 
         }); 
         $.ajax({ 
          type: 'POST', 
          url: '/games/rating', 
          data: { 
          slug: $(self).attr('id').slice(1), 
          rating: score 
          }, 
          success: function() { 
          console.log('setting to read-only'); 
          $(self).raty('readOnly', true); 
          } 
         }); 
         } 
        }); 
  • của người sử dụng đăng nhập nhưng bị tạm ngưng xếp hạng: Sao chép và dán một tập lệnh chỉ đọc khác cho điều kiện cụ thể này là nếu-else.

câu chuyện dài ngắn, nó đã trở thành một cơn ác mộng bảo trì cố gắng để duy trì hoạt Javascript tất cả điều này trong .jade mẫu tác phẩm của tôi, và đánh dấu của tôi trông không thể chấp nhận bẩn.

Giải pháp cho việc này là gì? Điều này có vẻ giống như một kịch bản phổ biến cho các ứng dụng CRUD. Lý tưởng nhất là tôi muốn chuyển tất cả javascript sang một số riêng biệt .js tệp. Nhưng nếu tôi có thể loại bỏ một số mã trùng lặp, đó sẽ là tuyệt vời quá.

Vấn đề là nếu tôi di chuyển javascript nội tuyến sang một tệp riêng biệt làm cách nào để biết tôi đang xếp hạng trò chơi nào? Làm cách nào để biết nút Mua có người dùng đã nhấp vào?

Ngay bây giờ không có sự mơ hồ bởi vì đối với N trò chơi tôi đã mua N nút, N hộp thoại modal và N kịch bản đánh giá. Bất kể những gì ai nghĩ về phong cách lập trình này, đó là một cách khủng khiếp để duy trì mã.

Vui lòng chia sẻ một số thông tin chi tiết với một noobie!

Cảm ơn bạn trước.

Dưới đây là một đoạn mã hoàn chỉnh các tập tin games.jade tôi:

extends layout 

block content 
    br 
    ul.nav.nav-pills 
    if heading === 'Top 25' 
     li.active 
     a(href='/games') Top 25 
    else 
     li 
     a(href='/games') Top 25 

    if heading === 'Action' 
     li.active 
     a(href='/games/genre/action') Action 
    else 
     li 
     a(href='/games/genre/action') Action 

    if heading === 'Adventure' 
     li.active 
     a(href='/games/genre/adventure') Adventure 
    else 
     li 
     a(href='/games/genre/adventure') Adventure 

    if heading === 'Driving' 
     li.active 
     a(href='/games/genre/driving') Driving 
    else 
     li 
     a(href='/games/genre/driving') Driving 

    if heading === 'Puzzle' 
     li.active 
     a(href='/games/genre/puzzle') Puzzle 
    else 
     li 
     a(href='/games/genre/puzzle') Puzzle 

    if heading === 'Role-Playing' 
     li.active 
     a(href='/games/genre/role-playing') Role-Playing 
    else 
     li 
     a(href='/games/genre/role-playing') Role-Playing 

    if heading === 'Simulation' 
     li.active 
     a(href='/games/genre/simulation') Simulation 
    else 
     li 
     a(href='/games/genre/simulation') Simulation 

    if heading === 'Strategy' 
     li.active 
     a(href='/games/genre/strategy') Strategy 
    else 
     li 
     a(href='/games/genre/strategy') Strategy 

    if heading === 'Sports' 
     li.active 
     a(href='/games/genre/sports') Sports 
    else 
     li 
     a(href='/games/genre/sports') Sports 


    if games.length == 0 
    .alert.alert-warning 
     | Database query returned no results. 
    else 
    table.table 
     tbody 
     for game in games 
      .modal.hide.fade(id='modal-#{game.slug}', tabindex='-1', role='dialog', aria-labelledby='myModalLabel', aria-hidden='true') 
      .modal-header 
       span.lead Game Checkout 
       img.pull-right(src='/img/new_visa_medium.gif') 
      .modal-body 
       label 
       i.icon-user 
       | Name on Card 
       input.input-medium(type='text') 
       label 
       i.icon-barcode 
       | Card Number 
       input.input-medium(type='text', placeholder='•••• •••• •••• ••••', maxlength=16) 

       label 
       i.icon-time 
       | Expiration Date 
       input.input-mini(type='text', placeholder='MMYY', maxlength=4) 
       label 
       i.icon-qrcode 
       | Card Code 
       input.input-mini(type='text', placeholder='CVC', maxlength=4) 
      .modal-footer 
       button.btn(data-dismiss='modal', aria-hidden='true') Cancel 
       button.btn.btn-primary(id='#{game.slug}') Buy 
      tr 
      td.span2 
       img.img-polaroid(src='/img/games/#{game.largeImage}') 
      td 
       a(href='/games/#{game.slug}') 
       strong 
        = game.title 
       |   

       if user.userName 
       button.btn.btn-primary.btn-mini(id='price-#{game.slug}', href='#modal-#{game.slug}', role='button', data-toggle='modal') 
        i.icon-shopping-cart.icon-white 
        = game.price 
       if user.purchasedGames && user.purchasedGames.length > 0 
        for mygame in user.purchasedGames 
        if mygame.game.slug == game.slug 
         script(type='text/javascript') 
         $('#price-#{game.slug}').removeAttr('href'); 
         $('#price-#{game.slug}').html('<i class="icon-shopping-cart icon-white"></i> Purchased'); 

       div 
       span(id='_' + game.slug) 
       span(id='votes', name='votes') 
       | (#{game.votes} votes) 
       div 
       small.muted 
        div #{game.releaseDate} | #{game.publisher} 
        div #{game.genre} 
       p 
       =game.description 

      // logged-in users 
      if user.userName 
      if game.votedPeople.length > 0 
       for voter in game.votedPeople 
       if voter == user.userName || user.suspendedRating 
        script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
         path: '/img', 
         round : { down: .25, full: .6, up: .76 }, 
         score: #{game.rating}/#{game.votes}, 
         readOnly: true 
        }); 
       else 
        script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
         path: '/img', 
         round : { down: .25, full: .6, up: .76 }, 
         score: #{game.rating}/#{game.votes}, 
         readOnly: false, 
         click: function (score, event) { 
         var self = this; 
         $.meow({ 
          message: 'Thanks for voting. Your rating has been recorded.', 
          icon: 'http://png-3.findicons.com/files/icons/1577/danish_royalty_free/32/smiley.png' 
         }); 
         $.ajax({ 
          type: 'POST', 
          url: '/games/rating', 
          data: { 
          slug: $(self).attr('id').slice(1), 
          rating: score 
          }, 
          success: function() { 
          console.log('setting to read-only'); 
          $(self).raty('readOnly', true); 
          } 
         }); 
         } 
        }); 
      else 
       if (user.suspendedRating) 
       script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
        path: '/img', 
        round : { down: .25, full: .6, up: .76 }, 
        score: #{game.rating}/#{game.votes}, 
        readOnly: true 
        }); 
       else 
       script(type='text/javascript') 
        $('#_#{game.slug}').raty({ 
         path: '/img/', 
         round : { down: .25, full: .6, up: .76 }, 
         score: #{game.rating}/#{game.votes}, 
         readOnly: false, 
         click: function (score, event) { 
          var self = this; 
          $.meow({ 
          message: 'Thanks for voting. Your rating has been recorded.', 
          icon: 'http://png-3.findicons.com/files/icons/1577/danish_royalty_free/32/smiley.png' 
          }); 
          $.ajax({ 
          type: 'POST', 
          url: '/games/rating', 
          data: { 
           slug: $(self).attr('id').slice(1), 
           rating: score 
          }, 
          success: function() { 
           console.log('setting to read-only'); 
           $(self).raty('readOnly', true); 
          } 
          }); 
         } 
         }); 
      else 
      script(type='text/javascript') 
       $('#_#{game.slug}').raty({ 
       path: '/img', 
       round : { down: .25, full: .6, up: .76 }, 
       score: #{game.rating}/#{game.votes}, 
       readOnly: true 
       }); 

      script(type='text/javascript') 
      $('##{game.slug}').click(function() { 
       var game = this; 
       $.ajax({ 
       type: 'post', 
       url: '/buy', 
       data: { 
        slug: $(game).attr('id') 
       } 
       }).success(function() { 
       $('#price-#{game.slug}').attr('disabled', 'true'); 
       $('#modal-' + $(game).attr('id')).modal('hide'); 
       humane.log('Your order has been submitted!'); 
       }); 
      }); 
+3

Tường thành văn bản lớn nhưng là một câu hỏi hay. +1 – Ben

Trả lời

3

Đó là cách quá dài để đọc. Dù sao, tôi nghĩ rằng tôi nhận được các ý chính về những gì bạn đang nói và sẽ sử dụng một định dạng như thế này:

<div id="some_container"> 
    <!-- The following div would be generated in each iteration of the for loop you speak of --> 
    <div class="item-container" data-game-name="Your game name" data-game-id="23"> 
     <span class="button delete-button">X</span> 
    </div> 
</div> 

Và kịch bản của bạn sẽ là một cái gì đó với đoàn (để giảm thiểu số lượng các ràng buộc rất nhiều):

$(document).ready(function() { 
    $("#some_container").on("click", ".delete-button", function() { 
     var $this = $(this); 
     var $container = $this.closest(".item-container"); 
     var game_name = $container.data("game-name"); 
     var game_id = $container.data("game-id"); 
     // Do whatever with the above 2 variables 
    }); 
}); 

Đối với nội dung phương thức, bạn có thể tạo <div> có "mẫu" cho nội dung hiển thị cho mọi thứ. Sau đó, khi bạn nhấp vào nút bất kỳ, bạn sử dụng logic như trên (lấy phụ huynh đầu tiên .item-container để lấy chi tiết về mặt hàng, họ điền vào "mẫu" theo phương thức với thông tin này. Sau đó, cách đó, "OK" nút không cần một triệu thứ được mã hóa cứng - chỉ cần một - lấy thông tin từ mẫu đó và thực hiện bất kỳ cuộc gọi nào hoặc gửi biểu mẫu.

+1

Cảm ơn, tôi đã kết thúc bằng cách sử dụng Mặc dù tôi không thể đặt quá nhiều thông tin, giống như tất cả tên người dùng đã bỏ phiếu cho một trò chơi cụ thể (mối quan tâm về quyền riêng tư), vì vậy tôi sẽ làm một số logic trong mẫu của tôi dẫn đến một biến boolean True/False sẽ được chuyển đến phía máy khách bên trong thuộc tính data- *. –