เรียกการตรวจจับการเปลี่ยนแปลงด้วยตนเองในเชิงมุม


387

Mode(): stringผมเขียนเป็นองค์ประกอบเชิงมุมที่มีคุณสมบัติ

ฉันต้องการที่จะสามารถตั้งค่าคุณสมบัตินี้โดยทางโปรแกรมไม่ได้ตอบสนองต่อเหตุการณ์ใด ๆ

ปัญหาคือในกรณีที่ไม่มีเหตุการณ์ของเบราว์เซอร์การเชื่อมโยงแม่แบบ{{Mode}}จะไม่ปรับปรุง

มีวิธีที่จะทริกเกอร์การตรวจจับการเปลี่ยนแปลงนี้ด้วยตนเองหรือไม่?

คำตอบ:


640

ลองหนึ่งในสิ่งเหล่านี้:

  • ApplicationRef.tick()- คล้ายกับ AngularJS's $rootScope.$digest()- เช่นตรวจสอบโครงสร้างส่วนประกอบแบบเต็ม
  • NgZone.run(callback)- คล้ายกับ$rootScope.$apply(callback)- คือประเมินฟังก์ชันการโทรกลับภายในโซนแองกูลาร์ ฉันคิดว่า แต่ฉันไม่แน่ใจว่าสิ่งนี้จบลงที่การตรวจสอบโครงสร้างส่วนประกอบแบบเต็มหลังจากดำเนินการฟังก์ชันการเรียกกลับ
  • ChangeDetectorRef.detectChanges()- คล้ายกับ$scope.$digest()- เช่นตรวจสอบเฉพาะส่วนนี้และลูก ๆ

คุณสามารถฉีดApplicationRef, NgZoneหรือChangeDetectorRefเข้าองค์ประกอบของคุณ


1
ขอบคุณฉันเลือกใช้วิธีที่ 3 เพื่อไม่ตรวจสอบทุกอย่างเนื่องจากการเปลี่ยนแปลงมีการแปลอย่างเป็นธรรม ฉันควรตรวจสอบตัวเลือกอื่น ๆ เมื่อฉันมีเวลามากขึ้น ตัวเลือกแต่ละตัวมีความหมายหรือไม่?
jz87

36
+1 ChangeDetectorRef.detectChanges()สำหรับ เครื่องมือตรวจสอบถูกยิงก่อนที่คำสั่งของฉันจะอัปเดตค่าของอินพุต
ps2goat

7
ApplicationRef.tick () และ ChangeDetectorRef.detectChanges () จะยังคงอยู่ใน 2.0.0 สุดท้าย
Max Mumford

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

1
ApplicationRef.tick () ช่วยแก้ปัญหาด้วย FireFox v17 (<20)
Dan J

123

ฉันใช้การอ้างอิงคำตอบที่ยอมรับได้และต้องการยกตัวอย่างเนื่องจากเอกสารประกอบของ Angular 2 นั้นอ่านยากมากฉันหวังว่ามันจะง่ายขึ้น:

  1. นำเข้าNgZone:

    import { Component, NgZone } from '@angular/core';
    
  2. เพิ่มไปยังตัวสร้างคลาสของคุณ

    constructor(public zone: NgZone, ...args){}
    
  3. เรียกใช้รหัสด้วยzone.run:

    this.zone.run(() => this.donations = donations)
    

6
คุณควรใส่zone.runรหัสไว้ที่ไหนและตรงdonationsไหน
suku

@suku donations เป็นทรัพย์สินที่คุณต้องการอัปเดตดังนั้นอาจเป็น this.foo = bar zone.run ไปทุกที่ที่คุณต้องการอัพเดทเนื้อหา
Matthew ทางเลือก Meehan

4
ฉันใช้วิธีนี้เพื่อบังคับให้มีการอัปเดตมุมมองเมื่อใช้ document.addEventListener ("Resume", callback)
marcovtwout

71

ฉันสามารถอัปเดตด้วยmarkForCheck ()

นำเข้า ChangeDetectorRef

import { ChangeDetectorRef } from '@angular/core';

ฉีดและยกตัวอย่างมัน

