มีวิธีการใน Vue ปฏิกิริยาหรือไม่?


9

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

  • ฉันพยายามตอบคำถามนี้และได้รับการบอกหลายครั้งว่าไม่เป็นเช่นนั้น
  • คำตอบที่ยอมรับได้ที่นี่ระบุว่า "[วิธีการ] จะได้รับการประเมินเมื่อคุณเรียกอย่างชัดเจนเท่านั้น"

ฉันค้นหาเอกสารและฉันไม่เห็นอะไรชัดเจนอย่างเหลือเชื่อ

หากพวกมันไม่ได้เกิดปฏิกิริยาทำไมตัวอย่างนี้ถึงใช้งานได้?

<ul>
  <li v-for="animal in animals" :key="animal.id">
    <span v-if="isAwesome(animal)">{{ animal.name }}</span>
  </li>
</ul>
export default {
  data() {
    return {
      awesomeAnimalIds: [],
      animals: [
        { id: 1, name: 'dog' },
        { id: 5, name: 'cat' },
        { id: 9, name: 'fish' },
      ],
    };
  },
  created() {
    setTimeout(() => {
      this.awesomeAnimalIds.push(5);
    }, 1000);
    setTimeout(() => {
      this.awesomeAnimalIds.push(9);
    }, 2000);
  },
  methods: {
    isAwesome(animal) {
      return this.awesomeAnimalIds.includes(animal.id);
    },
  },
};

ฉันจะจริงๆชอบที่จะมีคำตอบที่ชัดเจนและความพึงพอใจที่ชุมชนนี้สามารถดูได้ที่


Great คำถาม - ไม่แน่ใจว่ามีคำตอบ "เป็นทางการ" ที่แสดงถึงความเป็นจริง!
ไทเลอร์

คำตอบ:


4

ขึ้นอยู่กับการติดตามการเปลี่ยนแปลงจากเอกสารนี่คือสิ่งที่เกิดขึ้น:

แผนภาพวัฏจักรปฏิกิริยาของ Vue

  1. Watcher พิเศษถูกสร้างขึ้นสำหรับอินสแตนซ์ของส่วนประกอบเพื่อพิจารณาว่าเมื่อใดที่จำเป็นต้องแสดงผลซ้ำ

  2. Vue แปลงคุณสมบัติทั้งหมดของdataเป็น getters และ setters

get animals() {
  // Add dependency: potentially trigger a re-render if animals updates
  ...
}
set animals() {
  // Notify the watcher that animals has been updated
  ...
}
get awesomeAnimalIds() {
  // Add dependency: potentially trigger a re-render if awesomeAnimalIds updates
  ...
}
set awesomeAnimalIds() {
  // Notify the watcher that awesomeAnimalIds has been updated
  ...
}
  1. เทมเพลตถูกสร้างการแสดงผล ในระหว่างการเรนเดอร์จะมีการเรียกไปยังisAwesomeจากเทมเพลต
  2. ในเนื้อความของisAwesomeผู้ทะเยอทะยานที่awesomeAnimalIdsถูกเรียก
  3. ตะบองกำหนดพึ่งพาการด้านการawesomeAnimalIdsdata
  4. หลังจากหมดเวลาawesomeAnimalIdsได้รับการอัปเดตซึ่งจะเรียกใช้ตัวawesomeAnimalIdsตั้งค่า
  5. เนื่องจากเทมเพลตขึ้นอยู่กับdataฟิลด์ที่ได้รับการแจ้งเตือนจึงมีการทริกเกอร์การแสดงผลซ้ำ
  6. ทำซ้ำขั้นตอน (3)

จากตัวอย่างนี้และด้านบนเราสามารถสรุปได้ดังนี้:

การเรียกเมธอดที่สร้างจากเท็มเพลตจะสร้างการพึ่งพาแบบโต้ตอบบนชุดย่อยของdataฟิลด์ที่ใช้ในการเรียกเมธอด หากมีการอัพเดทฟิลด์พื้นฐานมันจะทริกเกอร์การแสดงผลองค์ประกอบอีกครั้ง

