asp.net-mvc: ký hiệu dao cạo '@' trong tệp js


90

Tôi có .csHtmltệp -razor với hàm javascript sử dụng hàm @Url.ContentC # bên trong cho URL ajax.
Tôi muốn chuyển chức năng đó sang .jstệp được tham chiếu từ chế độ xem của tôi.

Vấn đề là javascript không "biết" @ký hiệu và không phân tích cú pháp mã C #.
Có cách nào để tham chiếu .jstệp từ chế độ xem có ký hiệu "@" không?


2
Có lẽ điều này giúp (xem câu trả lời) stackoverflow.com/questions/7892793/ajax-succes-function
Andriy Khrystyanovich

Câu trả lời:


87

Bạn có thể sử dụng các data-*thuộc tính HTML5 . Giả sử rằng bạn muốn thực hiện một số hành động khi một số phần tử DOM như div được nhấp vào. Vì thế:

<div id="foo" data-url="@Url.Content("~/foobar")">Click me</div>

và sau đó trong tệp javascript riêng biệt của bạn, bạn có thể làm việc một cách không phô trương với DOM:

$('#foo').click(function() {
    var url = $(this).data('url');
    // do something with this url
});

Bằng cách này, bạn có thể tách biệt rõ ràng giữa đánh dấu và tập lệnh mà không cần bất kỳ thẻ phía máy chủ nào trong các tệp javascript của mình.


Cảm ơn. Tôi nghĩ rằng đối với nhiều giá trị có thể là một vấn đề đau đầu. Đầu tiên, tôi nghĩ nó có thể giải quyết vấn đề của mình nhưng sau khi thử, tôi đã tìm thấy rất nhiều giới thiệu trong mã của mình và quyết định tìm một cách khác.
QMaster

19

Tôi vừa tìm thấy một công cụ dao cạo trên nuget làm được điều đó! Có nghĩa là giải quyết @cú pháp!
Nó tên là RazorJS .

Các NuGet gói


Cập nhật năm 2016:
Gói này đã không được cập nhật trong 5 năm và liên kết trang web của dự án đã chết. Tôi không khuyên mọi người sử dụng thư viện này nữa.


Bạn có thể nhìn vào điều này? stackoverflow.com/questions/27702322/…
iamCR

Liên kết đầu tiên bị phá vỡ
Memet Olsen

