asp.net-mvc: símbolo '@' de razor no arquivo js

90

Eu tenho um .csHtmlarquivo -razor com uma função javascript que usa a @Url.Contentfunção C # interna para a URL ajax.
Quero mover essa função para um .jsarquivo referenciado de minha visão.

O problema é que o javascript não "conhece" o @símbolo e não analisa o código C #.
Existe uma maneira de fazer referência a .jsarquivos na visualização com o símbolo "@"?

gdoron está apoiando Monica
fonte
2
Talvez isso ajude (veja a resposta) stackoverflow.com/questions/7892793/ajax-succes-function
Andriy Khrystyanovich

Respostas:

87

Você pode usar data-*atributos HTML5 . Suponhamos que você deseje realizar alguma ação quando algum elemento DOM, como um div, for clicado. Assim:

<div id="foo" data-url="@Url.Content("~/foobar")">Click me</div>

e então, em seu arquivo javascript separado, você poderia trabalhar discretamente com o DOM:

$('#foo').click(function() {
    var url = $(this).data('url');
    // do something with this url
});

Dessa forma, você poderia ter uma separação pura entre marcação e script sem precisar de nenhuma tag do lado do servidor em seus arquivos javascript.

Darin Dimitrov
fonte
Obrigado. Acho que para vários valores pode ser uma dor de cabeça. Em primeiro lugar pensei que poderia resolver o meu problema, mas depois de experimentar, encontrei muitas referências no meu código e decidi encontrar outra forma.
QMaster
19

Bem, eu acabei de encontrar um motor de barbear no Nuget que faz isso! O significado resolve a @sintaxe!
Seu nome é RazorJS .

O pacote Nuget


Atualização de 2016:
O pacote não foi atualizado por 5 anos, e o link do site do projeto está morto. Eu não recomendo que as pessoas usem mais esta biblioteca.

