asp.net-mvc: js dosyasında razor '@' sembolü


90

Ajax URL'si için C # işlevini .csHtmlkullanan bir javascript işlevine sahip bir -razor dosyam var @Url.Content.
Bu işlevi .jsbenim görüşümden referans verilen bir dosyaya taşımak istiyorum .

Sorun şu ki, javascript @sembolü "bilmiyor" ve C # kodunu ayrıştırmıyor. Dosyalara "@" simgeli görünümden
başvurmanın bir yolu var mı .js?


Yanıtlar:


87

HTML5 data-*özelliklerini kullanabilirsiniz . Bir div gibi bir DOM öğesi tıklandığında bir eylem gerçekleştirmek istediğinizi varsayalım. Yani:

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

ve daha sonra, ayrı javascript dosyanızda DOM ile göze çarpmadan çalışabilirsiniz:

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

Bu şekilde, javascript dosyalarınızda herhangi bir sunucu tarafı etiketine ihtiyaç duymadan, biçimlendirme ve komut dosyası arasında saf bir ayrım yapabilirsiniz.


Teşekkürler. Birden fazla değer için baş ağrısı olabileceğini düşünüyorum. Öncelikle sorunumu çözebileceğimi düşündüm ama bunu denedikten sonra kodumda çok fazla tavsiye buldum ve başka bir yol bulmaya karar verdim.
QMaster

19

Nuget'te bunu yapan bir jilet motoru buldum! Anlam @sözdizimini çözer !
Adı RazorJS .

Nuget paketi


2016 Güncellemesi:
Paket 5 yıldır güncellenmedi ve proje sitesi bağlantısı kesildi. İnsanlara artık bu kütüphaneyi kullanmalarını önermiyorum.



İlk bağlantı koptu
Memet Olsen

