2013-04-28 31 views
8

Tôi có nhiều iframe trong một trang. Bây giờ tôi có một người nghe sự kiện message cho trang, nhận được tin nhắn từ tất cả các iframe. Tôi có một giải pháp để biết từ đó khung nội tuyến thông báo đang đến.javascript: nghe các sự kiện postMessage từ iframe cụ thể

Tôi muốn tạo trình xử lý sự kiện cho mỗi khung nội tuyến một cách riêng biệt. Điều này có thể không?

+0

Đừng nghĩ rằng là có thể. Cửa sổ có thể nhận các sự kiện 'message' từ bất cứ đâu. Nếu bạn có một giải pháp thay thế, điều đó có thể là ok. –

+1

Chỉ vì mục đích tò mò, bạn giải quyết cách nào? – zer00ne

Trả lời

1

Không, không thể. Tốt nhất bạn có thể làm là có một trình xử lý duy nhất định tuyến các thư đã nhận tới trình xử lý trợ giúp dựa trên nguồn gốc của người gửi thư.

+1

Có thể được thực hiện bằng cách đặt thuộc tính tên duy nhất cho mỗi khung nội tuyến.Sau đó, bên trong iframe window.name là tên của iframe và có thể được gửi với postMessage. –

7

Nếu src thuộc tính của mỗi iframe là duy nhất thì bạn có thể thử điều này:

Trên con:

function sendHeight() { 
    // sends height to parent iframe 
    var height = $('#app').height(); 
    window.parent.postMessage({ 
    'height': height, 
    'location': window.location.href 
    }, "*"); 
} 

$(window).on('resize', function() { 
    sendHeight(); 
}).resize(); 

Trên mẹ:

$(window).on("message", function(e) { 
    var data = e.originalEvent.data; 
    $('iframe[src^="' + data.location + '"]').css('height', data.height + 'px'); 
}); 

Đứa trẻ gửi nó là chiều cao và URL cho cha mẹ iframe sử dụng postMessage(). Sau đó, phụ huynh lắng nghe sự kiện đó, lấy khung nội tuyến bằng URL đó và đặt chiều cao cho nó.

+0

Mặc dù tôi không chắc chắn câu trả lời của bạn đề cập đến câu hỏi của OP rất tốt, tôi thấy mã của bạn hữu ích cho cá nhân tôi - nhờ, cảm ơn. – zer00ne

+0

Tôi đoán tôi có thể loại bỏ các bit chiều cao. Tôi có? –

+0

Tôi nghĩ OP chỉ đơn giản muốn các EventList riêng lẻ cho mỗi iframe, nhưng nó sẽ vô dụng vì nhiều eventListeners lắng nghe trên bất kỳ iframe nào sẽ là một bản sao vì nó là cùng một sự kiện. Bất kỳ eventListeners trùng lặp nào cũng chỉ là lãng phí gia vị vì chỉ có một người sẽ làm việc trong khi bất kỳ bản sao nào sẽ bị bỏ qua. – zer00ne

1

Bạn có thể sử dụng e.originalEvent.origin để xác định khung nội tuyến.

Trên con iframe:

window.parent.postMessage({ 
    'msg': 'works!' 
}, "*"); 

Trên iframe mẹ:

Javascript

window.addEventListener('message', function(e) { 
    console.log(e.origin); // outputs "http://www.example.com/" 
    console.log(e.data.msg); // outputs "works!" 
    if (e.origin === 'https://example1.com') { 
    // do something 
    } else if (e.origin === 'https://example2.com'){ 
    // do something else 
    } 
}, false); 

jQuery

$(window).on('message', function(e) { 
    ... 
}, false); 

Vì vậy, origin chứa giao thức và miền mà từ đó postMessage() được kích hoạt. Nó không bao gồm URI. Kỹ thuật này giả định rằng tất cả iframe có một miền duy nhất.

+1

'e.originalEvent.origin' có trả lại url do chuỗi được sắp xếp không? Tôi không phải tất cả những gì quen thuộc với jQuery và tất cả những gì tôi tìm thấy trên đó là nó trả về các thuộc tính nhất định bên trong một objectEvent đã được gói lên để thuận tiện bởi jQuery. Vì vậy, 'origin' thực sự có thể hiển thị' location.protocol + location.hostname' của sự kiện? – zer00ne

+0

Ví dụ không hoạt động, e.data không được xác định. –

0

Một cách để phát hiện thư đến từ đâu là bằng cách kiểm tra khung nội tuyến nào được tập trung hoặc cho trường hợp cụ thể của tôi mà khung nội tuyến hiển thị.

0

Thực ra bạn có thể. Thêm một thuộc tính tên duy nhất cho mỗi khung nội tuyến. tên iframe được chuyển xuống contentWindow. Vì vậy, bên trong iframe window.name là tên của khung nội tuyến và bạn có thể dễ dàng gửi nó trong thông báo bài viết.

0

Bạn phải nghe trên sự kiện message toàn cầu của đối tượng window, nhưng bạn có thể lọc iframe nguồn bằng cách sử dụng thuộc tính source của MessageEvent.

Ví dụ:

const childWindow = document.getElementById('test-frame').contentWindow; 
window.addEventListener('message', message => { 
    if (message.source !== childWindow) { 
     return; // Skip message in this event listener 
    } 

    // ... 
}); 
Các vấn đề liên quan