2012-06-19 6 views
46

Tôi đang làm việc trên ứng dụng web nơi trang chính chứa hai phần: khối không đổi luôn hiển thị và khối thông tin được tạo thành bởi một trong 3 chế độ xem một phần. Mỗi khung nhìn một phần xuất hiện như là kết quả của yêu cầu AJAX và được tải chỉ một lần (sau khi các cửa sổ chuyển đổi đó được cung cấp bởi jquery). Nó hoạt động tốt nhưng tôi đã phải đối mặt với một vấn đề.Tôi có thể đặt JavaScript ở một phần Chế độ xem

Mã html của một phần lượt xem chứa hàm js được sử dụng trong khối không đổi và trong khối thông tin. Khi trang được tải, các chức năng này có thể “nhìn thấy” và hoạt động nhưng chức năng chia sẻ lại không thể tìm thấy các khai báo chức năng và cảnh báo cho tôi về điều này. Tôi không thể giải quyết vấn đề bằng cách chuyển chúng thành tệp js bên ngoài vì cú pháp dao cạo có thể được tìm thấy trong mã của chúng.

Tôi có thể làm gì với điều này?

Cảm ơn.

Cập nhật:

Cuối cùng tôi đã quyết định để giải quyết vấn đề tách mã js của tôi từ quan điểm. Vì vậy, câu hỏi mới là làm thế nào để bao gồm cú pháp dao cạo vào tập tin js hoặc thay thế chấp nhận được là gì. Các giải pháp phổ biến mà tôi đã tìm thấy là sử dụng các biến toàn cầu, thuộc tính dữ liệu và thuộc tính tôi thích hơn - thư viện RazorJS của John Katsiotis.

http://djsolid.net/blog/razorjs---write-razor-inside-your-javascript-files

Tôi hy vọng nó sẽ làm việc ổn định và làm cho Resharper hạnh phúc.

Chúc mừng!

Cập nhật:

Sau 3 năm, tôi nhớ lại câu hỏi này và đã quyết định cập nhật nó theo kinh nghiệm của tôi. Trong thực tế bây giờ tôi không muốn khuyên bạn nên sử dụng thư viện bổ sung cho điều đó. Đặc biệt là nếu bạn không phải là thành viên duy nhất trong nhóm dự án… Sẽ tốt hơn nếu bạn được đảm bảo trong tất cả các thư viện của mình, chúng được hỗ trợ bởi người sáng tạo và cộng đồng và có thể dễ dàng tích hợp vào IDE của bạn (nếu sử dụng cú pháp đặc biệt) . Ngoài ra tất cả các chàng trai trong nhóm của bạn cũng nên biết nó hoạt động như thế nào. Vì vậy, bây giờ tôi sẽ đề nghị làm những việc tiếp theo:

  1. Giữ tất cả JS trong các tệp riêng biệt. Cô lập nó càng nhiều càng tốt. Cung cấp API bên ngoài cho nó.
  2. Gọi hàm API từ Chế độ xem của bạn.
  3. Chuyển tất cả các URL được tạo bằng Razor, tin nhắn văn bản, hằng số dưới dạng tham số tài nguyên.

Ví dụ:

js file:

$.api.someInitFunction = function(resources){ ... } 

Xem:

<script> 
    $.api.someInitFunction({ 
     urls: { myAction: '@Url.Action("MyAction", "MyController")' }, 
     messages: { error: '@errorMessage' }, 
     consts: { myConst: @myIntConst } 
    }); 
</script> 
+0

tôi không thể quyết định những gì câu trả lời là có ích hơn đối với tôi :) – Tomy

+0

Cảm ơn và hoan nghênh để Stackoverflow :) –

+0

Thật vui khi bắt đầu với một buổi tiếp tân tuyệt vời như vậy, cảm ơn rất nhiều! – Tomy

Trả lời

27

Nếu Resharper cảnh báo bạn nó không phải là một vấn đề lớn^_^

Nhưng nếu tôi là bạn tôi sẽ không đưa JavaScript vào chế độ xem một phần ở tất cả.

Vì chế độ xem một phần có thể được chèn vào một trang nhiều lần nên bạn sẽ gặp sự cố với JavaScripts của mình.

Và đối với trường hợp của bạn nếu bạn không thể tách tệp JavaScript thành JS thì chỉ cần tạo một PartialView khác và đặt các tập lệnh này vào nó và chỉ hiển thị nó trong trang chính của bạn.

+0

