asp.net-mvc: สัญลักษณ์ '@' มีดโกนในไฟล์ js


90

ฉันมี.csHtmlไฟล์ -razor ที่มีฟังก์ชันจาวาสคริปต์ที่ใช้@Url.Contentฟังก์ชัน C # ภายในสำหรับ URL ของ ajax
ฉันต้องการย้ายฟังก์ชันนั้นไปยัง.jsไฟล์ที่อ้างอิงจากมุมมองของฉัน

ปัญหาคือจาวาสคริปต์ไม่ "รู้" @สัญลักษณ์และไม่แยกวิเคราะห์รหัส C #
มีวิธีอ้างอิง.jsไฟล์จากมุมมองที่มีสัญลักษณ์ "@" หรือไม่?


2
บางทีนี่อาจช่วยได้ (ดูคำตอบ) stackoverflow.com/questions/7892793/ajax-succes-function
Andriy Khrystyanovich

คำตอบ:


87

คุณสามารถใช้data-*แอตทริบิวต์HTML5 สมมติว่าคุณต้องการดำเนินการบางอย่างเมื่อมีการคลิกองค์ประกอบ DOM บางส่วนเช่น div ดังนั้น:

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

จากนั้นในไฟล์จาวาสคริปต์แยกต่างหากของคุณคุณสามารถทำงานกับ DOM ได้อย่างสงบเสงี่ยม:

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

ด้วยวิธีนี้คุณสามารถแยกกันอย่างชัดเจนระหว่างมาร์กอัปและสคริปต์โดยที่คุณไม่ต้องใช้แท็กฝั่งเซิร์ฟเวอร์ในไฟล์จาวาสคริปต์ของคุณ


ขอบคุณ. ฉันคิดว่าค่าหลายค่าอาจเป็นเรื่องน่าปวดหัว ประการแรกฉันคิดว่ามันสามารถแก้ปัญหาของฉันได้ แต่หลังจากทดลองใช้ฉันพบว่ามีผู้อ้างอิงจำนวนมากในโค้ดของฉันและตัดสินใจที่จะหาวิธีอื่น
QMaster

19

ฉันเพิ่งพบเครื่องมือมีดโกนใน nuget ที่ทำได้! ความหมายแก้@ไวยากรณ์!
มันชื่อRazorJS RazorJS

Nugetแพคเกจ


การอัปเดตปี 2559:
แพ็กเกจไม่ได้รับการอัปเดตเป็นเวลา 5 ปีและลิงก์ไซต์โครงการไม่สามารถใช้งานได้ ฉันไม่แนะนำให้คนอื่นใช้ห้องสมุดนี้อีกต่อไป


คุณสามารถตรวจสอบสิ่งนี้ได้หรือไม่? stackoverflow.com/questions/27702322/…
A Coder

ลิงค์แรกเสีย
Memet Olsen

