Trying to improve my coding styles I've tried different solutions but I can't figure out what is the best.
I've started putting JavaScript inside my views but I don't particularly like this solution. It's hard to debug with Visual Studio, and it kinds of "pollutes" the page. My new "trend" is to put the scripts for the page in a separate file. The only problem I am facing is with the code. To solve the problem I've defined JavaScript variables like this:<script type="text/javascript">
var PriceListFetchAction = '<%=Url.Action("Fetch", "PriceList")%>';
var UploaderAction = '<%=Url.Action("UploadExcelPriceList", "PriceList")%>';
var ModelId = '<%=Model.id%>';
var ImportType = '<%=Model.Type%>';
var customerCodeFetchAction = '<%=Url.Action("FetchByCustomerCode", "Customers")%>';
var customerNameFetchAction = '<%=Url.Action("FetchByCustomerName", "Customers")%>';
var ImportErpAction = '<%=Url.Action("ImportPriceListErp", "PriceList")%>';
var i开发者_如何转开发mageCalendar = '<%=Url.Content("~/Content/Images/calendar.png")%>';
</script>
and then I use the variables in my JavaScript file. What is the best in terms of performance, debugging, style for you?
I follow a handful of rules:
- Don't attach a variable directly to the DOM unless absolutely necessary.
- Place as much information in js files as possible. The fewer js files, the better.
- Version your js files. When publishing, minify and mash via Chirpy or SquishIt
- In js, minimize your dependency on dynamic server-side values (generated ids, etc.) when you can.
So, here's an example:
I'll add jQuery and jQuery metadata to my project: http://plugins.jquery.com/project/metadata
Then, in my master js file, I'll extend jQuery with my own namespace:
$.extend({
fatDish : {
url : {},
urls : function(a) {
$.extend($.fatDish.url, a);
}
}
});
Almost all of my customized js logic will live in the $.fatDish namespace.
Now, let's say I want to pass a MVC route to $.fatDish. In my aspx page, I'd write the following:
<script src="@Url.Content("~/path/master.js")" type="text/javascript"></script>
<script type="text/javascript">
$.fatDish.urls({
path1 : '@Url.Action("Index", "Home")'
});
</script>
In a js file, I can now write:
window.location = $.fatDish.url.path1;
A second approach is to use jQuery metadata (which I mentioned above). On your aspx page, you could write something like:
<div class="faux-link {act:'@Url.Action("Index", "Home")'}">Go Somewhere</div>
Then, in your js file, you can grab the route value like so:
$('.faux-link').click(function() {
var $this = $(this);
var href = $this.metadata().act;
window.location = href;
});
I create separate javascripts for calculations / logic, but call them from my view. In this way I do not have to create global variables and its easier to re-use the javascripts.
example javascript:
function doSomeCoolProcessing(modelId, fetchAction)
{
//some stuff
}
and in the view
<script type="text/javascript">
$('document').ready(function() {
doSomeCoolProcessing('<%=Model.id%>', '<%=Url.Action("Fetch", "PriceList")%>');
)};
</script>
It also makes it a lot clearer what's happening (and debugging when you return to your project after six months), since nothing happens unless you explicitly tell it to do so.
Personally I always put javascript in separate files. Global variables which depend on routing or some server side information inside the view. Exactly as you do. As an alternative to storing global variables you could use anchor or form elements which already contain the url and then ajaxify them. As far as model values are concerned they could be stored also in DOM elements such as hidden fields, CSS classes, HTML5 data-* attributes, ... but this might not be applicable to all situations.
A separate file for tidiness at the least. The less languages you put into each file, the easier it will be to read what it does at a glance.
vandalo,
I've borrowed a situation whereby the javascript is all in seperate file. however, using a custom action result on the controller, the js is invoked as an htmlhelper function and has a context with the page. the htmlhelper actually serves the code as a file and it's therefore cached, thus speeding up excecution/delivery.
I know you'll be curious to see how this works, so will update the answer to show the mechanics of this a little later.
til then... (here's a link to where i got my inspiration. i then tweaked this to my own needs)
ASP.NET MVC routing and paths is js files
ok, here's my worked example (a simple mvc 2 project that contains required helpers and classes) - enjoy:
http://www.gatehousemusic.com/downloads/ServeJsExample.zip
Here's my methods on ASP.NET MVC3 to complete the @weirdlover answer, one thing he's missing is the JSON encoding which is quite important when you want to safely inject data in js.
If the data is not too big and can be logically attached to a DOM element, I use one (or several) data-attribute (don't require a jQuery plugin and leave the css class pretty) and a css class to find the elements from jQuery.
Stupid example:
HTML:
<div class="text-widget"
data-options="@Json.Encode(new { url = Url.Action("Update", "Text", new { id = 3 }), uselessParam = true })">
<input type="text" />
</div>
COFFEESCRIPT:
class TextWidget
constructor: (@element) ->
@el = $ @element
@options = @el.data 'options'
@input = @el.find 'input'
@input.change @update
update: =>
value = @input.val()
$.post @options.url,
value: value
, -> alert 'text saved'
$ ->
new TextWidget element for element in $('.text-widget').get()
A little gotcha with Json.Encode and jQuery.data: if you use it on a simple string, you will get a quoted string in javascript: $().data('strattribute') == ' "hello" '. Just use Html.Encode in that case.
Anyway I prefer to use a single attibute with an anonymous object I build in the controller, it's easier to maintain: data-options="@Json.Encode(Model.Options)"
.
If there is a lot of data, like a list of objects I will turn to ViewModels for knockoutjs, I use a <script>
and var data = @(Html.Raw(Json.Encode(Model.MyData)));
.
I also use namespacing and closures to avoid poluting the global object.
精彩评论