Sử dụng dao cạo trong JavaScript


434

Có thể hoặc có một cách giải quyết để sử dụng cú pháp Dao cạo trong JavaScript nằm trong dạng xem ( cshtml) không?

Tôi đang cố gắng thêm các điểm đánh dấu vào bản đồ Google ... Ví dụ: tôi đã thử cách này, nhưng tôi đang nhận được rất nhiều lỗi biên dịch:

<script type="text/javascript">

    // Some JavaScript code here to display map, etc.

    // Now add markers
    @foreach (var item in Model) {

        var markerlatLng = new google.maps.LatLng(@(Model.Latitude), @(Model.Longitude));
        var title = '@(Model.Title)';
        var description = '@(Model.Description)';
        var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'

        var infowindow = new google.maps.InfoWindow({
            content: contentString
        });

        var marker = new google.maps.Marker({
            position: latLng,
            title: title,
            map: map,
            draggable: false
        });

        google.maps.event.addListener(marker, 'click', function () {
            infowindow.open(map, marker);
        });
    }
</script>

3
bạn có thể quan tâm đến cập nhật của tôi về @:cú pháp.
StriplingWar Warrior

@anyone xem xét thực hiện theo cách này, ít nhất là đặt dữ liệu vào một thẻ script riêng biệt chỉ định nghĩa một số JSON sau đó được sử dụng trong JS. JS kết hợp back-end ở mặt trước đã là một Pita di sản đối với tôi trong một số dịp. Đừng viết mã bằng mã nếu bạn không phải làm vậy. Thay vào đó hãy tắt dữ liệu.
Erik Reppen

Câu trả lời:


636

Sử dụng <text>phần tử giả, như được mô tả ở đây , để buộc trình biên dịch dao cạo trở lại chế độ nội dung:

<script type="text/javascript">

    // Some JavaScript code here to display map, etc.


    // Now add markers
    @foreach (var item in Model) {
        <text>
            var markerlatLng = new google.maps.LatLng(@(Model.Latitude), @(Model.Longitude));
            var title = '@(Model.Title)';
            var description = '@(Model.Description)';
            var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'

            var infowindow = new google.maps.InfoWindow({
                content: contentString
            });

            var marker = new google.maps.Marker({
                position: latLng,
                title: title,
                map: map,
                draggable: false
            });

            google.maps.event.addListener(marker, 'click', function () {
                infowindow.open(map, marker);
            });
        </text>
    }
</script>

Cập nhật:

Scott Guthrie gần đây đã đăng về @:cú pháp trong Dao cạo, hơi khó sử dụng hơn một chút so với <text>thẻ nếu bạn chỉ có một hoặc hai dòng mã JavaScript để thêm. Cách tiếp cận sau có lẽ sẽ thích hợp hơn, vì nó làm giảm kích thước của HTML được tạo. (Bạn thậm chí có thể di chuyển hàm addMarker sang tệp JavaScript được lưu trong bộ nhớ cache để giảm thêm kích thước):

<script type="text/javascript">

    // Some JavaScript code here to display map, etc.
    ...
    // Declare addMarker function
    function addMarker(latitude, longitude, title, description, map)
    {
        var latLng = new google.maps.LatLng(latitude, longitude);
        var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>';

        var infowindow = new google.maps.InfoWindow({
            content: contentString
        });

        var marker = new google.maps.Marker({
            position: latLng,
            title: title,
            map: map,
            draggable: false
        });

        google.maps.event.addListener(marker, 'click', function () {
            infowindow.open(map, marker);
        });
    }

    // Now add markers
    @foreach (var item in Model) {
        @:addMarker(@item.Latitude, @item.Longitude, '@item.Title', '@item.Description', map);
    }
</script>

Cập nhật mã trên để thực hiện cuộc gọi addMarkerchính xác hơn.

Để làm rõ, các @:lực lượng Dao cạo trở lại chế độ văn bản, mặc dù addMarkercuộc gọi trông rất giống mã C #. Sau đó, dao động chọn @item.Propertycú pháp để nói rằng nó sẽ trực tiếp xuất nội dung của các thuộc tính đó.

