ตรวจจับการเปลี่ยนแปลงเนื้อหาองค์ประกอบด้วย jQuery


113

change() ฟังก์ชันทำงานและตรวจจับการเปลี่ยนแปลงขององค์ประกอบฟอร์ม แต่มีวิธีตรวจจับเมื่อเนื้อหาขององค์ประกอบ DOM เปลี่ยนแปลงหรือไม่

สิ่งนี้ไม่ได้ผลเว้นแต่#contentจะเป็นองค์ประกอบแบบฟอร์ม

$("#content").change( function(){
    // do something
});

ฉันต้องการให้สิ่งนี้กระตุ้นเมื่อทำสิ่งต่างๆเช่น:

$("#content").html('something');

นอกจากนี้html()หรือappend()ฟังก์ชันไม่มีการโทรกลับ

ข้อเสนอแนะใด ๆ ?


คำถามเก่าที่ฉันรู้ แต่ตรวจสอบคำตอบของฉันสำหรับโซลูชันที่สวยงามstackoverflow.com/a/23826615/744975
Andrew Atkinson

คำตอบ:


26

เหล่านี้มีการกลายพันธุ์ของเหตุการณ์ที่เกิดขึ้น

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


17
ปลั๊กอินเหตุการณ์การกลายพันธุ์นี้ไม่สามารถใช้งานได้เพราะเพียงแค่เชื่อมโยงเหตุการณ์เข้ากับวิธีการกลายพันธุ์ของ jQuery พวกเขาจะเริ่มทำงานเมื่อ jQuery พยายามเปลี่ยนองค์ประกอบ แต่ไม่ใช่เมื่อองค์ประกอบได้รับการเปลี่ยนแปลงจาก jQuery ภายนอก พวกเขาไม่เฝ้าดูการเปลี่ยนแปลงในเอกสาร ลองดูปลั๊กอินเล็ก ๆ นี้แทน: stackoverflow.com/questions/3233991/jquery-watch-div/…
Sebastián Grignoli

10
Googling และโพสต์ลิงก์ไปยังห้องสมุดที่คุณไม่เคยลองไม่ได้มีประโยชน์มากนัก (แสดงความคิดเห็นเพราะฉันได้รับแจ้งให้ลงคะแนน)
หยุดใส่ร้าย Monica Cellio


ทางเลือกที่จะกลายพันธุ์เหตุการณ์ดูเหมือนจะMutationObservers
WoodrowShigeru

69

ฉันรู้ว่าโพสต์นี้มีอายุหนึ่งปีแล้ว แต่ฉันต้องการเสนอแนวทางการแก้ปัญหาที่แตกต่างออกไปสำหรับผู้ที่มีปัญหาคล้ายกัน:

  1. เหตุการณ์การเปลี่ยนแปลง jQuery ถูกใช้เฉพาะในช่องป้อนข้อมูลของผู้ใช้เนื่องจากหากมีการจัดการสิ่งอื่นใด (เช่น div) การจัดการนั้นมาจากโค้ด ดังนั้นค้นหาว่าการจัดการเกิดขึ้นที่ใดจากนั้นเพิ่มสิ่งที่คุณต้องการลงไปที่นั่น

  2. แต่ถ้าเป็นไปไม่ได้ไม่ว่าด้วยเหตุผลใด ๆ (คุณกำลังใช้ปลั๊กอินที่ซับซ้อนหรือไม่พบความเป็นไปได้ในการ "เรียกกลับ") แนวทาง jQuery ที่ฉันแนะนำคือ:

    สำหรับการจัดการ DOM อย่างง่ายให้ใช้ jQuery Chaining และ traversing$("#content").html('something').end().find(whatever)....

    ข หากคุณต้องการทำอย่างอื่นให้ใช้ jQuery bindกับเหตุการณ์ที่กำหนดเองและtriggerHandler

    $("#content").html('something').triggerHandler('customAction');
    
    $('#content').unbind().bind('customAction', function(event, data) {
       //Custom-action
    });

นี่คือลิงค์ไปยังตัวจัดการทริกเกอร์ jQuery: http://api.jquery.com/triggerHandler/


1
ความคิดสุดท้าย. แม้ว่าจะค่อนข้างครอบคลุมด้านบน: คุณสามารถอัปเดตค่าของฟิลด์อินพุตที่ซ่อนอยู่ด้วย #content html จากนั้นผูกเหตุการณ์การเปลี่ยนแปลงกับฟิลด์อินพุตที่ซ่อนอยู่ :) ตัวเลือกมากมาย
Kyle