gdoron está apoiando Monica
fonte
Você pode dar uma olhada nisso? stackoverflow.com/questions/27702322/…
iamCR
O primeiro link está quebrado
Memet Olsen
@MemetOlsen, de fato, desculpe, mas não consigo encontrar uma cópia dele, então removi :(
gdoron está apoiando Monica
@gdoron, sem problemas. Eu só queria que você soubesse sobre o link morto. Como você afirmou, o pacote não foi atualizado por 5 anos, então provavelmente é uma má ideia usá-lo de qualquer maneira.
Memet Olsen
10

Uma maneira de resolver o problema é:

Adicionando uma visão parcial com as funções javascript à visão.
Desta forma, você pode usar o @símbolo e todas as suas javascriptfunções serão separadas da visualização.

gdoron está apoiando Monica
fonte
9

Você tem duas opções:

  • Use o valor como um parâmetro na função e conecte na visualização
  • Crie um namespace (em vez de uma variável de nível público, o que é considerado uma prática ruim em JS) e defina esse valor no topo da página e, em seguida, use-o em seu js

Por exemplo:

 var MyCompany = 
 {
   MyProject: {
                  MyVariable:""
               }
  };

E então, em sua visão, defina-o:

MyCompany.MyProject.MyVariable = @....

ATUALIZAR

Você pode estar se perguntando que nenhum é bom por causa do acoplamento, bem, é verdade, você está acoplando js e view. É por isso que os scripts devem ignorar o local em que estão sendo executados, portanto, é um sintoma de organização inadequada de arquivos.

De qualquer forma, há uma terceira opção para criar um mecanismo de visualização e executar os arquivos js no barbeador e enviar os resultados de volta. Isso é mais limpo, mas muito mais lento, então também não é recomendado.

Aliostad
fonte
1
1 eu faço o primeiro método. Chame uma função de inicialização de sua visualização, passando todos os dados de que você precisa.
Richard Dalton
Obrigado, a segunda abordagem não é um acoplamento ruim entre a visualização e o arquivo js? Você tem uma maneira melhor?
gdoron está apoiando Monica em
Ambos estão acoplados. Não há como desacoplar, a menos que você escreva um mecanismo de visualização para processar arquivos js antes da renderização. Veja minhas atualizações.
Aliostad
que tal esse caminho que eu sugeri? stackoverflow.com/questions/7902213/…
gdoron está apoiando Monica em
Parece bom. Meu +1. Vista parcial ou total, não muda nada. É tudo vista de acoplamento com js.
Aliostad
7

Para obter a @variável em seu arquivo .js, você terá que usar uma variável global e definir o valor dessa variável na visualização mvc que está usando esse arquivo .js.

Arquivo JavaScript:

var myValue;

function myFunc() {
  alert(myValue);
}

Arquivo MVC View:

<script language="text/javascript">
    myValue = @myValueFromModel;
</script>

Apenas certifique-se de que qualquer chamada para sua função aconteça APÓS o valor ter sido definido pela visualização.

Joel Etherton
fonte
1
que tal passar diretamente myValue como um parâmetro para a função? Eu prefiro ter uma chamada explícita com param do que depender de globais; no entanto, não sou muito interessado em javascript, então posso estar perdendo alguns aspectos importantes de ter um global.
BigMike
@BigMike: Certamente aceitável. O método que apresentei acima simplesmente torna a variável disponível para várias funções simultaneamente, mas usar parâmetros é tão bom quanto.
Joel Etherton
obrigado pela clarificação. Seria ótimo ter algum tipo de versão de objeto js do modelo automaticamente (via Atributos na classe de modelo seria ótimo), isso apenas adicionaria um padrão e uma solução de variável totalmente ciente de namespace. Acho que o grande problema seria como injetar o código no html gerado e enviado para o navegador (diretamente da tag <script>). Acho que vou fazer alguns experimentos sobre isso assim que meu projeto atual terminar.
BigMike
@BigMike: Isso deve ser bastante fácil de realizar usando a classe DataContractJsonSerializer ( msdn.microsoft.com/en-us/library/… ). Isso criaria uma versão JSON de sua classe que poderia ser analisada na visualização.
Joel Etherton
4

Provavelmente, essa não é a abordagem certa. Considerando a separação de interesses. Você deve ter um data injectorem sua JavaScriptclasse e que na maioria dos casos são dados JSON.

Crie um arquivo JS em sua scriptpasta e adicione esta referência ao seuView

<script src="@Url.Content("~/Scripts/yourJsFile.js")" type="text/javascript"></script>

Agora, considere uma JavaScriptclasse literal em seu yourJsFile.js:

var contentSetter = {
    allData: {},
    loadData: function (data) {
        contentSetter.allData = eval('(' + data + ')');
    },
    setContentA: function () {
        $("#contentA").html(allData.contentAData);
    },
    setContentB: function () {
        $("#contentB").html(allData.contentAData);
    }
};

Também declara uma classe

public class ContentData
{
    public string ContentDataA { get; set }
    public string ContentDataB { get; set }
}

Agora, Actionfaça isso:

public ActionResult Index() {
    var contentData = new ContentData();
    contentData.ContentDataA = "Hello";
    contentData.ContentDataB = "World";
    ViewData.Add("contentData", contentData);
}

E do seu ponto de vista:

<div id="contentA"></div>
<div id="contentB"></div>

<script type="text/javascript">
    contentSetter.loadData('@Json.Encode((ContentData) ViewData["contentData"])');
    contentSetter.setContentA();
    contentSetter.setContentB();
</script>
Abdul Munim
fonte
Agradável! mas eu acho muito complicado ... o que você achou da minha resposta? stackoverflow.com/questions/7902213/… . a propósito, você tem erro de copiar e colar em setContentB que você escreveu contentAData. obrigado!
gdoron está apoiando Monica em
1
@gdoron Acredite em mim, gerenciar classes de JS e considerar a separação é um salva-vidas quando você tem um grande projeto
Abdul Munim
2

Eu costumo embrulhar o JS precisando de acesso às propriedades do modelo, nas funções e depois passar o @something na view. Por exemplo

<script type="text/javascript">
function MyFunction(somethingPresentInTheView) {
  alert(somethingPresentInTheView);
}
</script>

na visualização, adiciono a invocação de função via (apenas um exemplo):

<input type='button' onclick="MyFunction('@Model.PropertyNeeded')" />
BigMike
fonte
1

Acho que você está preso em ter que colocar esse código JS no View. O analisador Razor, até onde eu sei, não vai olhar para arquivos .js, portanto, qualquer coisa que você tiver que use @não funcionará. Além disso, como você percebeu, o próprio Javascript não gosta desse @caractere rondando sem motivo, a não ser, digamos, em uma string.

Jason Evans
fonte