เด็ก LWC แคชข้อมูลเก่าโดยการสอบถาม @wired Apex ผู้ปกครองไม่สามารถ refreshApex () บนลูกโดย querySelector () เนื่องจากเด็กถูกซ่อนโดย if: true จะทำอย่างไร?

Aug 17 2020

โครงสร้างแอปโดยย่อ (ดูภาพ): รายการส่วนประกอบย่อยของ "รายการโฆษณา" ทางด้านขวา (เพียง 1601xCC5Bulk เดียวในรูปนี้) คอนเทนเนอร์ที่มีพาเลททางด้านซ้าย << จัดสรร btn เปิดโมดอลลูกอื่นด้วยฟอร์ม (ถ้า: จริง .. ) รายการเลือกของแบบฟอร์มนี้ใช้ @wire apex เพื่อแสดงเฉพาะพาเลทที่ว่างเปล่าดังนั้นจึงรีเฟรชโดยตัวควบคุมของฟอร์มเองหลังจาก DML

ปัญหาเกิดขึ้นเมื่อเปลี่ยนจำนวนพาเลทโดยผู้ปกครองเช่นใช้ปุ่มสีแดงทางด้านขวา DML นี้จะลบคอนเทนเนอร์พร้อมกับพาเลท

แต่ถ้าเปิดฟอร์มที่ซ่อนไว้อีกครั้งค่าพาเลทเก่ายังคงแสดงเป็นค่ารายการเลือกฉันต้องรีเฟรชข้อมูลนั้น แต่ลูกนี้ถูกซ่อนไว้จึงไม่สามารถเข้าถึงได้ตามมาตรฐาน: parent -> querySelector (child2) .method ()

  • ขออภัยสำหรับคำถาม newb: มีวิธีเข้าถึงวิธีการของส่วนประกอบที่ซ่อนอยู่หรือไม่?
  • ฉันยังคิดที่จะย้ายการเรียกไปยัง Apex query ขึ้นไปยังองค์ประกอบหลัก (ง่ายต่อการทริกเกอร์) จากนั้นส่งต่อไปยังโมดอลลูกเป็นอาร์กิวเมนต์ api ดังนั้นเมื่อโมดอลปรากฏขึ้นมันจะได้รับข้อมูลที่อัปเดต รู้สึกผิดนิดหน่อยที่ต้องทำเพราะพ่อแม่ยกภาระให้ลูก (บางทีฉันคิดผิด)
  • ฉันยังคิดที่จะใช้ renderedCallback ของเด็กสำหรับแบบสอบถาม apex นั้น แต่กลัวการวนซ้ำการแสดงผลที่ไม่มีที่สิ้นสุด?
  • การปิดใช้งานการแคชออร่าเอเพ็กซ์จะเป็นสิ่งที่ดี แต่ดูเหมือนจะเป็นไปไม่ได้

นี่คือมาร์กอัปกระดูกเปลือยซึ่งแสดงเฉพาะส่วนที่เกี่ยวข้องทั้งหมด

=== PARENT (มีลูก 2 คน) ===

HTML

<template for:each={lineItems.data} for:item="lineItem">
   <lightning-layout-item key={lineItem.Id} size="12">
     <c-packing-list-line-item-card lineitem={lineItem} onallocatebuttonpress={openAllocationModal}></c-packing-list-line-item-card>
   </lightning-layout-item>
</template>

<template if:true={isLineItemModalOpen}>
     <c-packing-list-allocation-modal recordid={recordId} oncloseallocationmodal={closeAllocModal} onproductallocated={refreshData}></c-packing-list-allocation-modal>    
</template>

JS

openAllocationModal(e) {
        this.editItemId = e.detail;
        this.isLineItemModalOpen = true;
    }
closeAllocModal() {
        this.isLineItemModalOpen = false;
    }

=== เด็ก 1: รายการบรรจุ - รายการ - รายการ - การ์ด === (อันที่อยู่ทางขวาแสดงรายละเอียดสินค้าส่งรหัสไปยังโมดอล)

HTML

<lightning-button variant="brand" label="<< Allocate" data-itemid={lineitem.Id} onclick={openAllocationModal}></lightning-button>

JS