7
+1 "ค้นหาว่าเกิดการปรับแต่งที่ใดจากนั้นเพิ่มสิ่งที่คุณต้องการลงไปที่นั่น" แก้ไขปัญหาของฉันใน 2 วินาทีโดยไม่มีแฮ็ก / ปลั๊กอินใด ๆ :)
Hartley Brody

สิ่งเดียวที่ฉันขอแนะนำที่นี่คือการเปลี่ยนแปลงที่bindคาดหวังว่าตัวจัดการของคุณจะส่งคืนไฟล์bool.
Serj Sagan

15

เบราว์เซอร์จะไม่เริ่มเหตุการณ์ onchange สำหรับ<div>องค์ประกอบ

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

 $("#content").html('something').each(function() { });

คุณยังสามารถเริ่มเหตุการณ์ด้วยตนเองเช่นนี้:

 $("#content").html('something').change();

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


11
ถือว่าคุณได้เขียนจาวาสคริปต์ทั้งหมดแล้วซึ่งอาจไม่เป็นเช่นนั้น
Myster

ขอบคุณ!!!! สิ่งนี้ช่วยฉันแก้ปัญหาที่ฉันจ้องมองมาเป็นเวลา 6 ชั่วโมง
Jordan Parmer

สิ่งที่ฉันต้องการ
smac89

15

แล้วhttp://jsbin.com/esepal/2

$(document).bind("DOMSubtreeModified",function(){
  console.log($('body').width() + ' x '+$('body').height());
})

เหตุการณ์นี้ได้ถูกเลิกใช้แล้วเนื่องจากMutation Observer API


1
ไม่ใช่ความคิดที่ไม่ดีแม้ว่าฉันจะสงสัยว่ามีการสนับสนุนมากแค่ไหน developer.mozilla.org/en/DOM/DOM_event_reference/…
Elzo Valugi

คุณตรวจสอบองค์ประกอบเฉพาะสำหรับการเปลี่ยนแปลงได้อย่างไร ขณะนี้เอกสารตรวจสอบทั้งหน้า
Patoshi パトシ




3

ไม่ใช่คำตอบของ jQuery อย่างเคร่งครัด แต่มีประโยชน์ในการกล่าวถึงสำหรับการดีบัก

ใน Firebug คุณสามารถคลิกขวาที่องค์ประกอบในโครงสร้าง DOM และตั้งค่า 'Break on Attribute Change':

คลิกขวาที่ Element ใน Firebug โดยเน้น Break on Attribute Change

เมื่อมีการเปลี่ยนแปลงแอตทริบิวต์ในสคริปต์หน้าต่างดีบักจะปรากฏขึ้นและคุณสามารถติดตามสิ่งที่เกิดขึ้นได้ นอกจากนี้ยังมีตัวเลือกสำหรับการแทรกองค์ประกอบและการลบองค์ประกอบด้านล่าง (ป๊อปอัปใน screengrab ถูกบดบังอย่างไม่ช่วยเหลือ)


1
นี่เป็นประโยชน์ แต่ไม่ใช่สิ่งที่เขาขอ สิ่งนี้จะตรวจจับสิ่งต่างๆเช่นเมื่อคลาสเปลี่ยนไปหรือเมื่อมีการเพิ่มหรือเปลี่ยนแปลงแอตทริบิวต์สไตล์ จะไม่ตรวจสอบเมื่อเนื้อหาที่อยู่ภายในโหนดเปลี่ยนแปลง ตัวอย่างเช่นหากจาวาสคริปต์บางแห่งเปลี่ยนโหนดจาก <span> สวัสดี </span> เป็น <span> โลก </span> สิ่งนี้จะตรวจไม่พบ
Joshua Soileau

2