Cập nhật 2

Điều đáng chú ý là Xem mã thực sự không phải là nơi tốt để đặt mã JavaScript. Mã JavaScript phải được đặt trong một .jstệp tĩnh và sau đó nó sẽ nhận được dữ liệu mà nó cần từ một cuộc gọi Ajax hoặc bằng cách quét các data-thuộc tính từ HTML. Bên cạnh việc có thể lưu mã JavaScript của bạn, điều này cũng tránh được các vấn đề về mã hóa, vì Dao cạo được thiết kế để mã hóa cho HTML, nhưng không phải là JavaScript.

Xem mã

@foreach(var item in Model)
{
    <div data-marker="@Json.Encode(item)"></div>
}

Mã JavaScript

$('[data-marker]').each(function() {
    var markerData = $(this).data('marker');
    addMarker(markerData.Latitude, markerData.Longitude,
              markerData.Description, markerData.Title);
});

3
Tôi không hiểu ví dụ cập nhật của bạn. Hàm addmarker có đúng không?
NVM

2
@NVM: Thay vì xuất ra cùng một mã javascript nhiều lần, tôi khuyên bạn nên tạo một hàm javascript duy nhất (có thể được giữ trong tệp .js được lưu trong bộ nhớ cache) và thực hiện một số lệnh gọi cho hàm đó. Tôi không biết chức năng này có đúng không: Tôi chỉ dựa vào mã của OP.
StriplingWar Warrior

1
Tại sao '@ Model.Latitude' trong foreach. Tại sao không phải là vật phẩm.
NVM

5
Các biến C # của bạn cần được thoát. Nếu @item.Titlechứa một trích dẫn, mã này sẽ phát nổ.
mở

7
@Mark: Quan sát tốt. Trong thực tế, tôi thường không kết hợp javascript và Razor ở tất cả trong mã của riêng tôi: Tôi thích sử dụng Razor để tạo HTML với data-các thuộc tính, và sau đó sử dụng tĩnh, javascript không phô trương để thu thập thông tin này từ DOM. Nhưng toàn bộ cuộc thảo luận đó là loại vượt quá phạm vi của câu hỏi.
StriplingWar Warrior

39

Tôi chỉ viết chức năng trợ giúp này. Đặt nó vào App_Code/JS.cshtml:

@using System.Web.Script.Serialization
@helper Encode(object obj)
{
    @(new HtmlString(new JavaScriptSerializer().Serialize(obj)));
}

Sau đó, trong ví dụ của bạn, bạn có thể làm một cái gì đó như thế này:

var title = @JS.Encode(Model.Title);

Lưu ý cách tôi không đặt dấu ngoặc kép xung quanh nó. Nếu tiêu đề đã chứa dấu ngoặc kép, nó sẽ không phát nổ. Có vẻ để xử lý từ điển và các đối tượng ẩn danh độc đáo quá!


19
Nếu bạn đang cố mã hóa một đối tượng trong khung nhìn thì không cần tạo mã trợ giúp, thì đã tồn tại một đối tượng. Chúng tôi sử dụng điều này mọi lúc@Html.Raw(Json.Encode(Model))
PJH

2
Bạn có thể mở rộng câu trả lời của bạn không? Làm thế nào để bạn chỉ định tiêu đề nếu bạn chỉ mã hóa "Model"?
obesechicken13

2
Ngoài ra, khi tôi thử phương pháp này với Model.Title tôi nhận được một số trích dẫn bổ sung xung quanh javascript được mã hóa. Tôi không thể loại bỏ các trích dẫn ngay cả khi tôi ghép nó với một cái gì đó khác. Những trích dẫn trở thành một phần của js của bạn.
obesechicken13

1
Nhận xét của PJH là tuyệt vời. Theo cách bạn giải tuần tự hóa các mô hình phía máy chủ thành khối javascript.
netfed

24

Bạn đang cố gắng kẹt một cái chốt vuông trong một cái lỗ tròn.

