MVC показывает значение сеанса в HTML [duplicate]

Что вы должны знать о this

this (иначе говоря, «контекст») - это специальное ключевое слово внутри каждой функции, и его значение зависит только от , как была вызвана функция, а не как / когда / где она была определена. Лексические области не затрагиваются, как и другие переменные. Вот несколько примеров:

function foo() {
    console.log(this);
}

// normal function call
foo(); // `this` will refer to `window`

// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`

// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`

Чтобы узнать больше о this, просмотрите документацию MDN .


Как сделать обратитесь к правильному this

Не используйте this

Фактически вы не хотите иметь доступ к this в частности, но объект, на который он ссылается на . Вот почему простое решение - просто создать новую переменную, которая также относится к этому объекту. Переменная может иметь любое имя, но общие - self и that.

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}

Поскольку self является нормальной переменной, она подчиняется лексическим правилам области и доступна внутри обратного вызова. Это также имеет то преимущество, что вы можете получить доступ к значению this самого обратного вызова.

Явно установить this обратного вызова - часть 1

Возможно, у вас есть не контролируйте значение this, потому что его значение устанавливается автоматически, но на самом деле это не так.

Каждая функция имеет метод .bind [docs] , который возвращает новую функцию с this, привязанную к значению. Функция имеет то же поведение, что и тот, который вы назвали .bind, только то, что this было установлено вами. Независимо от того, как и когда эта функция вызывается, this всегда будет ссылаться на переданное значение.

function MyConstructor(data, transport) {
    this.data = data;
    var boundFunction = (function() { // parenthesis are not necessary
        alert(this.data);             // but might improve readability
    }).bind(this); // <- here we are calling `.bind()` 
    transport.on('data', boundFunction);
}

В этом случае мы привязываем обратный вызов this к значению MyConstructor 's this.

Примечание. При связывании контекста для jQuery вместо этого используйте jQuery.proxy [docs] . Причина этого заключается в том, что вам не нужно сохранять ссылку на функцию при отмене обратного вызова события. jQuery обрабатывает это внутренне.

ECMAScript 6: Используйте функции стрелок

В ECMAScript 6 представлены функции стрелок , которые можно рассматривать как лямбда-функции. У них нет собственной привязки this. Вместо этого this просматривается в области видимости как обычная переменная. Это означает, что вам не нужно называть .bind. Это не единственное особое поведение, которое у них есть. Дополнительную информацию см. В документации MDN.

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}

Установите this обратного вызова - часть 2

Некоторые функции / методы, которые принимают обратные вызовы, также принимают значение, к которому должен обращаться обратный вызов this. Это в основном то же самое, что и привязывать его самостоятельно, но функция / метод делает это за вас. Array#map [docs] - такой метод. Его подпись такова:

array.map(callback[, thisArg])

Первый аргумент - это обратный вызов, а второй аргумент - значение this. Вот надуманный пример:

var arr = [1, 2, 3];
var obj = {multiplier: 42};