มีความเข้าใจผิดทั่วไปว่าวิธีการ "เรียกใช้เพียงครั้งเดียว" หรือ "ไฟและลืม" เมื่อเรียกจากแม่แบบ นี้ชัดเจนไม่เสมอกรณีเพราะวิธีการสามารถสร้างการพึ่งพาปฏิกิริยา

ดังนั้นเมื่อไหร่เราจึงควรใช้คุณสมบัติที่คำนวณได้กับวิธีการ?

ดูในส่วนคู่มือเกี่ยวกับคอมพิวเตอร์แคชเทียบกับวิธีการ นี่คือสิ่งที่ฉันจะทำ:

  • คุณสมบัติที่คำนวณได้จะประเมินค่าใหม่เมื่อการอ้างอิงปฏิกิริยาเปลี่ยนไป นั่นคือใช้แคชเพื่อเพิ่มประสิทธิภาพ
  • คุณสมบัติที่คำนวณได้ควรปราศจากผลข้างเคียง เช่นคุณไม่ควรโทรfetchจากพวกเขา
  • ต้องการคุณสมบัติที่คำนวณได้เสมอไปหากเป็นไปได้ด้วยเหตุผลด้านประสิทธิภาพ
  • ใช้วิธีการถ้าคุณมีผลข้างเคียงหรือถ้าคุณต้องการผ่านการโต้แย้ง (ดังที่เห็นในคำถามเดิม)

คำอธิบายที่ชัดเจนดีขอบคุณ
Ackroydd

4

ไม่วิธีการนี้ไม่เกิดปฏิกิริยา ข้อมูลเท่านั้นที่สามารถตอบสนองใน Vue

แต่มันเป็นสิ่งสำคัญที่จะเข้าใจว่า Vue ทำงานอย่างไร ...

  1. Vue จะนำเทมเพลตของคุณรวบรวมไปยังฟังก์ชั่นการเรนเดอร์และเรียกใช้ฟังก์ชั่นเรนเดอร์
  2. ในขณะที่ฟังก์ชั่นการเรนเดอร์กำลังทำงาน Vue จะตรวจสอบdata()สมาชิกทั้งหมด(จะทำเช่นนี้ตลอดเวลาไม่เพียง แต่ในช่วงการเรนเดอร์ที่ 1) หากเข้าถึงข้อมูลใด ๆ ระหว่างการแสดงผล Vue จะรู้ว่าเนื้อหาของสมาชิกข้อมูลนี้มีผลต่อผลลัพธ์ของการแสดงผล
  3. Vue ใช้ความรู้ที่รวบรวมในขั้นตอนที่ 2 เมื่อใดก็ตามที่สมาชิกข้อมูล "แตะ" ในระหว่างการแสดงผลการเปลี่ยนแปลงก็รู้ว่าการแสดงผลใหม่ควรเกิดขึ้นและทำสิ่ง ...

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


1

นี่เป็นกรณีที่น่าสนใจมาก

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

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

ฉันทำการทดลอง ฉันเพิ่มวิdivไปแต่ละลูปที่สร้างหมายเลขสุ่มเมื่อสร้าง

<li v-for="animal in animals" :key="animal.id">
        <div>{{ random() }}</div>
        <span v-if="isAwesome(animal)">{{ animal.name }}</span>
</li>

...

random() {
      return Math.random();
}

และสิ่งที่ฉันเห็นคือทุกครั้งที่มีการใส่รหัสใหม่เข้าไปในอาร์เรย์ตัวเลขสุ่มทั้งหมดจะเปลี่ยนไป นี่คือกุญแจสำคัญในการเข้าใจว่าทำไม "ดูเหมือน" ราวกับว่าวิธีการisAwesomeมีปฏิกิริยา

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

ดังนั้นเพื่อตอบคำถามของคุณ isAwesomeไม่ได้ตอบสนองมันเป็นเพียงภาพลวงตาที่สร้างขึ้นโดยการเรนเดอร์ของลูปอีกครั้ง


1
มันเป็นความจริงสำหรับคุณสมบัติที่สังเกตได้ในส่วนประกอบ (prop / data / computed) เมื่อใดก็ตามที่พวกเขาเปลี่ยนมันจะก่อให้เกิดupdateซึ่งก่อให้เกิดre-renderและเรียกวิธีการใด ๆ ที่ถูกผูกไว้ในแม่แบบ
Ohgodwhy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.