Cảm ơn, Wahid! Nhưng đôi khi mã Resharper thực sự tốt hơn tôi :) Trong thực tế, tôi biết rằng không nên đặt j vào một phần lượt xem. Nhưng như tôi đã nói, trên trang của tôi họ tồn tại trong một bản sao để làm tổ ví dụ chỉ là "impossibru". Làm theo lời khuyên của bạn về chế độ xem từng phần với các tập lệnh, tôi sẽ làm cho các chế độ xem chính khá tốt. Nhưng điều đáng tiếc là RenderPartial không giải quyết được vấn đề Resharper. Tôi có thể sai không? – Tomy

+3

Nếu đây là một ứng dụng nhỏ và bạn không muốn dành nhiều thời gian hơn cho nó, hãy cứ giữ công việc của bạn. Nhưng nếu bạn đang nói về "thói quen lập trình" thì bạn nên tách JavaScript của mình khỏi Chế độ xem. –

+0

Và đối với '@ Html.ActionLink (...)' có nhiều giải pháp nhưng không phải là giải pháp nào là đặt JavaScript trực tiếp trong PartialView. Bạn có thể xem câu trả lời này http://stackoverflow.com/a/3789959/105445 –

3

Tôi đồng ý với Wahid rằng bạn không nên đặt JavaScript ở chế độ xem một phần hoặc cách khác. Tôi đã nhìn thấy đủ mã mà làm điều này để biết nó chỉ dẫn đến không tốt.

Tôi cũng sẽ nói rằng bạn sẽ có thể chuyển logic được đóng gói trong cú pháp Razor vào JavaScript, bạn chỉ cần chuyển tới JavaScript của bạn thông tin cần thiết bởi logic của bạn.

Tôi chỉ đoán từ kinh nghiệm với nhận xét tiếp theo này nhưng bạn nên thiết kế JavaScript giống như cách bạn sẽ thiết kế cấu trúc mã C# hoặc VB.NET của bạn. Bằng cách đó, logic mà bạn đang sử dụng Razor cho nên là một phần của JavaScript của bạn.

Bằng cách đó, JavaScript của bạn sẽ dễ bảo trì hơn và tôi cho rằng Resharper cũng sẽ vui hơn.

+0

Cảm ơn câu trả lời của bạn! Nhưng vấn đề không phải là logic. Tôi sử dụng Razor để xây dựng các liên kết (ví dụ như Url.Action) và những thứ tương tự. Thông qua chúng như các tham số trông khá lạ tôi đoán. – Tomy

+0

Đối với các liên kết bạn vẫn có thể đặt chúng trên href chỉ cần sử dụng preventDefault. Ngoài ra các thuộc tính dữ liệu html5 cũng hữu ích trong các tình huống này. kiểm tra hoặc dojo hoặc yui3 và xem làm thế nào có thư viện được xây dựng. – eaglestorm

+0

Các tính năng hữu ích, cảm ơn bạn! – Tomy

1

Tôi làm điều này và thấy nó rất thuận tiện. Nó hoạt động tốt để tự động tải các đoạn mã javascript một phần với sự sẵn có của ViewBag, HttpContext, v.v.

Nó mang lại kết quả giống như sử dụng mẫu T4.

Bạn thậm chí có thể nhận được xác thực javascript, intellisense, v.v. nếu bạn thêm các thẻ ma tập lệnh như thế này.

@using System.Configuration 
@if (false) 
{ 
    @:<script type="text/javascript"> 
}  
     $scope.clickCartItem = function(cartItem) { 
      console.log(cartItem); 
      window.location.href [email protected]("('" + ConfigurationManager.AppSettings["baseUrl"] + "/Checkout/' + cartItem.ItemId)"); 
     }; 
     dataAccess.getCart(
     function (response) { 
      //... 
     }, 
     function (response) { 
      //... 
     } 
     ); 

@if (false) 
{ 
    @:</script> 
} 
6

Nếu bạn muốn viết quang cảnh một phần được đóng gói "widget" mà chỉ làm việc khi bạn bao gồm chúng trong một trang, sau đó nhúng một khối kịch bản bên trong xem một phần là một cách sạch để quấn đánh dấu và kịch bản khởi tạo cùng nhau trong một chế độ xem một phần. Ví dụ: tôi có thể có một chế độ xem một phần có tên "_EventList" mà tôi sử dụng trên toàn bộ trang web của mình. Nếu tôi đặt ở hai nơi trên trang chủ của tôi nó chỉ nên làm việc và tôi không muốn phải viết logic trong trang chủ của tôi để khởi tạo các widget.

Nếu bạn sẽ không bao giờ sử dụng nó nhiều lần trong một trang, nó đơn giản. Nhưng nếu bạn có thể, sau đó quấn kịch bản để nó không thực hiện hai lần. Xem bên dưới. Vì lợi ích của các đoạn chồng tràn ngăn xếp, tôi mô phỏng nó bằng cách lặp lại xem một phần hai lần trong đoạn mã để biểu diễn bao gồm một phần xem hai lần trong một trang chính.