var new_arr = arr.map(function(v) {
    return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument

Примечание. Можно ли передать значение для this, как правило, упоминается в документации этой функции / метода. Например, метод $.ajax jQuery [docs] описывает параметр, называемый context:

Этот объект станет контекстом всех обратных вызовов, связанных с Ajax.


Общая проблема: использование объектных методов в качестве обработчиков обратных вызовов / событий

Еще одно распространенное проявление этой проблемы - когда объектный метод используется как обработчик обратного вызова / события , Функции являются первоклассными гражданами в JavaScript, а термин «метод» - просто разговорный термин для функции, которая является значением свойства объекта. Но эта функция не имеет конкретной ссылки на ее «содержащий» объект.

Рассмотрим следующий пример:

function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = function() {
    console.log(this.data);
};

Функция this.method назначается как обработчик события click , но если щелкнуть document.body, зарегистрированное значение будет undefined, потому что внутри обработчика события this ссылается на document.body, а не на экземпляр Foo. Как уже упоминалось в начале, то, что относится к [49], зависит от того, как называется функция, а не от того, как она определена. Если код выглядит следующим образом, может быть более очевидно, что функция не имеет неявной ссылки на объект:

function method() {
    console.log(this.data);
}


function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = method;

Решение такое же, как указано выше: если доступно, используйте .bind явно привязать this к определенному значению

document.body.onclick = this.method.bind(this);

или явно вызвать функцию как «метод» объекта, используя анонимную функцию в качестве обработчика обратного вызова / события и назначить object (this) к другой переменной:

var self = this;
document.body.onclick = function() {
    self.method();
};

или использовать функцию стрелки:

document.body.onclick = () => this.method();
387
задан Peter Mortensen 1 January 2016 в 17:45
поделиться

6 ответов

Одна вещь, которую нужно добавить - я обнаружил, что синтаксис синтаксиса Razor (и, вероятно, компилятор) интерпретирует положение открытой скобки по-разному:

<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>
7
ответ дан Andy 21 August 2018 в 05:58
поделиться

Я просто написал эту вспомогательную функцию. Поместите его в 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);

Обратите внимание, как я не помещаю кавычки вокруг него. Если заголовок уже содержит кавычки, он не будет взорваться. Кажется, тоже прекрасно справляются со словарями и анонимными объектами!

37
ответ дан Community 21 August 2018 в 05:58
поделиться
  • 1
    Я не понимаю ваш обновленный пример. Правильно ли работает функция addmarker? – NVM 14 November 2011 в 18:01
  • 2
    @NVM: Вместо того, чтобы выводить один и тот же код javascript несколько раз, я предлагаю создать единую функцию javascript (которая может храниться в кэшированном файле .js) и вывести несколько вызовов этой функции. Я не знаю, правильна ли эта функция: я просто основывал ее на коде OP. – StriplingWarrior 14 November 2011 в 18:08
  • 3
    Почему «@ Model.Latitude» в foreach. Почему не item.Latitude? – NVM 14 November 2011 в 18:10
  • 4
    Если вы пытаетесь закодировать объект в представлении, нет необходимости в создании вспомогательного кода, он уже существует. Мы используем это все время @Html.Raw(Json.Encode(Model)) – PJH 29 January 2014 в 16:47
  • 5
    Переменные C # должны быть экранированы. Если @item.Title содержит одну цитату, этот код взорвется. – mpen 29 January 2014 в 18:42
  • 6
    @Mark: Хорошее наблюдение. На самом деле, я обычно не объединяю javascript и Razor вообще в своем собственном коде: я предпочитаю использовать Razor для генерации HTML с атрибутами data-, а затем использовать статический, ненавязчивый javascript, чтобы получить это информация из DOM. Но вся эта дискуссия была чем-то вроде рамки вопроса. – StriplingWarrior 29 January 2014 в 18:48
  • 7
    Можете ли вы расширить свой ответ PJH? Как вы определяете заголовок, если вы просто кодируете «Модель»? – obesechicken13 1 April 2015 в 16:33
  • 8
    Кроме того, когда я пробовал этот подход с Model.Title, я получаю дополнительные кавычки вокруг закодированного javascript. Я не могу избавиться от кавычек, даже если я объединю его с чем-то другим. Эти цитаты становятся частью ваших js. – obesechicken13 1 April 2015 в 16:42
  • 9
    Комментарий PJH превосходный. В некотором смысле десериализуйте серверные модели в блоке javascript. – netfed 12 April 2017 в 18:46

Я предпочитаю «& lt;! -" "->" как "текст>"

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

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

</script>
8
ответ дан Fernando JS 21 August 2018 в 05:58
поделиться

Какие конкретные ошибки вы видите?

Что-то вроде этого может работать лучше:

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

Обратите внимание, что вам нужен магический тег <text> после foreach до что Razor должен переключиться в режим разметки.

15
ответ дан marcind 21 August 2018 в 05:58
поделиться

Наконец я нашел решение (* .vbhtml):

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

    /* String */
    var str = '@stringvariable';
    alert(str);
}
19
ответ дан Peter Mortensen 21 August 2018 в 05:58
поделиться
  • 1
    Я обновил свой вопрос, он не работает для меня - все идеи, что не так? благодаря – raklos 4 January 2011 в 23:57
  • 2
    @raklos: Вам нужно избегать ваших строк. Вызовите HTML.Raw(Server.JavaScriptStringEncode(...)) – SLaks 4 January 2011 в 23:59
  • 3
    HTML.Raw(HttpUtility.JavaScriptStringEncode(...)) - У свойства Server этот метод отсутствует. HttpUtility делает. – it3xl 8 July 2015 в 16:55
  • 4
    The Razor template engine doesn't care what it's outputting and does not differentiate between <script> or other tags. Вы уверены, что? [Д0] stackoverflow.com/questions/33666065/… – HMR 12 November 2015 в 08:14
  • 5
    @HMR: Эта функция не существовала, когда я написал этот ответ. – SLaks 12 November 2015 в 16:13
20
ответ дан Peter Mortensen 1 November 2018 в 01:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: