Gọi hàm cửa sổ cha từ iframe


281

Tôi muốn gọi một hàm JavaScript cửa sổ cha từ iframe.

<script>
    function abc()
    {
        alert("sss");
    }
</script>

<iframe id="myFrame">
    <a onclick="abc();" href="#">Call Me</a>
</iframe>

1
Tôi sẽ không thể hiển thị bất cứ điều gì ngay bây giờ (2016), tôi không biết liệu người cung cấp cũ hơn có hỗ trợ hay không
Weijing Jay Lin

Câu trả lời:


438
<a onclick="parent.abc();" href="#" >Call Me </a>

Xem window.parent

Trả về một tham chiếu đến cha mẹ của cửa sổ hiện tại hoặc khung con.

Nếu một cửa sổ không có cha mẹ, thuộc tính mẹ của nó là một tham chiếu đến chính nó.

Khi một cửa sổ được tải trong một <iframe>, <object>hoặc <frame>, cha mẹ của nó là cửa sổ với phần tử nhúng cửa sổ.


17
Luôn luôn tính đến rằng tài liệu gốc và tài liệu iframe phải khớp với giao thức và tên miền. Nếu nó không xảy ra thì bạn sẽ gặp lỗi bảo mật vì nó không cho phép có kịch bản tên miền chéo.
a4bike

M chỉ tự hỏi cái nào hai alerts sẽ được gọi; alertHàm cha hoặc hàm iframe alert, trong trường hợp parent.abc();được gọi trên iframe?
Prakhar Mishra

@PrakharMishra Đừng nhầm lẫn. cha mẹ có nghĩa là cha mẹ.
Sahu V Kumar

3
@ a4bike cho các kịch bản như vậy, window.postMessage()(hoặc window.parent.postMessage()) tồn tại. Kiểm tra câu trả lời @Andrii
Fr0zenFyr

81

Gần đây tôi đã phải tìm hiểu tại sao điều này không hoạt động quá.

Javascript mà bạn muốn gọi từ iframe con cần phải nằm trong đầu của cha mẹ. Nếu nó nằm trong phần thân, tập lệnh không có sẵn trong phạm vi toàn cầu.

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="parent.abc();" href="#">Click Me</a>
    </iframe>
</body>

Hy vọng điều này sẽ giúp bất cứ ai vấp phải vấn đề này một lần nữa.


1
Không có kỹ thuật nào được đề cập trong bài đăng này hoạt động trên Chrome. Bất kỳ giải pháp cho điều này?
Kumar Kush

3
Nếu tôi nhớ chính xác, tôi không thể làm điều này hoạt động như mong đợi nếu iframe có tên miền khác với cha mẹ. Xin lỗi, đây không phải là một giải pháp, nhưng nó có thể giải thích tại sao nó không hoạt động.
Ash Clarke

1
Đúng. Tôi biết rằng đó là do các lĩnh vực khác nhau, nhưng không có cách nào để giải quyết vấn đề này?
Kumar Kush

1
Tôi vừa đăng những gì có thể là một cách giải quyết vấn đề của bạn. Hãy xem câu trả lời khác.
Ash Clarke

1
Theo các quy tắc xác định chính sách nguồn gốc giống nhau (xem: en.wikipedia.org/wiki/ ,), tên miền phụ được coi là tên máy chủ khác với tên miền phụ của tên miền. Nếu bạn chưa có, bạn có thể thử chỉ đặt document.domain thành tên miền phụ không?
Ash Clarke

72

Window.postMessage ()

Phương pháp này cho phép một cách an toàn cross-origin giao tiếp .

Và nếu bạn có quyền truy cập vào mã trang cha thì bất kỳ phương thức cha nào cũng có thể được gọi cũng như mọi dữ liệu có thể được truyền trực tiếp từ đó Iframe. Đây là một ví dụ nhỏ:

Trang phụ huynh:

if (window.addEventListener) {
    window.addEventListener("message", onMessage, false);        
} 
else if (window.attachEvent) {
    window.attachEvent("onmessage", onMessage, false);
}

function onMessage(event) {
    // Check sender origin to be trusted
    if (event.origin !== "http://example.com") return;

    var data = event.data;

    if (typeof(window[data.func]) == "function") {
        window[data.func].call(null, data.message);
    }
}

// Function to be called from iframe
function parentFunc(message) {
    alert(message);
}

Mã iframe:

window.parent.postMessage({
    'func': 'parentFunc',
    'message': 'Message text from iframe.'
}, "*");
// Use target origin instead of *

CẬP NHẬT:

Lưu ý bảo mật:

Luôn cung cấp một mục tiêu cụ thể, KHÔNG *, nếu bạn biết tài liệu của cửa sổ khác sẽ được đặt ở đâu. Không cung cấp mục tiêu cụ thể tiết lộ dữ liệu bạn gửi đến bất kỳ trang web độc hại nào quan tâm (nhận xét của ZalemCitizen ).