trang chủ của tôi có thể trông giống như:

<div id="left-nav"> 
    @Html.Partial("_EventList")   
</div> 

<div id="body"> 
</div> 

<div id="right-nav"> 
    @Html.Partial("_EventList") 
</div> 

Ví dụ:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<!-- Self-contained partial view containing widget --> 
 

 
<div id="widgetDiv" class="panel panel-default"> 
 

 
    <div class="panel-heading">Event Dates</div> 
 
    <div class="panel panel-group"> 
 
     <ul class="widget"> 
 
     <!-- These will load dynamically --> 
 
     </ul> 
 
    </div> 
 

 
    <script> 
 
     $(document).ready(function() { 
 

 
      // Run this once only in case widget is on page more than once 
 
      if(typeof $widget == 'undefined') { 
 
       $widget = $("ul.widget"); // could be more than one 
 
       // mock data to simulate an ajax call 
 
       var data = [ 
 
        {Description: "March", StartDate: "03/01/2015"}, 
 
        {Description: "April", StartDate: "04/01/2015"}, 
 
        {Description: "May", StartDate: "05/01/2015"} 
 
       ]; 
 

 
       $.each($widget, function(w, widget) { 
 
        // might be an $.ajax call 
 
        $.each(data, function(i, row) { 
 
         $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>"); 
 
        }); 
 
       }); 
 
      } 
 
     }); 
 
    </script> 
 
</div> 
 
<!-- End of widget/partial view --> 
 

 

 

 
<!-- Second copy of above for sake of example snippet --> 
 
<!-- No need to read further --> 
 

 

 

 

 

 

 

 

 

 
<!-- Self-contained partial view containing widget --> 
 

 
<div id="widgetDiv" class="panel panel-default"> 
 

 
    <div class="panel-heading">Event Dates</div> 
 
    <div class="panel panel-group"> 
 
     <ul class="tinylist nav nav-sidebar widget"> 
 
     <!-- These will load dynamically --> 
 
     </ul> 
 
    </div> 
 

 
    <script> 
 
     $(document).ready(function() { 
 

 
      // Run this once only in case widget is on page more than once 
 
      if(typeof $widget == 'undefined') { 
 
       $widget = $("ul.widget"); // could be more than one 
 
       // mock data to simulate an ajax call 
 
       var data = [ 
 
        {Description: "March", StartDate: "03/01/2015"}, 
 
        {Description: "April", StartDate: "04/01/2015"}, 
 
        {Description: "May", StartDate: "05/01/2015"} 
 
       ]; 
 

 
       $.each($widget, function(w, widget) { 
 
        // might be an $.ajax call 
 
        $.each(data, function(i, row) { 
 
         $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>"); 
 
        }); 
 
       }); 
 
      } 
 
     }); 
 
    </script> 
 
</div> 
 
<!-- End of widget/partial view -->

+1

Mặc dù thực tế là có nhiều câu trả lời upvoted hơn, tôi chắc chắn khuyên bạn nên aproach này thay vì chia phụ thuộc cao highly gắn kết chỉ vì lợi ích của nhóm chúng bằng phần mở rộng. Vì vậy, có một lớn ++ từ tôi. –

+0

Tôi mạnh mẽ đồng ý: Không chia HTML và JS cố kết. Không có nghi ngờ ... Nhưng ví dụ của bạn xem một phần sẽ không làm việc cho tất cả người tiêu dùng của Visual Studios mẫu của ASP MVC: Bên trong '_Layout.cshtml' jQuery được trả lại * sau *' @RenderBody() 'vì vậy bạn không thể sử dụng nó. Cách giải quyết của bạn không thực sự tốt hơn: Dòng đầu tiên '' sẽ bao gồm jQuery hai lần trở lên thường xuyên (1x cho một phần xem và 1x trong bạn '_Layout.cshtml') – Marcel

+0

@Marcel - ví dụ có nghĩa là hoạt động trong trình chỉnh sửa đoạn mã để hiển thị kỹ thuật. Tôi thực sự cảnh báo về điều đó, bao gồm nhiều jquery bao gồm, trong câu trả lời của tôi và đề xuất cải tiến, vì vậy tôi không chắc chắn nếu bạn đọc "từ chối trách nhiệm" của tôi. Các trang bố trí thực sự của tôi thường có jquery và các tập lệnh khác trong phần đầu. Công việc bổ sung nằm ngoài phạm vi yêu cầu về phạm vi/thời gian của câu trả lời của tôi vào thời điểm đó. Bạn được hoan nghênh cải thiện câu trả lời này miễn là nó vẫn hoạt động trong Stack Overflow – codenheim