จะสร้างเทมเพลตโครงสร้าง If-Else ในมุมมองที่มีขอบเขตข้อมูลได้อย่างไร


95

ฉันพบว่าตัวเองใช้สำนวนนี้ในเทมเพลต HTML ที่ใช้ KO อยู่ตลอดเวลา:

<!-- ko if: isEdit -->
<td><input type="text" name="email" data-bind="value: email" /></td>
<!-- /ko -->
<!-- ko ifnot: isEdit -->
<td data-bind="text: email"></td>
<!-- /ko -->

มีวิธีที่ดีกว่า / สะอาดกว่าในการทำเงื่อนไขใน KO หรือมีแนวทางที่ดีกว่าการใช้โครงสร้าง if-else แบบเดิมหรือไม่?

นอกจากนี้ฉันอยากจะชี้ให้เห็นว่า Internet Explorer (IE 8/9) บางเวอร์ชันไม่ได้แยกวิเคราะห์ตัวอย่างข้างต้นอย่างถูกต้อง โปรดดูคำถาม SO นี้สำหรับข้อมูลเพิ่มเติม สรุปโดยย่อคืออย่าใช้ความคิดเห็น (การผูกเสมือน) ภายในแท็กตารางเพื่อรองรับ IE ใช้tbodyแทน:

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>

ใครก็ตามที่ดูสิ่งนี้อาจต้องการติดตามgithub.com/knockout/knockout/issues/962
Brian M. Hunt

คำตอบ:


64

คุณสามารถจัดการโค้ดประเภทนี้ได้หลายวิธี

  • ด้วยการผสมผสาน if / ifnot เหมือนตอนนี้ วิธีนี้ใช้งานได้ดีและไม่ได้ใช้คำฟุ่มเฟือยมากนัก

  • การผูกสวิตช์ / เคสของ Michael Best ( https://github.com/mbest/knockout-switch-case ) ค่อนข้างยืดหยุ่นและช่วยให้คุณจัดการสิ่งนี้ได้อย่างง่ายดายและซับซ้อนมากขึ้น (สถานะมากกว่าจริง / เท็จ)

  • อีกทางเลือกหนึ่งคือการใช้เทมเพลตแบบไดนามิก คุณจะผูกพื้นที่กับเทมเพลตอย่างน้อยหนึ่งเทมเพลตโดยใช้ชื่อเทมเพลตตามที่สังเกตได้ นี่คือโพสต์ที่ผมเขียนเกี่ยวกับหัวข้อนี้ในขณะที่กลับมา: http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html ในสถานการณ์ของคุณอาจมีลักษณะดังนี้:

<td data-bind="template: $root.getCellTemplate"></td>

<script id="cellEditTmpl" type="text/html">
    <input type="text" name="email" data-bind="value: email" />
</script>

<script id="cellTmpl" type="text/html">
    <span data-bind="text: email"></span>
</script>

getCellTemplateฟังก์ชั่นจะอยู่ที่ใดก็ตาม แต่จะได้รับรายการ ($ ข้อมูล) เป็นอาร์กิวเมนต์แรกและจะกลับมาในชื่อของแม่แบบในการใช้งาน


แปลก HTML ของฉันไม่ปรากฏ ยังเพิ่งสังเกตว่าไมเคิลให้คำตอบแบบเดียวกัน
RP Niemeyer

ขอบคุณสำหรับรายการตัวเลือกที่ครอบคลุม ฉันเดาว่ารูปแบบรหัสดั้งเดิมของฉันใช้ได้กับกรณีง่ายๆ ฉันจะตรวจสอบตัวเลือกอื่น ๆ เมื่อจำเป็น
เซ่นชิง

มีวิธีปรับแต่งเทมเพลตให้มากยิ่งขึ้นเช่น "template: data, proppertyName: 'email'" และใน template data-bind = "text: $ data [propertyName]"
Onur Topal

@OnurTOPAL - ใช่ตราบใดที่คุณมีตัวแปรpropertyNameคุณสามารถกำหนดชื่อเทมเพลตแบบไดนามิกได้
RP Niemeyer

44

แนวทางหนึ่งคือการใช้เทมเพลตที่มีชื่อ (ซึ่งสามารถรองรับการส่งผ่านอาร์กิวเมนต์):

<!-- ko template: isEdit() ? 'emailEdit' : 'emailDisplay' --><!-- /ko -->
<script id="emailEdit" type="text/html">
    <td><input type="text" name="email" data-bind="value: email" /></td>
</script>
<script id="emailDisplay" type="text/html">
    <td data-bind="text: email"></td>
</script>

อีกทางเลือกหนึ่งคือใช้ปลั๊กอินสวิตช์ / เคสของฉันซึ่งจะได้ผลดังนี้:

<!-- ko switch -->
    <!-- ko case: isEdit -->
        <td><input type="text" name="email" data-bind="value: email" /></td>
    <!-- /ko -->
    <!-- ko case: $else -->
        <td data-bind="text: email"></td>
    <!-- /ko -->
<!-- /ko -->

ขอบคุณ. ฉันจะคำนึงถึงปลั๊กอินสวิตช์ / เคสเมื่อมีความจำเป็น
เซ่นชิง

2
คุณมีปลั๊กอินที่ดี! จะใช้อันนี้แน่นอน.
Andrew Camilleri 'Kukks'

เทมเพลตที่มีชื่อใช้งานได้ดีและรองรับ if elseif elseif พิมพ์สถานการณ์โดยการซ้อนตัวดำเนินการ terniary

4

เพื่อหลีกเลี่ยงการคำนวณใหม่ของการผูกสิ่งที่น่าพิศวงเมื่อใช้การรวมกันของ if: / ifnot: คุณสามารถใช้ร่วมกับโครงสร้าง 'with:'

    <!-- ko with: $data.DoSomePerformanceCriticalWork($data.SomeParameter()) -->
        <!-- ko if: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
        <!-- ko ifnot: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
    <!-- /ko -->

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