Người giới thiệu:


1
Tôi thích sử dụng này hơn những người khác. Đặc biệt bởi vì nó có ý nghĩa hơn khi sử dụng iframe trên các tài liệu gốc chéo (mặc dù các lập trình viên khai thác iframe thường xuyên hơn không) và hỗ trợ rộng rãi cho chức năng này trên các trình duyệt.
Fr0zenFyr

1
Cảm ơn! Tôi luôn phải dành một giờ hoặc nhiều hơn để quay lại và nghiên cứu cách thực hiện nhắn tin với các ví dụ phức tạp, dài dòng. Điều này làm việc trong 60 giây. Cảm ơn cho một ví dụ ngắn gọn và chính xác.
RandallĐến

2
đáng để nâng cao điều đó (từ các tài liệu web MDN ): Luôn cung cấp một mục tiêu cụ thể, không phải *, nếu bạn biết tài liệu của cửa sổ khác sẽ được đặt ở đâu. Không cung cấp mục tiêu cụ thể tiết lộ dữ liệu bạn gửi đến bất kỳ trang web độc hại nào quan tâm
ZalemCitizen

20

Tôi đã đăng bài này như một câu trả lời riêng vì nó không liên quan đến câu trả lời hiện có của tôi.

Vấn đề này gần đây đã được cắt lại để truy cập cha mẹ từ iframe tham chiếu tên miền phụ và các bản sửa lỗi hiện tại không hoạt động.

Lần này, câu trả lời là sửa đổi document.domain của trang mẹ và iframe giống nhau. Điều này sẽ đánh lừa các kiểm tra chính sách nguồn gốc tương tự khi nghĩ rằng chúng cùng tồn tại trên cùng một tên miền (tên miền phụ được coi là một máy chủ khác nhau và không kiểm tra chính sách nguồn gốc giống nhau).

Chèn phần sau vào <head>trang trong iframe để khớp với miền mẹ (điều chỉnh cho loại tài liệu của bạn).

<script>
    document.domain = "mydomain.com";
</script>

Xin lưu ý rằng điều này sẽ gây ra lỗi khi phát triển localhost, vì vậy hãy sử dụng kiểm tra như sau để tránh lỗi:

if (!window.location.href.match(/localhost/gi)) {
    document.domain = "mydomain.com";
} 

và những gì về thử nghiệm này trong localhost? bất kỳ cách giải quyết cho điều đó?
Umesh Awasthi

Xem: "Xin lưu ý rằng điều này sẽ gây ra lỗi khi phát triển localhost, vì vậy hãy sử dụng một kiểm tra như sau để tránh lỗi"
Ash Clarke

2
Điều đáng chú ý là (ít nhất là trong Google Chrome) cả, cha mẹ và con PHẢI cài đặt tài liệu.domain ngay cả khi một trong số chúng đã "chính xác"! Ví dụ: Parent là example.comiframe abc.example.com, thì cả cha và iframe đều phải gọidocument.domain = "example.com"
KillerX

Đúng vậy, tôi đã đánh máy ở đây: "trang trong iframe giống nhau". phải là "trang và iframe giống nhau." ..... Cảm ơn!
Ash Clarke

đối với if () tại sao bạn không sử dụng if (document.domain! = "mydomain.com"? Ngoài ra, tôi bối rối, <script> có đi vào cửa sổ cha mẹ hoặc iFrame không? Ngoài ra, hãy đặt document.domain trong iFrame tạo "Không thể đặt thuộc tính 'domain' trên 'Document': 'localhost' không phải là hậu tố của 'sc-localhost'.
user2568374

18

Bạn có thể dùng

window.top

xem những điều sau đây

<head>
    <script>
    function abc() {
        alert("sss");
    }
    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="window.top.abc();" href="#">Click Me</a>
    </iframe>
</body>

Khi cố gắng gọi Parent.custom_feft (); từ iframe không hoạt động, bạn có thể tìm window.top.custom_feft (); sẽ làm việc. Làm việc cho tôi vì một số lý do kỳ lạ. Tất cả các javascripts của tôi trên cửa sổ cha mẹ đều được nhúng vào phần chân trang, tôi đọc ở đâu đó bao gồm các tệp javascript trong phần chân trang gây ra vấn đề Parent.custom_feft () không hoạt động.
Friso Horstman

@Vinothkumar, xin vui lòng một câu hỏi, đó là sự khác biệt giữa việc gọi "window.top.abc ()" so với chỉ gọi "abc ()", cảm ơn trước =)
Zilev av

