在JavaScript中使用Razor
在视图( cshtml
)中的JavaScript中使用Razor语法是否可行或是否有解决方法?
我正在尝试将标记添加到Google地图中…例如,我尝试了这一点,但是收到了大量的编译错误:
<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>
使用<text>
伪元素,如此处所述,强制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>
更新:
Scott Guthrie最近在Razor上发布了关于@:
语法的内容,如果你只添加了一行或两行JavaScript代码,它比<text>
标签稍微笨拙。 下面的方法可能会更好,因为它减less了生成的HTML的大小。 (你甚至可以将addMarker函数移动到一个静态的,caching的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#代码。 然后剃刀拿起@item.Property
语法来说,它应该直接输出这些属性的内容。
更新2
值得注意的是,查看代码真的不是放置JavaScript代码的好地方。 JavaScript代码应该放在一个静态的.js
文件中,然后它应该从Ajax调用或通过扫描HTML中的data-
属性来获取它所需要的data-
。 除了可以cachingJavaScript代码,这也可以避免编码问题,因为Razor被devise为编码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); });
我只写了这个帮助函数。 把它放在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);
注意我怎么不把它引用。 如果标题已经包含引号,则不会爆炸。 似乎很好地处理字典和匿名对象!
你正在试图把一个方形的钉子塞在一个圆孔里。
Razor的目的是作为一个HTML生成模板语言。 您可能很好地生成JavaScript代码,但它不是为此devise的。
例如:如果Model.Title
包含一个撇号呢? 这会破坏你的JavaScript代码,并且Razor默认不会正确地转义它。
在辅助函数中使用String生成器可能更合适。 这种方法可能会导致意想不到的后果。
你看到了什么具体的错误?
像这样的东西可以更好地工作:
<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应该切换到标记模式。
这将工作得很好,只要它在一个CSHTML页面,而不是一个外部的JavaScript文件。
Razor模板引擎不关心输出的内容,也不区分<script>
或其他标签。
但是,您需要对string进行编码以防止XSS攻击。
我更喜欢“<! – ”“ – >”像“文本”“
<script type="text/javascript"> //some javascript here @foreach (var item in itens) { <!-- var title = @(item.name) ... --> </script>
有一件事要补充 – 我发现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>
一个简单而直接的例子:
<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>
这会在您放置上面的代码的位置在您的页面中创build一个脚本,如下所示:
<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
的全局JavaScriptvariables,您可以在客户端上访问和使用该variables。 Razor引擎显然从@User.Identity.Name
(服务器端variables)中提取了值,并将其写入到写入脚本标记的代码中。
还有一个比@和<text></text>
更多的选项。
使用<script>
块本身。
当你需要根据Razor代码来完成大块的JavaScript时,你可以这样做:
@if(Utils.FeatureEnabled("Feature")) { <script> // If this feature is enabled </script> } <script> // Other JavaScript code </script>
这种方式的优点是它不会混合使用JavaScript和Razor,因为混合它们会导致可读性问题。 同样大的文本块也不是很可读。
下面的解决scheme似乎比JavaScript和Razor更加精确。 看看这个: https : //github.com/brooklynDev/NGon
您可以将几乎任何复杂的数据添加到ViewBag.Ngon并在JavaScript中访问它
在控制器中:
public class HomeController : Controller { public ActionResult Index() { var person = new Person { FirstName = "John", LastName = "Doe", Age = 30 }; ViewBag.NGon.Person = person; return View(); } }
在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>
它允许任何普通的旧CLR对象 (POCO)可以使用默认的JavascriptSerializer
进行序列化。
以前的解决scheme没有任何工作正常…我已经尝试了所有的方法,但它没有给我预期的结果…最后我发现代码中有一些错误…并给出完整的代码下面。
<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>
我终于find了解决scheme(* .vbhtml):
function razorsyntax() { /* Double */ @(MvcHtmlString.Create("var szam =" & mydoublevariable & ";")) alert(szam); /* String */ var str = '@stringvariable'; alert(str); }