首页 文章

在JavaScript中使用Razor

提问于
浏览
392

在视图( cshtml )中的JavaScript中使用Razor语法是否可行或有解决方法?

我正在尝试将标记添加到Google Map 中...例如,我试过这个,但是我收到了大量的编译错误:

<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>

12 回答

  • 15

    只要它在CSHTML页面而不是外部JavaScript文件中,这样就可以正常工作 .

    Razor模板引擎不会输出't care what it'或其他标签 .

    但是,您需要对字符串进行编码以防止XSS攻击 .

  • 20

    我更喜欢“<! - ”“ - >”喜欢“文字>”

    <script type="text/javascript">
    //some javascript here     
    
    @foreach (var item in itens)
    {                 
    <!--  
       var title = @(item.name)
        ...
    -->
    
    </script>
    
  • 7

    你试图把一个方形的钉子塞进圆孔里 .

    Razor旨在用作生成HTML的模板语言 . 您很可能会生成JavaScript代码,但它不是为此而设计的 .

    例如:如果 Model.Title 包含撇号怎么办?这会破坏您的JavaScript代码,默认情况下Razor无法正确转义它 .

    在辅助函数中使用String生成器可能更合适 . 这种方法可能会产生更少的意外后果 .

  • 8

    您看到了哪些具体错误?

    像这样的东西可以更好地工作:

    <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>
    

    请注意,您需要在 foreach 之后使用神奇的 <text> 标记来指示Razor应切换到标记模式 .

  • 578

    使用 <text> 伪元素(如here所述)强制Razor编译器返回内容模式:

    <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>
    

    Update:

    Scott Guthrie recently posted关于Razor中的 @: 语法,如果你只需要添加一行或两行JavaScript代码,它就会比 <text> 标签略显笨重 . 以下方法可能更可取,因为它减少了生成的HTML的大小 . (您甚至可以将addMarker函数移动到静态缓存的JavaScript文件中以进一步减小大小):

    <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>
    

    更新了上面的代码,使对 addMarker 的调用更加正确 .

    为了澄清, @: 迫使Razor回到文本模式,即使 addMarker 调用看起来很像C#代码 . 然后Razor选择 @item.Property 语法来说它应该直接输出这些属性的内容 .

    更新2

    它是放置JavaScript代码的好地方 . JavaScript代码应放在静态 .js 文件中,然后它应该从Ajax调用或从HTML扫描 data- 属性获取所需的数据 . 除了可以缓存JavaScript代码之外,这还避免了编码问题,因为Razor旨在编码HTML,而不是JavaScript .

    查看代码

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

    JavaScript代码

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

    我刚写了这个辅助函数 . 把它放在 App_Code/JS.cshtml

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

    然后在您的示例中,您可以执行以下操作:

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

    注意我怎么不在它周围加上引号 . 如果 Headers 已包含引号,则不会爆炸 . 似乎也很好地处理字典和匿名对象!

  • 10

    有一点要补充 - 我发现Razor语法hilighter(可能还有编译器)以不同的方式解释了开括号的位置:

    <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

    以下解决方案似乎比将JavaScript与Razor结合起来更准确 . 看看这个:https://github.com/brooklynDev/NGon

    您可以将几乎任何复杂数据添加到 ViewBag.Ngon 并在 JavaScript 中访问它

    In the controller:

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

    In 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>
    

    它允许使用默认 JavascriptSerializer 序列化的任何plain old CLR objects(POCO) .

  • 5

    一个简单而好的直截了当的例子:

    <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>
    

    这会在页面中放置代码的位置创建一个脚本,如下所示:

    <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>
    

    现在您有一个名为 razorUserName 的全局JavaScript变量,您可以在客户端上访问和使用它 . Razor引擎显然从 @User.Identity.Name (服务器端变量)中提取了值,并将其放入写入脚本标记的代码中 .

  • 4

    除了@:和 <text></text> 之外,还有一个选项 .

    使用 <script> 块本身 .

    当您需要根据Razor代码执行大量JavaScript时,您可以这样做:

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

    这种方式的优点是它不会混淆JavaScript和Razor太多,因为混合它们会最终导致可读性问题 . 大文本块也不是很易读 .

  • 3

    以前的解决方案都没有正常工作......我已经尝试了所有的方法,但它没有给我预期的结果......最后我发现代码中有一些错误......下面给出了完整的代码 .

    <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>
    
  • 3

    我终于找到了解决方案(* .vbhtml):

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

相关问题