Ist es möglich, in einer externen Javascript-Datei auf eine Model-Eigenschaft zuzugreifen?
z.B. In der Datei "somescript.js"
var currency = '@Model.Currency';
alert(currency);
Meiner Ansicht nach
<script src="../../Scripts/somescript.js" type="text/javascript">
Dies scheint jedoch nicht zu funktionieren, wenn ich das Javascript direkt in die Ansicht innerhalb der Skript-Tags setze, funktioniert es dann? Dies bedeutet, dass der Code die ganze Zeit in die Seite eingefügt werden muss, anstatt die externe Skriptdatei wie folgt zu laden:
@model MyModel;
<script lang=, type=>
var currency = '@Model.Currency';
alert(currency);
</script>
Gibt es einen Weg, dies zu umgehen?
Es ist nicht möglich, MVC/Razor-Code in JS-Dateien zu implementieren.
Sie sollten variable Daten in Ihrem HTML-Code (in den .cshtml-Dateien) festlegen. Dies ist konzeptionell in Ordnung und verstößt nicht gegen die Trennung von Bedenken (vom Server generierter HTML-Code im Vergleich zu Client-Skriptcode). Wenn Sie darüber nachdenken, sind diese Variablenwerte ein Serveranliegen.
Sehen Sie sich diese (teilweise aber schöne) Problemumgehung an: Verwenden von Inline C # in der Javascript-Datei in MVC Framework
Ich habe dieses Problem zusammen mit jQuery mit Datenattributen angegangen. Es sorgt für sehr gut lesbaren Code, ohne dass Teilansichten oder statisches Javascript über eine ViewEngine erforderlich sind. Die JavaScript-Datei ist vollständig statisch und wird normalerweise zwischengespeichert.
Index.cshtml:
@model Namespace.ViewModels.HomeIndexViewModel
<h2>
Index
</h2>
@section scripts
{
<script id="Index.js" src="~/Path/To/Index.js"
data-action-url="@Url.Action("GridData")"
data-relative-url="@Url.Content("~/Content/Images/background.png")"
data-sort-by="@Model.SortBy
data-sort-order="@Model.SortOrder
data-page="@ViewData["Page"]"
data-rows="@ViewData["Rows"]"></script>
}
Index.js:
jQuery(document).ready(function ($) {
// import all the variables from the model
var $vars = $('#Index\\.js').data();
alert($vars.page);
alert($vars.actionUrl); // Note: hyphenated names become camelCased
});
_Layout.cshtml (optional, aber gute Gewohnheit):
<body>
<!-- html content here. scripts go to bottom of body -->
@Scripts.Render("~/bundles/js")
@RenderSection("scripts", required: false)
</body>
Was Sie tun können, ist, die Rasiermesser-Tags als Variable zu übergeben.
Im Rasiermesser Datei>
var currency = '@Model.Currency';
doAlert(currency);
in JS-Datei>
function doAlert(curr){
alert(curr);
}
Was ich getan habe, war ein js-Objekt mit dem Method Invocation-Muster zu erstellen. Dann können Sie es aus der externen js-Datei aufrufen. Da js globale Variablen verwendet, kapsle ich es, um sicherzustellen, dass keine Konflikte mit anderen js-Bibliotheken auftreten. Beispiel: In der Ansicht
@section scripts{
<script>
var thisPage = {
variableOne: '@Model.One',
someAjaxUrl: function () { return '@Url.Action("ActionName", "ControllerName")'; }
};
</script>
@Scripts.Render("~/Scripts/PathToExternalScriptFile.js")
}
Innerhalb der externen Seite können Sie dann die Daten mit einem geschützten Bereich abrufen, um sicherzustellen, dass sie nicht mit anderen globalen Variablen in Js in Konflikt stehen.
console.log('VariableOne = ' + thisPage.variableOne);
console.log('Some URL = ' + thisPage.someAjaxUrl());
Sie können es auch innerhalb eines Moduls in die externe Datei packen, um es sogar noch kollisionssicherer zu machen. Beispiel:
$(function () {
MyHelperModule.init(thisPage || {});
});
var MyHelperModule = (function () {
var _helperName = 'MyHelperModule';
// default values
var _settings = { debug: false, timeout:10000, intervalRate:60000};
//initialize the module
var _init = function (settings) {
// combine/replace with (thisPage/settings) passed in
_settings = $.extend(_settings, settings);
// will only display if thisPage has a debug var set to true
_write('*** DEBUGGER ENABLED ***');
// do some setup stuff
// Example to set up interval
setInterval(
function () { _someCheck(); }
, _settings.intervalRate
);
return this; // allow for chaining of calls to helper
};
// sends info to console for module
var _write = function (text, always) {
if (always !== undefined && always === true || _settings.debug === true) {
console.log(moment(new Date()).format() + ' ~ ' + _helperName + ': ' + text);
}
};
// makes the request
var _someCheck = function () {
// if needed values are in settings
if (typeof _settings.someAjaxUrl === 'function'
&& _settings.variableOne !== undefined) {
$.ajax({
dataType: 'json'
, url: _settings.someAjaxUrl()
, data: {
varOne: _settings.variableOne
}
, timeout: _settings.timeout
}).done(function (data) {
// do stuff
_write('Done');
}).fail(function (jqxhr, textStatus, error) {
_write('Fail: [' + jqxhr.status + ']', true);
}).always(function () {
_write('Always');
});
} else {// if any of the page settings don't exist
_write('The module settings do not hold all required variables....', true);
}
};
// Public calls
return {
init: _init
};
})();
Versuchen Sie JavaScriptModel ( http://jsm.codeplex.com ):
Fügen Sie Ihrer Controller-Aktion einfach folgenden Code hinzu:
this.AddJavaScriptVariable("Currency", Currency);
Nun können Sie in JavaScript auf die Variable "Währung" zugreifen.
Wenn diese Variable an der Bohrungsstelle verfügbar sein sollte, legen Sie sie in einen Filter. Ein Beispiel für die Verwendung von JavaScriptModel aus einem Filter finden Sie in der Dokumentation.
Ich hatte das gleiche Problem und tat dies:
Aussicht.
`var model = @Html.Raw(Json.Encode(Model.myModel));
myFunction(model);`
Externe js.
`function myFunction(model){
//do stuff
}`
Sie könnten immer RazorJs versuchen. Es ist so ziemlich nicht mehr möglich, ein Modell in Ihren js-Dateien verwenden zu können. RazorJs