constructor(private ref: ChangeDetectorRef) { 
}

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

this.ref.markForCheck();

นี่คือตัวอย่างที่ markForCheck () ใช้งานได้และ detectChanges () ไม่ทำงาน

https://plnkr.co/edit/RfJwHqEVJcMU9ku9XNE7?p=preview

แก้ไข: ตัวอย่างนี้ไม่ได้แสดงให้เห็นปัญหาอีกต่อไป :( ฉันเชื่อว่ามันอาจจะใช้รุ่น Angular ที่ใหม่กว่าซึ่งมันได้รับการแก้ไข

(กด STOP / RUN เพื่อเรียกใช้อีกครั้ง)


Goo point สำหรับ detectChanges () ไม่ทำงาน ฉันสังเกตเห็นปัญหาเดียวกันและพบว่าใช้งานได้หากการตรวจจับการเปลี่ยนแปลงไม่ใช่ OnPush คงจะดีถ้าได้รับคำอธิบายสำหรับเรื่องนี้ ...
คริสเตียน

2
ดูเหมือนว่า detectChanges ทำงานได้จริงในเครื่องดักฟังหรือไม่ ฉันพลาดอะไรไปรึเปล่า?
Jared_C

1
คุณควรทราบว่า ChangeDetectorRef ใช้งานได้เฉพาะใน Components
kevinius

(!) นี่เป็นตัวอย่างที่ไม่ดีฉันขอโทษ ตัวอย่างไม่แสดงอะไรเลย รายการแรกเพิ่งถูกเขียนทับ เพียงแค่ปรับตัวนับบิต ...
ปีเตอร์ Stegnar

ตัวอย่างนี้ไม่ได้แสดงถึงปัญหาอีกต่อไป :( ฉันเชื่อว่ามันอาจจะใช้เวอร์ชั่นภาษา Angular ที่ใหม่กว่าซึ่งมันได้รับการแก้ไขแล้ว
Nuno Tomas

7

ใน Angular 2+ ให้ลอง @ decor มัณฑนากร

จะช่วยให้การผูกคุณสมบัติที่ดีบางอย่างระหว่างองค์ประกอบหลักและเด็ก

ก่อนอื่นให้สร้างตัวแปรส่วนกลางในพาเรนต์เพื่อเก็บออบเจ็กต์ / คุณสมบัติที่จะถูกส่งไปยังลูก

ถัดไปสร้างตัวแปรโกลบอลในชายด์เพื่อเก็บอ็อบเจ็กต์ / คุณสมบัติที่ส่งผ่านจากพาเรนต์

จากนั้นใน parent html ที่มีการใช้แม่แบบลูกให้เพิ่มสัญกรณ์วงเล็บเหลี่ยมด้วยชื่อของตัวแปรลูกแล้วตั้งค่าให้เท่ากับชื่อของตัวแปรหลัก ตัวอย่าง:

<child-component-template [childVariable] = parentVariable>
</child-component-template>

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

@Input()
public childVariable: any

เมื่อตัวแปรพาเรนต์ของคุณได้รับการอัปเดตควรส่งการอัปเดตไปยังองค์ประกอบย่อยซึ่งจะอัปเดต html

นอกจากนี้หากต้องการเรียกใช้ฟังก์ชันในองค์ประกอบลูกลองดูที่ ngOnChanges


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

ฉันมีปัญหาเดียวกันหลายวันแล้ว ฉันพยายามดึงข้อมูลจาก PHP แบ็กเอนด์และข้อมูลไม่อัปเดตเลย ใน Microsoft Edge ทำงานได้ดี แต่เบราว์เซอร์อื่นไม่ทำงาน ฉันยังคงได้รับข้อมูลที่ฉันได้เมื่อเริ่มต้น แต่ถ้าข้อมูลการเปลี่ยนแปลงมันไม่ได้รับการปรับปรุงในมุมมอง
el6976

1

ChangeDetectorRef.detectChanges () - คล้ายกับ $ scope $ digest () - เช่นให้ตรวจสอบเฉพาะส่วนนี้และลูก ๆ

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