openAllocationModal(e) {
        const selectEvent = new CustomEvent('allocatebuttonpress', { detail: e.target.dataset.itemid });
        this.dispatchEvent(selectEvent);
    }

=== เด็ก 2: โมดอลการจัดสรร (การแสดงเงื่อนไข) ===

HTML

<template if:true={showInsertButton}>
                <button class="slds-button slds-button_brand" onclick={handleAllocationInsert}>Insert</button>
            </template>

JS (คุณอาจสนใจเฉพาะ closeModal () {} ส่วนอื่น ๆ ก็เพื่อความสมบูรณ์)

handleAllocationInsert() {
[...]
createRecord(recordInput)
.then((allocId) => {
  this.showToast('success', 'Success', 'Product Allocated');
  this.handleInsert(this.palletValue);
  this.refreshPallets();
})
.catch((error) => {
  this.showToast('error', 'Error creating record', error.body.message);
  this.closeModal();
});

}

closeModal() {
        // On save parent closes modal
        console.log('closing 1');
        const selectEvent = new CustomEvent('closeallocationmodal');
        this.dispatchEvent(selectEvent);
        this.spinner = false;
    }

    handleInsert(palletValue) {
        // On save parent refreshes container view
        const selectEvent = new CustomEvent('productallocated', {
            detail: this.palletcontainers[palletValue].containerId
        });
        this.dispatchEvent(selectEvent);
        this.closeModal();
    }

คำตอบ

4 sfdcfox Aug 17 2020 at 20:36

ขออภัยสำหรับคำถาม newb: มีวิธีเข้าถึงวิธีการของส่วนประกอบที่ซ่อนอยู่หรือไม่?

ไม่เด็กถูกลบออกจาก DOM ทางกายภาพและไม่มีอยู่เลย (ยกเว้นอาจอยู่ในแคชคอมโพเนนต์)

ฉันยังคิดที่จะย้ายการเรียกไปยัง Apex query ขึ้นไปยังองค์ประกอบหลัก (ง่ายต่อการทริกเกอร์) จากนั้นส่งต่อไปยังโมดอลลูกเป็นอาร์กิวเมนต์ api ดังนั้นเมื่อโมดอลปรากฏขึ้นมันจะได้รับข้อมูลที่อัปเดต รู้สึกผิดนิดหน่อยที่ต้องทำเพราะพ่อแม่ยกภาระให้ลูก (บางทีฉันคิดผิด)

นี่เป็นวิธีมาตรฐานมากในการทำเช่นนี้ เด็กเพียงแค่ต้องกังวลเกี่ยวกับการแสดงข้อมูลซึ่งเป็นสิ่งที่ออกแบบมาเพื่อทำ โดยทั่วไปเป็นความคิดที่ดีที่จะรับ / ตั้งค่าข้อมูลในลำดับชั้นขององค์ประกอบให้สูงที่สุดเท่าที่จะทำได้ (แต่ไม่สูงเกินความจำเป็น)

ฉันยังคิดที่จะใช้ renderedCallback ของเด็กสำหรับแบบสอบถาม apex นั้น แต่กลัวการวนซ้ำการแสดงผลที่ไม่มีที่สิ้นสุด?

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

การปิดใช้งานการแคชออร่าเอเพ็กซ์จะเป็นสิ่งที่ดี แต่ดูเหมือนจะเป็นไปไม่ได้

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


สรุปได้ว่าการควบคุมข้อมูลจากผู้ปกครองน่าจะเป็นทางออกที่ง่ายที่สุด นี่เป็นวิธีแก้ปัญหาที่ยอมรับได้โดยทั่วไปในกรณีส่วนใหญ่เนื่องจากโดยทั่วไปแล้วส่วนประกอบย่อยจะทำงานกับข้อมูลที่ได้รับจากผู้ปกครองเท่านั้น ตัวอย่างเช่นlightning-inputไม่ได้ทำอะไรกับเซิร์ฟเวอร์โดยตรง แต่จะสื่อสารการเปลี่ยนแปลงกับผู้ปกครองผ่านเหตุการณ์ เป็นการออกแบบที่เป็นธรรมชาติอย่างสมบูรณ์แบบที่จะใช้

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