Dao cạo được dự định là ngôn ngữ mẫu tạo HTML. Bạn rất có thể lấy nó để tạo mã JavaScript, nhưng nó không được thiết kế cho điều đó.

Ví dụ: Điều gì nếu Model.Titlechứa dấu nháy đơn? Điều đó sẽ phá vỡ mã JavaScript của bạn và theo mặc định, Dao cạo sẽ không thoát được mã đó.

Có lẽ sẽ thích hợp hơn khi sử dụng trình tạo String trong hàm trợ giúp. Có thể sẽ có ít hậu quả không lường trước của phương pháp đó.


17

Những lỗi cụ thể bạn đang nhìn thấy?

Một cái gì đó như thế này có thể hoạt động tốt hơn:

<script type="text/javascript">

//now add markers
 @foreach (var item in Model) {
    <text>
      var markerlatLng = new google.maps.LatLng(@Model.Latitude, @Model.Longitude);
      var title = '@(Model.Title)';
      var description = '@(Model.Description)';
      var contentString = '<h3>' + title + '</h3>' + '<p>' + description + '</p>'
    </text>
}
</script>

Lưu ý rằng bạn cần <text>thẻ ma thuật sau foreachđể chỉ ra rằng Dao cạo nên chuyển sang chế độ đánh dấu.


1
Mô hình lặp (bằng foreach) và được đánh dấu @ Model.Latidue? chức năng của lặp là gì? Tôi nghĩ rằng đã bỏ lỡ một cái gì đó. nó có thể là @ item.Latitude, v.v.
Nuri YILMAZ

12

Điều đó sẽ hoạt động tốt, miễn là nó ở trong trang CSHTML chứ không phải tệp JavaScript bên ngoài.

Công cụ mẫu dao cạo không quan tâm đến những gì nó xuất ra và không phân biệt giữa <script>hoặc các thẻ khác.

Tuy nhiên, bạn cần mã hóa chuỗi của mình để ngăn chặn các cuộc tấn công XSS .


2
Tôi đã cập nhật câu hỏi của mình, Nó không hoạt động đối với tôi - rất nhiều ý tưởng có gì sai? cảm ơn
raklos

3
@raklos: Bạn cần thoát khỏi chuỗi của bạn. GọiHTML.Raw(Server.JavaScriptStringEncode(...))
SLaks

1
HTML.Raw(HttpUtility.JavaScriptStringEncode(...))- Thuộc tính máy chủ không có phương pháp này bây giờ. Khả năng hoạt động nào.
it3xl

1
The Razor template engine doesn't care what it's outputting and does not differentiate between <script> or other tags.Bạn có chắc chắn aobut đó? stackoverflow.com/questions/33666065/
trộm

2
@HMR: Tính năng đó không tồn tại khi tôi viết câu trả lời này.
SLaks

11

Tôi thích "<! -" "->" thích "văn bản>"

<script type="text/javascript">
//some javascript here     