ฉันกำลังพัฒนาไลบรารี JS เล็ก ๆ ที่เรียกว่า mutabor ( https://github.com/eskat0n/mutabor ) ซึ่งมีวัตถุประสงค์เพื่อลดความซับซ้อนในการใช้งาน DOM Mutation Events ดูตัวอย่าง demo.html



1

บ่อยครั้งวิธีที่ง่ายและมีประสิทธิภาพในการบรรลุเป้าหมายนี้คือการติดตามว่าคุณกำลังแก้ไข DOM เมื่อใดและที่ไหน

คุณสามารถทำได้โดยการสร้างฟังก์ชันกลางหนึ่งฟังก์ชันที่รับผิดชอบในการแก้ไข DOM เสมอ จากนั้นคุณทำการล้างข้อมูลที่คุณต้องการในองค์ประกอบที่แก้ไขจากในฟังก์ชันนี้

ในแอปพลิเคชันล่าสุดฉันไม่ต้องการการดำเนินการในทันทีดังนั้นฉันจึงใช้การเรียกกลับสำหรับฟังก์ชัน handly load () เพื่อเพิ่มคลาสให้กับองค์ประกอบที่แก้ไขใด ๆ จากนั้นอัปเดตองค์ประกอบที่แก้ไขทั้งหมดทุกสองสามวินาทีด้วยตัวจับเวลา setInterval

$($location).load("my URL", "", $location.addClass("dommodified"));

จากนั้นคุณสามารถจัดการได้ตามที่คุณต้องการ - เช่น

setInterval("handlemodifiedstuff();", 3000); 
function handlemodifiedstuff()
{
    $(".dommodified").each(function(){/* Do stuff with $(this) */});
}

3
ถือว่าคุณได้เขียนจาวาสคริปต์ทั้งหมดแล้วซึ่งอาจไม่เป็นเช่นนั้น
Myster

1

คุณสามารถเพิ่มตัวเลือกการโทรกลับไปยังฟังก์ชัน html (หรือใดก็ได้):

$.fn.oldHtml = $.fn.html;
$.fn.html = function(html,fn){
  fn = fn || function(){};
  var result =  this.oldHtml(html);
  fn();
  return result;
};
$('body').html(11,function(){alert("haha");});

สาธิตที่นี่

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


ฉันต้องแก้ปัญหานี้ในวันนี้ ฉันไม่สามารถแก้ไขโค้ดที่เรียกว่า html () ได้เนื่องจากอยู่ในไลบรารีของบุคคลที่สาม เวอร์ชันที่แก้ไขแล้วนี้เหมาะสำหรับฉัน ฉันทำสิ่งนี้: $ .fn.oldHtml = $ .fn.html (); $ .fn.html = function (e) {var result = this.oldHtml (e); this.trigger ('afterHtmlChange', e);} ตอนนี้ฉันสามารถผูกเหตุการณ์ใด ๆ ที่ฉันต้องการกับเหตุการณ์ afterHtmlChange ที่สร้างขึ้นใหม่บนองค์ประกอบใด ๆ ซึ่งจะเริ่มทำงานเมื่อใดก็ตามที่มีการเรียกใช้ html () fn ของ jQuery
Daniel Howard

อ๊ะผิดพลาดเล็กน้อย Fn ในความคิดเห็นของฉันด้านบนควรเป็น: function (e) {var result = this.oldHtml (e); this.trigger ( 'afterHtmlChange', E); return result;}
Daniel Howard

0

ฉันเขียนตัวอย่างข้อมูลที่จะตรวจสอบการเปลี่ยนแปลงขององค์ประกอบในเหตุการณ์

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

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

$('.button').live('click', function() {

            var tableHtml = $('#table > tbody').html();
            var timeout = window.setInterval(function(){

                if (tableHtml != $('#table > tbody').
                    console.log('no change');
                } else {
                    console.log('table changed!');
                    clearInterval(timeout);
                }

            }, 10);
        });

รหัสหลอก:

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

0

เราสามารถบรรลุนี้โดยใช้การกลายพันธุ์เหตุการณ์ อ้างอิงจาก www.w3.org โมดูลเหตุการณ์การกลายพันธุ์ได้รับการออกแบบมาเพื่อให้สามารถแจ้งเตือนการเปลี่ยนแปลงโครงสร้างของเอกสารรวมถึงการแก้ไข attr และข้อความ สำหรับรายละเอียดเพิ่มเติมกิจกรรมการปิดเสียง

ตัวอย่างเช่น :

$("body").on('DOMSubtreeModified', "#content", function() {
    alert('Content Modified'); // do something
});

สิ่งนี้เลิกใช้งานมาระยะหนึ่งแล้ว หนึ่งควรใช้Mutation Observers (แนวคิดเดียวกัน)
Carles Alcolea

-3

เป็นไปไม่ได้ฉันเชื่อว่า ie มีเหตุการณ์ที่เปลี่ยนแปลงเนื้อหา แต่ไม่ใช่ x-browser อย่างแน่นอน

ฉันควรจะพูดว่าเป็นไปไม่ได้หากไม่มีช่วงเวลาที่น่ารังเกียจบางอย่างอยู่เบื้องหลัง!


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