@MemetOlsen ขอโทษจริงๆ แต่ฉันไม่พบสำเนาของมันดังนั้นฉันจึงลบออก :(
gdoron สนับสนุน Monica

@gdoron ไม่มีปัญหา ฉันแค่อยากจะแจ้งให้คุณทราบเกี่ยวกับลิงก์ที่ตายแล้ว ตามที่คุณระบุไว้แพ็คเกจไม่ได้รับการอัปเดตเป็นเวลา 5 ปีดังนั้นจึงเป็นความคิดที่ดีที่จะใช้ต่อไป
Memet Olsen

10

วิธีหนึ่งในการแก้ไขปัญหาคือ:

การเพิ่มมุมมองบางส่วนด้วยฟังก์ชันจาวาสคริปต์ในมุมมอง
ด้วยวิธีนี้คุณสามารถใช้@สัญลักษณ์และjavascriptฟังก์ชันทั้งหมดของคุณจะแยกออกจากมุมมอง


9

คุณมีสองทางเลือก:

  • ใช้ค่าเป็นพารามิเตอร์ในฟังก์ชันและวางสายในมุมมอง
  • สร้างเนมสเปซ (แทนตัวแปรระดับสาธารณะซึ่งถือว่าเป็นการปฏิบัติที่ไม่ดีใน JS) และตั้งค่านี้ที่ด้านบนสุดของเพจจากนั้นใช้ใน js ของคุณ

ตัวอย่างเช่น:

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

จากนั้นในมุมมองของคุณให้ตั้งค่า:

MyCompany.MyProject.MyVariable = @....

อัปเดต

คุณอาจสงสัยว่าไม่มีอะไรดีเพราะการมีเพศสัมพันธ์มันเป็นเรื่องจริงคุณกำลัง coupling js และ view นั่นคือเหตุผลที่สคริปต์ต้องถูกลบเลือนไปยังตำแหน่งที่รันอยู่ดังนั้นจึงเป็นอาการของการจัดระเบียบไฟล์ที่ไม่เหมาะสม

อย่างไรก็ตามมีตัวเลือกที่สามในการสร้างเอนจิ้นมุมมองและเรียกใช้ไฟล์ js กับมีดโกนและส่งผลลัพธ์กลับ วิธีนี้สะอาดกว่า แต่ช้ากว่ามากจึงไม่แนะนำเช่นกัน


1
+1 ฉันทำวิธีแรก เรียกใช้ฟังก์ชันการเริ่มต้นจากมุมมองของคุณที่ส่งผ่านข้อมูลทั้งหมดที่คุณต้องการ
Richard Dalton

ขอบคุณแนวทางที่สองไม่ใช่การเชื่อมต่อที่ไม่ดีระหว่างมุมมองและไฟล์ js? คุณมีวิธีที่ดีกว่านี้ไหม
gdoron รองรับ Monica

ทั้งสองมีเพศสัมพันธ์ ไม่มีวิธีคลายการเชื่อมต่อเว้นแต่คุณจะเขียน view engine เพื่อประมวลผลไฟล์ js ก่อนแสดงผล ดูการอัปเดตของฉัน
Aliostad

แล้ววิธีนี้ที่ฉันแนะนำล่ะ? stackoverflow.com/questions/7902213/…
gdoron สนับสนุน Monica

ฟังดูโอเค +1 ของฉัน ไม่ว่าจะเป็นมุมมองบางส่วนหรือทั้งหมดไม่เปลี่ยนแปลงอะไร เป็นมุมมองการมีเพศสัมพันธ์กับ js ทั้งหมด
Aliostad

7

เพื่อให้ได้ไฟล์ @ตัวแปรลงในไฟล์. js ของคุณคุณจะต้องใช้ตัวแปรส่วนกลางและตั้งค่าของตัวแปรนั้นจากมุมมอง mvc ที่ใช้ประโยชน์จากไฟล์. js นั้น

ไฟล์ JavaScript:

var myValue;

function myFunc() {
  alert(myValue);
}

MVC ดูไฟล์:

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

ตรวจสอบให้แน่ใจว่าการเรียกใช้ฟังก์ชันของคุณเกิดขึ้นหลังจากมุมมองกำหนดค่าแล้ว


1
สิ่งที่เกี่ยวกับการส่ง myValue โดยตรงเป็นพารามิเตอร์ไปยังฟังก์ชัน? ฉันชอบที่จะโทรอย่างชัดเจนด้วยพารามิเตอร์มากกว่าการใช้ globals แต่ฉันไม่ค่อยชอบใช้จาวาสคริปต์ดังนั้นฉันอาจพลาดสิ่งสำคัญบางอย่างในการมีโกลบอล
BigMike

@BigMike: ยอมรับได้แน่นอน วิธีที่ฉันกล่าวไว้ข้างต้นทำให้ตัวแปรพร้อมใช้งานหลายฟังก์ชันพร้อมกัน แต่การใช้พารามิเตอร์ก็ทำได้ดีเช่นกัน
Joel Etherton

ขอบคุณสำหรับความกระจ่าง จะเป็นการดีที่จะมีโมเดลอ็อบเจ็กต์ js บางประเภทโดยอัตโนมัติ (ผ่านแอตทริบิวต์ในคลาสโมเดลจะดีมาก) สิ่งนี้จะเพิ่มรูปแบบและโซลูชันตัวแปรที่รับรู้เนมสเปซแบบเต็ม ฉันเดาว่าปัญหาใหญ่น่าจะเป็นวิธีการฉีดโค้ดใน html ที่สร้างขึ้นที่ส่งไปยังเบราว์เซอร์ (โดยตรงจากแท็ก <script>) ฉันคิดว่าฉันจะทำการทดลองบางอย่างเกี่ยวกับเรื่องนี้ทันทีที่โครงการปัจจุบันของฉันสิ้นสุดลง
BigMike

@BigMike: สิ่งนี้น่าจะทำได้ง่ายพอสมควรโดยใช้คลาส DataContractJsonSerializer ( msdn.microsoft.com/en-us/library/… ) มันจะสร้างคลาสของคุณในเวอร์ชัน JSON ที่สามารถแยกวิเคราะห์ในมุมมองได้
โจเอลอีเธอร์ตัน

4

อาจไม่ใช่แนวทางที่ถูกต้อง พิจารณาแยกความกังวล คุณควรมีdata injectorในJavaScriptชั้นเรียนของคุณและในกรณีส่วนใหญ่ข้อมูลคือJSONชั้นและที่เป็นในกรณีส่วนใหญ่ข้อมูล

สร้างไฟล์ JS ในscriptโฟลเดอร์ของคุณและเพิ่มการอ้างอิงนี้ในไฟล์View

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

ตอนนี้ให้พิจารณาไฟล์ JavaScriptคลาสตามตัวอักษรในyourJsFile.js:

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

ประกาศคลาสด้วย

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

ตอนนี้จากไฟล์ Actionทำสิ่งนี้:

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

และจากมุมมองของคุณ:

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

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

ดี! แต่ฉันคิดว่ามันซับซ้อนเกินไป ... คุณคิดยังไงกับคำตอบของฉัน? stackoverflow.com/questions/7902213/… . โดยวิธีที่คุณมีข้อผิดพลาดในการคัดลอกวางใน setContentB ที่คุณเขียน contentAData ขอบคุณ!
gdoron รองรับ Monica

1
@gdoron เชื่อฉันเถอะการจัดการชั้นเรียน JS และการพิจารณาแยกกันเป็นตัวช่วยชีวิตเมื่อคุณมีโปรเจ็กต์ขนาดใหญ่
อับดุลมูนิม

4

ฉันเพิ่งเขียนบล็อกเกี่ยวกับหัวข้อนี้: การสร้างไฟล์ JavaScript ภายนอกโดยใช้มุมมองมีดโกนบางส่วนใช้บางส่วนมีดโกนชม

วิธีแก้ปัญหาของฉันคือใช้แอตทริบิวต์ที่กำหนดเอง ( ExternalJavaScriptFileAttribute) ซึ่งแสดงผลมุมมอง Razor บางส่วนตามที่เป็นอยู่แล้วส่งคืนโดยไม่มี<script>แท็กรอบข้าง นั่นทำให้เป็นไฟล์ JavaScript ภายนอกที่ถูกต้อง


2

ฉันมักจะตัด JS ที่ต้องการเข้าถึงคุณสมบัติของโมเดลในฟังก์ชันจากนั้นส่ง @something ในมุมมอง ตัวอย่างเช่น

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

ในมุมมองฉันเพิ่มการเรียกใช้ฟังก์ชันผ่าน (เพียงตัวอย่าง):

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

1

ฉันคิดว่าคุณติดอยู่กับการต้องใส่โค้ด JS นั้นใน View เท่าที่ฉันรู้ Razor parser จะไม่ดูไฟล์. js ดังนั้นสิ่งที่คุณมี@จะใช้ไม่ได้ PLus ตามที่คุณได้เห็น Javascript เองไม่ชอบ@อักขระนี้ที่ห้อยอยู่รอบ ๆ โดยไม่มีเหตุผลอื่น ๆ พูดเป็นสตริง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.