@foreach (var item in itens)
{                 
<!--  
   var title = @(item.name)
    ...
-->

</script>

Đây là một giải pháp kỳ lạ phù hợp với tôi, bởi vì văn bản tôi cần đưa vào có một số dấu phân cách mà Razor không thích với các phương thức @:<text>
BuddyZ

8

Một điều cần thêm vào - Tôi thấy rằng cú pháp dao cạo hilolder (và có lẽ là trình biên dịch) diễn giải vị trí của dấu ngoặc mở khác nhau:

<script type="text/javascript">
    var somevar = new Array();

    @foreach (var item in items)
    {  // <----  placed on a separate line, NOT WORKING, HILIGHTS SYNTAX ERRORS
        <text>
        </text>
    }

    @foreach (var item in items) {  // <----  placed on the same line, WORKING !!!
        <text>
        </text>
    }
</script>

6

Một ví dụ đơn giản và tốt về phía trước:

<script>
    // This gets the username from the Razor engine and puts it
    // in JavaScript to create a variable I can access from the
    // client side.
    //
    // It's an odd workaraound, but it works.
    @{
        var outScript = "var razorUserName = " + "\"" + @User.Identity.Name + "\"";
    }
    @MvcHtmlString.Create(outScript);
</script>

Điều này tạo ra một tập lệnh trong trang của bạn tại vị trí bạn đặt mã ở trên trông giống như sau:

<script>
    // This gets the username from the Razor engine and puts it
    // in JavaScript to create a variable I can access from
    // client side.
    //
    // It's an odd workaraound, but it works.

    var razorUserName = "daylight";
</script>

Bây giờ bạn có một biến JavaScript toàn cầu có tên razorUserNamemà bạn có thể truy cập và sử dụng trên máy khách. Công cụ dao cạo rõ ràng đã trích xuất giá trị từ @User.Identity.Name(biến phía máy chủ) và đặt nó vào mã mà nó ghi vào thẻ script của bạn.


6

Giải pháp sau đây có vẻ chính xác với tôi hơn là kết hợp JavaScript với Dao cạo. Hãy xem điều này: https://github.com/brooklynDev/NGon

Bạn có thể thêm hầu hết mọi dữ liệu phức tạp vào ViewBag.Ngon và truy cập nó bằng JavaScript

Trong bộ điều khiển:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var person = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
        ViewBag.NGon.Person = person;
        return View();
    }
}

Trong JavaScript:

<script type="text/javascript">
    $(function () {
        $("#button").click(function () {
            var person = ngon.Person;
            var div = $("#output");
            div.html('');
            div.append("FirstName: " + person.FirstName);
            div.append(", LastName: " + person.LastName);
            div.append(", Age: " + person.Age);
        });
    });
</script>

Nó cho phép mọi đối tượng CLR cũ (POCO) đơn giản có thể được tuần tự hóa bằng cách sử dụng mặc định JavascriptSerializer.


5

Ngoài ra còn có một tùy chọn khác hơn @: và <text></text>.

Sử dụng <script>khối chính nó.

Khi bạn cần thực hiện một khối lượng lớn JavaScript tùy thuộc vào mã Dao cạo, bạn có thể làm như thế này:

@if(Utils.FeatureEnabled("Feature")) {
    <script>
        // If this feature is enabled
    </script>
}

<script>
    // Other JavaScript code
</script>

Ưu điểm của cách này là nó không trộn lẫn JavaScript và Dao cạo quá nhiều, vì trộn chúng nhiều sẽ gây ra vấn đề về khả năng đọc. Ngoài ra các khối văn bản lớn cũng không dễ đọc.


4

Không có giải pháp nào trước đây hoạt động chính xác ... Tôi đã thử tất cả các cách, nhưng nó không mang lại cho tôi kết quả như mong đợi ... Cuối cùng tôi thấy rằng có một số lỗi trong mã ... Và mã đầy đủ được đưa ra phía dưới.

<script type="text/javascript">

    var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 10,
        center: new google.maps.LatLng(23.00, 90.00),
        mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    @foreach (var item in Model)
    {
        <text>
            var markerlatLng = new google.maps.LatLng(@(item.LATITUDE), @(item.LONGITUDE));
            var title = '@(item.EMP_ID)';
            var description = '@(item.TIME)';
            var contentString = '<h3>' + "Employee " +title+ " was here at "+description+ '</h3>' + '<p>'+" "+ '</p>'

            var infowindow = new google.maps.InfoWindow({
                // content: contentString
            });

            var marker = new google.maps.Marker({
                position: markerlatLng,
                title: title,
                map: map,
                draggable: false,
                content: contentString
            });

            google.maps.event.addListener(marker, 'click', (function (marker) {
                return function () {
                    infowindow.setContent(marker.content);
                    infowindow.open(map, marker);
                }
            })(marker));
        </text>
    }
</script>

4

Cuối cùng tôi đã tìm thấy giải pháp (* .vbhtml):

function razorsyntax() {
    /* Double */
    @(MvcHtmlString.Create("var szam =" & mydoublevariable & ";"))
    alert(szam);

    /* String */
    var str = '@stringvariable';
    alert(str);
}
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.