asp.net-mvc: simbol pisau cukur '@' di file js


90

Saya memiliki .csHtmlfile -razor dengan fungsi javascript yang menggunakan fungsi @Url.ContentC # di dalamnya untuk URL ajax.
Saya ingin memindahkan fungsi itu ke .jsfile yang direferensikan dari pandangan saya.

Masalahnya adalah bahwa javascript tidak "mengetahui" @simbol tersebut dan tidak mengurai kode C #.
Apakah ada cara untuk mereferensikan .jsfile dari tampilan dengan simbol "@"?


Jawaban:


87

Anda bisa menggunakan data-*atribut HTML5 . Misalkan Anda ingin melakukan beberapa tindakan ketika beberapa elemen DOM seperti div diklik. Begitu:

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

dan kemudian di file javascript terpisah Anda, Anda dapat bekerja secara diam-diam dengan DOM:

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

Dengan cara ini Anda dapat memiliki pemisahan murni antara markup dan skrip tanpa Anda memerlukan tag sisi server apa pun di file javascript Anda.


Terima kasih. Saya pikir untuk beberapa nilai bisa memusingkan. Pertama-tama saya pikir ini dapat menyelesaikan masalah saya tetapi setelah mencobanya, saya menemukan begitu banyak referensi dalam kode saya dan memutuskan untuk mencari cara lain.
QMaster

19

Saya baru saja menemukan mesin silet di nuget yang bisa melakukannya! Arti memecahkan @sintaks!
Namanya adalah RazorJS .

The Nuget paket


Pembaruan 2016:
Paket tidak diperbarui selama 5 tahun, dan tautan situs proyek mati. Saya tidak merekomendasikan orang untuk menggunakan perpustakaan ini lagi.



Tautan pertama rusak
Memet Olsen