@MemetOlsen, quả thật vậy, xin lỗi nhưng tôi không thể tìm thấy một bản sao của nó, vì vậy tôi đã xóa nó :(
gdoron đang hỗ trợ Monica

@gdoron, không sao. Tôi chỉ muốn cho bạn biết về liên kết chết. Như bạn đã nói, gói này đã không được cập nhật trong 5 năm nên có lẽ bạn vẫn nên sử dụng nó.
Memet Olsen

10

Một cách để giải quyết vấn đề là:

Thêm chế độ xem một phần bằng các hàm javascript vào chế độ xem.
Bằng cách này, bạn có thể sử dụng @biểu tượng và tất cả các javascriptchức năng của bạn được tách biệt khỏi dạng xem.


9

Bạn có hai lựa chọn:

  • Sử dụng giá trị làm tham số trong hàm và kết nối trong chế độ xem
  • Tạo một không gian tên (thay vì biến mức công khai được coi là hoạt động không tốt trong JS) và đặt giá trị này ở đầu trang rồi sử dụng nó trong js của bạn

Ví dụ:

 var MyCompany = 
 {
   MyProject: {
                  MyVariable:""
               }
  };

Và sau đó theo quan điểm của bạn, hãy đặt nó:

MyCompany.MyProject.MyVariable = @....

CẬP NHẬT

Bạn có thể tự hỏi không có gì là tốt vì ghép nối, tốt là đúng, bạn đang ghép nối js và xem. Đó là lý do tại sao các tập lệnh phải không biết vị trí mà chúng đang chạy, vì vậy đó là một triệu chứng của việc tổ chức các tệp không tối ưu.

Dù sao cũng có tùy chọn thứ ba để tạo công cụ xem và chạy các tệp js trên dao cạo và gửi kết quả trở lại. Điều này là sạch hơn nhưng chậm hơn nhiều nên cũng không được khuyến khích.


1
+1 Tôi thực hiện phương pháp đầu tiên. Gọi một hàm khởi tạo từ chế độ xem của bạn, truyền vào tất cả dữ liệu bạn yêu cầu.
Richard Dalton

Cảm ơn, cách tiếp cận thứ hai không phải là một kết hợp tồi giữa chế độ xem và tệp js? Bạn có cách nào tốt hơn không?
gdoron đang hỗ trợ Monica

Cả hai đều được ghép nối. Không có cách nào để tách trừ khi bạn viết công cụ xem để xử lý tệp js trước khi hiển thị. Xem cập nhật của tôi.
Aliostad

những gì về cách này mà tôi đã đề xuất? stackoverflow.com/questions/7902213/...
gdoron đang hỗ trợ Monica

Có vẻ ổn. +1 của tôi. Xem một phần hoặc toàn bộ, không thay đổi bất cứ điều gì. Đó là tất cả các chế độ xem khớp nối với js.
Aliostad

7

Để đưa @biến vào tệp .js của bạn, bạn sẽ phải sử dụng một biến toàn cục và đặt giá trị của biến đó từ chế độ xem mvc đang sử dụng tệp .js đó.

Tệp JavaScript:

var myValue;

function myFunc() {
  alert(myValue);
}

MVC Xem tệp:

<script language="text/javascript">
    myValue = @myValueFromModel;
</script>

Chỉ cần đảm bảo rằng mọi lệnh gọi đến hàm của bạn xảy ra SAU KHI giá trị đã được đặt bởi dạng xem.


1
những gì về việc truyền trực tiếp myValue dưới dạng một tham số cho hàm? Tôi thích gọi rõ ràng bằng tham số hơn là dựa vào toàn cầu, tuy nhiên, tôi không quá quan tâm đến javascript vì vậy tôi có thể thiếu một số khía cạnh quan trọng của việc có toàn cầu.
BigMike

@BigMike: Chắc chắn có thể chấp nhận được. Phương pháp tôi đưa ra ở trên chỉ đơn giản là làm cho biến có sẵn cho nhiều hàm đồng thời, nhưng sử dụng các tham số cũng tốt.
Joel Etherton

cảm ơn đã làm rõ. Sẽ thật tuyệt nếu có một số loại phiên bản đối tượng js của mô hình tự động (thông qua Thuộc tính trong lớp mô hình sẽ rất tuyệt), điều này sẽ chỉ thêm một mẫu và một giải pháp biến nhận biết không gian tên đầy đủ. Tôi đoán vấn đề lớn sẽ là làm thế nào để đưa mã vào html đã tạo được gửi đến trình duyệt (trực tiếp thông qua thẻ <script>). Tôi nghĩ rằng tôi sẽ thực hiện một số thử nghiệm về điều này ngay khi dự án hiện tại của tôi kết thúc.
BigMike

@BigMike: Điều này sẽ khá dễ thực hiện bằng cách sử dụng lớp DataContractJsonSerializer ( msdn.microsoft.com/en-us/library/… ). Nó sẽ tạo ra một phiên bản JSON của lớp bạn có thể được phân tích cú pháp vào dạng xem.
Joel Etherton

4

Có lẽ đây không phải là cách tiếp cận đúng. Cân nhắc tách rời các mối quan tâm. Bạn nên có một data injectortrên JavaScriptlớp của mình và trong hầu hết các trường hợp là dữ liệu JSON.

Tạo một tệp JS trong scriptthư mục của bạn và thêm tham chiếu này vàoView

<script src="@Url.Content("~/Scripts/yourJsFile.js")" type="text/javascript"></script>

Bây giờ, hãy xem xét một JavaScriptlớp chữ trong yourJsFile.js:

var contentSetter = {
    allData: {},
    loadData: function (data) {
        contentSetter.allData = eval('(' + data + ')');
    },
    setContentA: function () {
        $("#contentA").html(allData.contentAData);
    },
    setContentB: function () {
        $("#contentB").html(allData.contentAData);
    }
};

Cũng khai báo một lớp

public class ContentData
{
    public string ContentDataA { get; set }
    public string ContentDataB { get; set }
}

Bây giờ, từ bạn Actionlàm điều này:

public ActionResult Index() {
    var contentData = new ContentData();
    contentData.ContentDataA = "Hello";
    contentData.ContentDataB = "World";
    ViewData.Add("contentData", contentData);
}

Và theo quan điểm của bạn:

<div id="contentA"></div>
<div id="contentB"></div>

<script type="text/javascript">
    contentSetter.loadData('@Json.Encode((ContentData) ViewData["contentData"])');
    contentSetter.setContentA();
    contentSetter.setContentB();
</script>

Đẹp! nhưng tôi nghĩ nó quá phức tạp ... bạn nghĩ sao về câu trả lời của tôi? stackoverflow.com/questions/7902213/… . bằng cách bạn có lỗi sao chép dán trong setContentB mà bạn đã viết contentAData. cảm tạ!
gdoron đang hỗ trợ Monica 26/10/11

1
@gdoron Tin tôi đi, quản lý lớp học JS và xem xét tách là một cuộc sống tiết kiệm khi bạn có một dự án khổng lồ
Abdul Munim


2

Tôi thường quấn JS cần quyền truy cập vào các thuộc tính mô hình, trong các hàm và sau đó chuyển @something trong chế độ xem. Ví dụ

<script type="text/javascript">
function MyFunction(somethingPresentInTheView) {
  alert(somethingPresentInTheView);
}
</script>

trong dạng xem, tôi thêm lệnh gọi hàm thông qua (chỉ là một ví dụ):

<input type='button' onclick="MyFunction('@Model.PropertyNeeded')" />

1

Tôi nghĩ rằng bạn đang gặp khó khăn với việc phải đặt mã JS đó trong Chế độ xem. Trình phân tích cú pháp Razor, theo như tôi biết, sẽ không xem xét các tệp .js, do đó bất kỳ thứ gì bạn có mà sử dụng @sẽ không hoạt động. PLus, như bạn đã phát hiện ra, bản thân Javascript không thích @ký tự này quanh quẩn mà không có lý do gì, chẳng hạn như trong một chuỗi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.