@MemetOlsen, gerçekten üzgünüm ama bir kopyasını bulamıyorum, bu yüzden kaldırdım :(
gdoron Monica'yı destekliyor

@gdoron, sorun değil. Sadece ölü bağlantı hakkında bilgi vermek istedim. Sizin de belirttiğiniz gibi, paket 5 yıldır güncellenmedi, bu yüzden onu kullanmak muhtemelen kötü bir fikirdir.
Memet Olsen

10

Tek yönSorunu çözmenin şudur:

Görünüme javascript işlevleriyle kısmi bir görünüm ekleme.
Bu şekilde @sembolü kullanabilirsiniz ve tüm javascriptişlevleriniz görünümden ayrılır.


9

İki seçeneğiniz var:

  • Değeri parametre olarak kullanın işlevde ve görünümde bağlantı kurun
  • Bir ad alanı oluşturun (JS'de kötü uygulama olarak kabul edilen genel düzey değişkeni yerine) ve bu değeri sayfanın en üstünde ayarlayın ve ardından js'nizde kullanın

Örneğin:

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

Ve sonra kendi görüşünüze göre ayarlayın:

MyCompany.MyProject.MyVariable = @....

GÜNCELLEME

Kaplin yüzünden hiçbirinin iyi olmadığını merak edebilirsiniz, bu doğru, js ve görüntüyü birleştiriyorsunuz. Bu nedenle komut dosyalarının çalıştıkları konumdan habersiz olmaları gerekir, bu nedenle bu, dosyaların optimum olmayan bir şekilde düzenlenmesinin bir belirtisidir.

Her neyse, bir görünüm motoru oluşturmak ve js dosyalarını jilete karşı çalıştırmak ve sonuçları geri göndermek için üçüncü bir seçenek var. Bu daha temizdir ancak çok daha yavaştır, bu nedenle de önerilmez.


1
+1 İlk yöntemi yapıyorum. İhtiyacınız olan tüm verileri ileten görünümünüzden bir başlatma işlevi çağırın.
Richard Dalton

Teşekkürler, ikinci yaklaşım, görünüm ve js dosyası arasında kötü bir bağlantı değil mi? Daha iyi bir yolun var mı?
gdoron

İkisi de birleşiyor. Oluşturmadan önce js dosyalarını işlemek için bir görünüm motoru yazmadıkça ayırmanın bir yolu yoktur. Güncellemelerime bakın.
Aliostad


İyi görünüyor. + 1'im. Kısmi veya tam görünüm, hiçbir şeyi değiştirmez. Hepsi js ile birleştirme görünümüdür.
Aliostad

7

@Değişkeni .js dosyanıza almak için genel bir değişken kullanmanız ve bu değişkenin değerini, o .js dosyasından yararlanan mvc görünümünden ayarlamanız gerekir.

JavaScript dosyası:

var myValue;

function myFunc() {
  alert(myValue);
}

MVC Görünüm dosyası:

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

Görünüm tarafından değer ayarlandıktan SONRA işlevinize yapılan tüm çağrıların gerçekleştiğinden emin olun.


1
işleve bir parametre olarak doğrudan myValue aktarmaya ne dersiniz? Globallere güvenmektense param ile açık arama yapmayı tercih ederim, ancak javascript'e pek hevesli olmadığım için global olmanın bazı önemli yönlerini kaçırıyor olabilirim.
BigMike

@BigMike: Kesinlikle kabul edilebilir. Yukarıda ortaya koyduğum yöntem, değişkeni aynı anda birden fazla işlev için kullanılabilir hale getirir, ancak parametreleri kullanmak da aynı derecede iyidir.
Joel Etherton

açıklama için teşekkürler. Modelin bir tür js nesnesi sürümüne otomatik olarak sahip olmak harika olurdu (model sınıfındaki Öznitelikler aracılığıyla harika olacak), bu sadece bir desen ve tamamen ad alanına duyarlı bir değişken çözümü ekleyecektir. Sanırım en büyük sorun, tarayıcıya gönderilen (doğrudan <script> etiketi aracılığıyla) oluşturulan html'deki kodun nasıl enjekte edileceğidir. Sanırım mevcut projem biter bitmez bu konuda bazı deneyler yapacağım.
BigMike

@BigMike: DataContractJsonSerializer sınıfını ( msdn.microsoft.com/en-us/library/… ) kullanarak bunu başarmak oldukça kolay olmalıdır . Sınıfınızın, görünüme ayrıştırılabilecek bir JSON sürümünü oluşturur.
Joel Etherton

4

Muhtemelen bu doğru yaklaşım değildir. Endişelerin ayrılması düşünülüyor. Bir olmalıdır data injectorsenin üzerinde JavaScriptsınıf ve verilerdir çoğu durumda olanJSON .

scriptKlasörünüzde bir JS dosyası oluşturun ve bu referansıView

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

Şimdi, JavaScriptsizin için gerçek bir sınıf düşünün yourJsFile.js:

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

Ayrıca bir sınıf ilan edin

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

Şimdi, sizden şunu yapın Action:

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

Ve size göre:

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

<script type="text/javascript">
    contentSetter.loadData('@Json.Encode((ContentData) ViewData["contentData"])');
    contentSetter.setContentA();
    contentSetter.setContentB();
</script>

Güzel! ama bence çok karmaşık ... cevabım hakkında ne düşünüyorsun? stackoverflow.com/questions/7902213/… . bu arada setContentB'de contentAData yazdığınız kopyala yapıştır hatası alıyorsunuz. teşekkür!
gdoron, Monica'yı

1
@gdoron İnan bana, JS sınıflarını yönetmek ve ayrılığı düşünmek, büyük bir projeniz olduğunda hayat kurtarıcıdır
Abdul Munim


2

Genellikle işlevlerde model özelliklerine erişime ihtiyaç duyan JS'yi sararım ve ardından görünümde @something'i geçiririm. Örneğin

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

görünümde işlev çağrısı ekliyorum (sadece bir örnek):

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

1

Sanırım bu JS kodunu Görünüm'e koymak zorunda kaldığınızı düşünüyorum. Razor ayrıştırıcısı, bildiğim kadarıyla, .js dosyalarına bakmayacaktır, bu nedenle kullandığınız hiçbir şey @çalışmayacaktır. PLus, sizin de fark ettiğiniz gibi, Javascript bu @karakterin sebepsiz yere ortalıkta dolaşmasından hoşlanmıyor , mesela bir dizede.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.