@Zilev av Toàn bộ điểm của luồng này đang gọi một hàm trong tài liệu gốc từ iframe con. Đó là sự khác biệt. Gọi abc()sẽ chỉ hoạt động nếu function abc()được khai báo trong iframe trái ngược với trên trang mẹ. window.top.abc()thoát ra khỏi iframe vào tài liệu gốc.
Sean Kendle

3

Một bổ sung cho những người cần nó. Giải pháp của Ash Clarke không hoạt động nếu họ đang sử dụng các giao thức khác nhau, vì vậy hãy chắc chắn rằng nếu bạn đang sử dụng SSL, iframe của bạn cũng đang sử dụng SSL hoặc nó sẽ phá vỡ chức năng. Giải pháp của anh ấy đã làm việc cho chính tên miền, vì vậy cảm ơn vì điều đó.


2

Giải pháp do Ash Clarke đưa ra cho các tên miền phụ hoạt động rất tốt, nhưng xin lưu ý rằng bạn cần bao gồm document.domain = "mydomain.com"; trong cả phần đầu của trang iframe và phần đầu của trang mẹ, như đã nêu trong liên kết, cùng kiểm tra chính sách xuất xứ

Một tiện ích mở rộng quan trọng cho cùng một chính sách nguồn gốc được triển khai để truy cập JavaScript DOM (nhưng không phải cho hầu hết các hương vị khác của kiểm tra cùng nguồn gốc) là hai trang web chia sẻ một tên miền cấp cao chung có thể chọn liên lạc mặc dù không có "cùng một máy chủ" kiểm tra bằng cách đặt lẫn nhau thuộc tính DOM.d.domain tương ứng của chúng thành cùng một phần bên phải, đủ điều kiện của tên máy chủ hiện tại của chúng. Ví dụ: nếu http://en.example.com/http://fr.example.com/ đều đặt document.domain thành "example.com", thì từ thời điểm đó được coi là cùng nguồn gốc cho mục đích của thao tác DOM.


Đúng vậy, tôi đã đánh máy ở đây: "trang trong iframe giống nhau". phải là "trang và iframe giống nhau." ..... Cảm ơn!
Ash Clarke

Làm thế nào về việc chạy tập tin trong máy tính cục bộ? giá trị của là document.domaingì?
Raptor

Nó sẽ là localhosthoặc địa chỉ IP của máy (thông thường 127.0.0.1), tùy thuộc vào những gì trong thanh địa chỉ url.
Ash Clarke

2

Parent.abc () sẽ chỉ hoạt động trên cùng một tên miền do mục đích bảo mật. tôi đã thử cách giải quyết này và tôi đã làm việc hoàn hảo.

<head>
    <script>
    function abc() {
        alert("sss");
    }

    // window of the iframe
    var innerWindow = document.getElementById('myFrame').contentWindow;
    innerWindow.abc= abc;

    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="abc();" href="#">Click Me</a>
    </iframe>
</body>

Hi vọng điêu nay co ich. :)


Điều này cũng thực sự chỉ được sử dụng cho tài liệu của iframe, thêm các biến chứng lớn nếu bạn cần tham khảo các điều khiển trên biểu mẫu chính.
Paul

1

Với Firefox và Chrome, bạn có thể sử dụng:

<a href="whatever" target="_parent" onclick="myfunction()">

Nếu chức năng của tôi có mặt cả trong iframe và cha mẹ, thì cha mẹ sẽ được gọi.


nó không hoạt động. Đây là bản demo của tôi: dotku.github.io/tech/html/iframe/iframe_feft_container.html
Weijing Jay Lin

Như Ash Clarke đã nêu, javascript mà bạn muốn gọi từ iframe con cần phải nằm trong đầu của cha mẹ.
bông tuyết

Câu trả lời được chấp nhận không cần phải có kịch bản trong đầu. Tôi đã không kiểm tra xem giải pháp này có còn cần cho kịch bản trong đầu hay không.
Guy Schalnat

0

Trong khi một số giải pháp này có thể hoạt động, không ai trong số họ thực hiện theo các thực tiễn tốt nhất. Nhiều người gán các biến toàn cục và bạn có thể thấy mình thực hiện các cuộc gọi đến nhiều biến cha hoặc hàm, dẫn đến một không gian tên dễ bị lộn xộn.

Để tránh điều này, sử dụng một mô-đun mô-đun. Trong cửa sổ cha mẹ:

var myThing = {
    var i = 0;
    myFunction : function () {
        // do something
    }
};

var newThing = Object.create(myThing);

Sau đó, trong iframe:

function myIframeFunction () {
    parent.myThing.myFunction();
    alert(parent.myThing.i);
};

Điều này tương tự với các mẫu được mô tả trong chương Kế thừa của văn bản tinh dịch của Crockford, "Javascript: Các bộ phận tốt." Bạn cũng có thể tìm hiểu thêm tại trang của w3 để biết các thực tiễn tốt nhất của Javascript. https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.