ผู้ฟังเหตุการณ์
ก่อนอื่นสิ่งสำคัญคือต้องเข้าใจว่ามี "ผู้ฟังเหตุการณ์" สองประเภท:
ขอบเขตผู้ฟังเหตุการณ์ที่ลงทะเบียนผ่าน$on
:
$scope.$on('anEvent', function (event, data) {
...
});
ตัวจัดการเหตุการณ์ที่แนบกับองค์ประกอบผ่านตัวอย่างเช่นon
หรือbind
:
element.on('click', function (event) {
...
});
$ ขอบเขต. $ ทำลาย ()
เมื่อ$scope.$destroy()
มีการดำเนินการมันจะลบผู้ฟังทั้งหมดที่ลงทะเบียนผ่านทาง$on
ขอบเขต $ นั้น
มันจะไม่ลบองค์ประกอบ DOM หรือตัวจัดการเหตุการณ์ที่แนบมาของชนิดที่สอง
ซึ่งหมายความว่าการโทร$scope.$destroy()
ด้วยตนเองจากตัวอย่างภายในฟังก์ชั่นลิงค์ของ directive จะไม่ลบ handler ที่แนบมาเช่นelement.on
หรือองค์ประกอบ DOM เอง
element.remove ()
โปรดทราบว่าremove
เป็นวิธีการ jqLite (หรือวิธี jQuery หากโหลด jQuery ก่อน AngularjS) และไม่สามารถใช้ได้กับวัตถุองค์ประกอบ DOM มาตรฐาน
เมื่อelement.remove()
ถูกดำเนินการองค์ประกอบที่และทุกเด็กของมันจะถูกลบออกจาก DOM element.on
ร่วมกันทั้งหมดจะจัดการเหตุการณ์ติดผ่านทางตัวอย่างเช่น
มันจะไม่ทำลายขอบเขต $ ที่เกี่ยวข้องกับองค์ประกอบ
$destroy
ที่จะทำให้มันมากขึ้นทำให้เกิดความสับสนนอกจากนี้ยังมีเหตุการณ์ที่เรียกว่า jQuery บางครั้งเมื่อทำงานกับไลบรารี jQuery บุคคลที่สามที่ลบองค์ประกอบออกหรือถ้าคุณลบด้วยตนเองคุณอาจต้องล้างข้อมูลเมื่อเกิดเหตุการณ์เช่นนี้:
element.on('$destroy', function () {
scope.$destroy();
});
จะทำอย่างไรเมื่อคำสั่ง "ถูกทำลาย"
ขึ้นอยู่กับว่าคำสั่งนั้นถูก "ทำลาย" อย่างไร
กรณีปกติคือคำสั่งถูกทำลายเพราะng-view
เปลี่ยนมุมมองปัจจุบัน เมื่อสิ่งนี้เกิดขึ้นng-view
คำสั่งจะทำลายขอบเขต $ ที่เกี่ยวข้องตัดการอ้างอิงทั้งหมดไปยังขอบเขตหลักและเรียกremove()
ใช้องค์ประกอบ
ซึ่งหมายความว่าหากมุมมองนั้นมีคำสั่งในฟังก์ชันลิงก์เมื่อถูกทำลายโดยng-view
:
scope.$on('anEvent', function () {
...
});
element.on('click', function () {
...
});
ผู้ฟังเหตุการณ์ทั้งสองจะถูกลบโดยอัตโนมัติ
แต่มันเป็นสิ่งสำคัญที่จะต้องทราบว่ารหัสภายในฟังเหล่านี้ยังสามารถก่อให้เกิดการรั่วไหลของหน่วยความจำตัวอย่างเช่นถ้าคุณได้ประสบความสำเร็จร่วมกัน JS circular references
รูปแบบหน่วยความจำรั่ว
แม้ในกรณีปกติของคำสั่งที่ถูกทำลายเนื่องจากการเปลี่ยนมุมมองมีบางสิ่งที่คุณอาจจำเป็นต้องทำความสะอาดด้วยตนเอง
ตัวอย่างเช่นหากคุณลงทะเบียนผู้ฟังใน$rootScope
:
var unregisterFn = $rootScope.$on('anEvent', function () {});
scope.$on('$destroy', unregisterFn);
สิ่งนี้จำเป็นเนื่องจาก$rootScope
จะไม่ถูกทำลายในช่วงอายุการใช้งานของแอปพลิเคชัน
เช่นเดียวกันหากคุณใช้การติดตั้ง pub / sub อื่นที่ไม่ดำเนินการล้างข้อมูลที่จำเป็นโดยอัตโนมัติเมื่อขอบเขต $ ถูกทำลายหรือหากคำสั่งของคุณส่งการเรียกกลับไปยังบริการ
สถานการณ์อื่นจะเป็นการยกเลิก$interval
/ $timeout
:
var promise = $interval(function () {}, 1000);
scope.$on('$destroy', function () {
$interval.cancel(promise);
});
หากคำสั่งของคุณแนบตัวจัดการเหตุการณ์กับองค์ประกอบเช่นนอกมุมมองปัจจุบันคุณต้องล้างสิ่งเหล่านั้นด้วยตนเอง:
var windowClick = function () {
...
};
angular.element(window).on('click', windowClick);
scope.$on('$destroy', function () {
angular.element(window).off('click', windowClick);
});
เหล่านี้เป็นตัวอย่างของสิ่งที่ต้องทำเมื่อคำสั่งถูก "ทำลาย" โดย Angular ตัวอย่างเช่นโดย ng-view
ng-if
หรือ
หากคุณมีคำสั่งที่กำหนดเองที่จัดการวงจรชีวิตขององค์ประกอบ DOM ฯลฯ แน่นอนว่ามันจะซับซ้อนมากขึ้น