@MemetOlsen, sungguh, maaf tapi saya tidak dapat menemukan salinannya, jadi saya menghapusnya :(
gdoron mendukung Monica

@gdoron, tidak masalah. Saya hanya ingin memberi tahu Anda tentang tautan mati. Seperti yang Anda nyatakan, paket tidak diperbarui selama 5 tahun jadi mungkin ide yang buruk untuk tetap menggunakannya.
Memet Olsen

10

Satu arah untuk mengatasi masalah tersebut adalah:

Menambahkan tampilan parsial dengan fungsi javascript ke tampilan.
Dengan cara ini Anda dapat menggunakan @simbol dan semua javascriptfungsi Anda dipisahkan dari tampilan.


9

Anda memiliki dua pilihan:

  • Gunakan nilai sebagai parameter dalam fungsi dan kawat dalam tampilan
  • Buat namespace (bukan variabel tingkat publik yang dianggap praktik buruk di JS) dan setel nilai ini di bagian atas halaman lalu gunakan di js Anda

Sebagai contoh:

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

Dan kemudian dalam tampilan Anda, setel:

MyCompany.MyProject.MyVariable = @....

MEMPERBARUI

Anda mungkin bertanya-tanya tidak ada yang bagus karena penggandengan, memang benar, Anda menggabungkan js dan tampilan. Itulah mengapa skrip harus tidak menyadari lokasi tempat mereka dijalankan sehingga ini adalah gejala organisasi file yang tidak optimal.

Pokoknya ada pilihan ketiga untuk membuat mesin tampilan dan menjalankan file js melawan pisau cukur dan mengirim hasilnya kembali. Ini lebih bersih tapi jauh lebih lambat jadi tidak disarankan juga.


1
+1 Saya melakukan metode pertama. Panggil fungsi inisialisasi dari tampilan Anda dengan meneruskan semua data yang Anda butuhkan.
Richard Dalton

Terima kasih, pendekatan kedua bukanlah penggabungan yang buruk antara view dan file js? Apakah Anda punya cara yang lebih baik?
gdoron mendukung Monica

Keduanya adalah kopel. Tidak ada cara untuk melepaskan sambungan kecuali Anda menulis mesin tampilan untuk memproses file js sebelum rendering. Lihat pembaruan saya.
Aliostad

bagaimana dengan cara yang saya sarankan ini? stackoverflow.com/questions/7902213/…
gdoron mendukung Monica

Kedengarannya oke. +1 saya. Baik tampilan parsial maupun penuh, tidak mengubah apapun. Itu semua tampilan kopling dengan js.
Aliostad

7

Untuk memasukkan @variabel ke dalam file .js Anda, Anda harus menggunakan variabel global dan menetapkan nilai variabel tersebut dari tampilan mvc yang menggunakan file .js tersebut.

File JavaScript:

var myValue;

function myFunc() {
  alert(myValue);
}

MVC Lihat file:

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

Pastikan saja bahwa setiap panggilan ke fungsi Anda terjadi SETELAH nilainya ditetapkan oleh view.


1
bagaimana dengan mengirimkan langsung myValue sebagai parameter ke fungsi? Saya lebih suka memiliki panggilan eksplisit dengan param daripada mengandalkan global, namun saya tidak begitu tertarik pada javascript jadi saya mungkin kehilangan beberapa aspek penting dari memiliki global.
BigMike

@BigMike: Bisa diterima. Metode yang saya kemukakan di atas hanya membuat variabel tersedia untuk beberapa fungsi secara bersamaan, tetapi menggunakan parameter sama baiknya.
Joel Etherton

terima kasih atas klarifikasinya. Akan sangat bagus untuk memiliki semacam versi objek js dari model secara otomatis (melalui Atribut di kelas model akan menjadi hebat), ini hanya akan menambahkan pola dan solusi variabel yang sadar ruang nama sepenuhnya. Saya kira masalah besarnya adalah bagaimana menyuntikkan kode dalam html yang dihasilkan yang dikirim ke browser (langsung melalui tag <script>). Saya pikir saya akan melakukan beberapa eksperimen tentang ini segera setelah proyek saya saat ini selesai.
BigMike

@BigMike: Ini seharusnya cukup mudah dilakukan dengan menggunakan kelas DataContractJsonSerializer ( msdn.microsoft.com/en-us/library/… ). Ini akan membuat versi JSON dari kelas Anda yang dapat diurai ke dalam tampilan.
Joel Etherton

4

Mungkin ini bukan pendekatan yang tepat. Mempertimbangkan pemisahan kekhawatiran. Anda harus memiliki data injectordi JavaScriptkelas Anda dan yang dalam banyak kasus adalah data JSON.

Buat file JS di scriptfolder Anda dan tambahkan referensi ini keView

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

Sekarang, pertimbangkan JavaScriptkelas literal di yourJsFile.js:

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

Juga nyatakan sebuah kelas

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

Sekarang, dari Anda Actionlakukan ini:

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

Dan dari pandangan Anda:

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

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

Bagus! tapi saya pikir itu terlalu rumit ... apa pendapat Anda tentang jawaban saya? stackoverflow.com/questions/7902213/… . omong-omong Anda memiliki kesalahan salin tempel di setContentB yang Anda tulis contentAData. terima kasih!
gdoron mendukung Monica

1
@gdoron Percayalah, mengelola kelas JS dan mempertimbangkan pemisahan adalah penyelamat hidup saat Anda memiliki proyek besar
Abdul Munim


2

Saya biasanya membungkus JS yang membutuhkan akses ke properti model, dalam fungsi, lalu meneruskan @something dalam tampilan. Sebagai contoh

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

dalam tampilan saya menambahkan pemanggilan fungsi melalui (hanya sebuah contoh):

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

1

Saya pikir Anda terjebak dengan harus meletakkan kode JS itu di View. Parser Razor, sejauh yang saya tahu, tidak akan melihat file .js, jadi apa pun yang Anda miliki yang Anda gunakan @tidak akan berfungsi. PLus, seperti yang Anda lihat, Javascript sendiri tidak suka @karakter ini berkeliaran tanpa alasan, selain itu, katakanlah, dalam sebuah string.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.