kích hoạt sự kiện window.resize trong Internet Explorer


76

Như bạn đã biết, trong Internet Explorer, sự kiện window.resize được kích hoạt khi bất kỳ phần tử nào trên trang được thay đổi kích thước. Không quan trọng liệu phần tử trang có được thay đổi kích thước thông qua việc gán / thay đổi thuộc tính chiều cao hoặc kiểu của nó hay không, bằng cách chỉ cần thêm một phần tử con vào nó hoặc bất cứ điều gì - mặc dù việc thay đổi kích thước phần tử không ảnh hưởng đến kích thước của chính khung nhìn.

Trong ứng dụng của tôi, điều này gây ra một đệ quy khó chịu, vì trong trình xử lý window.resize của tôi, tôi đang thay đổi kích thước một số phần tử <li>, đến lượt nó sẽ kích hoạt lại window.resize, v.v. Một lần nữa, đây chỉ là một vấn đề trong IE.

Có cách nào để ngăn window.resize kích hoạt trong IE khi các phần tử trên trang được thay đổi kích thước không?

Tôi cũng nên đề cập rằng tôi đang sử dụng jQuery.


2
Thật thú vị, tôi không biết điều đó. Tôi không quen với JQuery nhưng có thể dừng sự kiện nếu phần tử nguồn của nó không phải là chính cửa sổ. Tôi chắc rằng ai đó sẽ nghĩ ra một giải pháp mã hóa.
Pekka

Đây là phiên bản IE nào và bạn có thể cung cấp một số mã thực sự hiển thị thay đổi kích thước phần tử kích hoạt window.resize không?
DEfusion

Không nên phiên bản về khác, nhưng nó sẽ xảy ra trong IE 8
Cocowalla

1
tôi không thể cảm ơn bạn đủ cho câu hỏi này. Tôi liên tục giật tóc: "TẠI SAO TRANG CỦA TÔI LẠI CHẬM?" lần lượt ra ie8 giữ bắn window.resize trên mỗi khung và sau đó xử lý thay đổi kích thước của tôi sẽ phải đặt lại vị trí tất cả mọi thứ hơn và hơn nữa
user151496

Cám ơn vì cái này. Có thể xác nhận rằng đó là một vấn đề trên IE9.
SAGExSDX

Câu trả lời:


60

Tôi vừa phát hiện ra một vấn đề khác có thể giúp bạn.

Tôi đang sử dụng jQuery và tôi có sự kiện window.resize để gọi một hàm sẽ định vị lại div được nối vào phần thân.

Bây giờ khi tôi đặt thuộc tính LEFT css của div được nối thêm đó, sự kiện window.resize được kích hoạt cho KHÔNG CÓ LÝ DO TỐT.

Nó dẫn đến một vòng lặp vô hạn, kích hoạt window.resize lặp đi lặp lại.

Mã không có sửa chữa:

$(window).resize(function(){
    var onResize = function(){
        //The method which alter some css properties triggers 
        //window.resize again and it ends in an infinite loop
        someMethod();
    }
    window.clearTimeout(resizeTimeout);
    resizeTimeout = window.setTimeout(onResize, 10);
});

Giải pháp:

var winWidth = $(window).width(),
    winHeight = $(window).height();

$(window).resize(function(){
    var onResize = function(){
        //The method which alter some css properties triggers 
        //window.resize again and it ends in an infinite loop
        someMethod();
    }

    //New height and width
    var winNewWidth = $(window).width(),
        winNewHeight = $(window).height();

    // compare the new height and width with old one
    if(winWidth!=winNewWidth || winHeight!=winNewHeight){
        window.clearTimeout(resizeTimeout);
        resizeTimeout = window.setTimeout(onResize, 10);
    }
    //Update the width and height
    winWidth = winNewWidth;
    winHeight = winNewHeight;
});

Vì vậy, về cơ bản nó sẽ kiểm tra xem chiều cao hoặc chiều rộng có bị thay đổi hay không (điều này CHỈ xảy ra khi bạn thực sự thay đổi kích thước bằng cửa sổ).


Aamir, có vẻ như đó là một mẹo nhỏ. Hãy để tôi thử và tôi sẽ quay lại và cho bạn biết nó hoạt động như thế nào.
MissingLinq 21/12/09

1
Cảm ơn ý tưởng để kiểm tra và xem liệu chiều rộng / chiều cao của cửa sổ đã thay đổi để xem liệu cửa sổ thực sự có thay đổi kích thước hay không!
Bryan Denny

là onResize toàn cầu có chủ đích hay bạn quên var?
Jethro Larson

Giải pháp tuyệt vời - có cùng một tình huống lặp vô hạn mà bản sửa lỗi này đã khắc phục được.
Prembo

Mặc dù bạn vẫn nên kiểm tra xem chiều rộng hoặc chiều cao có thay đổi hay không, điều này không giải quyết được tình huống trong đó resizetrình xử lý liên tục được kích hoạt mặc dù chiều rộng và chiều cao vẫn giữ nguyên. Trong trường hợp của tôi, đó là documentđối tượng khiến trình xử lý kích hoạt và dẫn đến một vòng lặp vô hạn.
WynandB

25

điều này có ý nghĩa với tôi và dường như hoạt động trong IE7 trở lên:

    //variables to confirm window height and width
    var lastWindowHeight = $(window).height();
    var lastWindowWidth = $(window).width();

    $(window).resize(function() {

        //confirm window was actually resized
        if($(window).height()!=lastWindowHeight || $(window).width()!=lastWindowWidth){

            //set this windows size
            lastWindowHeight = $(window).height();
            lastWindowWidth = $(window).width();

            //call my function
            myfunction();


        }
    });

19

Ràng buộc trình nghe thay đổi kích thước của bạn với .one()để nó tự hủy liên kết sau khi kích hoạt. Sau đó, bạn có thể làm bất cứ điều gì bạn muốn, miễn là cuối cùng bạn rebind trình nghe thay đổi kích thước. Tôi thấy cách dễ nhất để làm điều này là đặt trình nghe thay đổi kích thước trong một hàm ẩn danh như sau:

var resizeListener = function(){
  $(window).one("resize",function(){ //unbinds itself every time it fires

    //resize things

    setTimeout(resizeListener,100); //rebinds itself after 100ms
  });
}
resizeListener();

Về mặt kỹ thuật, bạn không cần cái setTimeoutbọc xung quanh resizeListener()nhưng tôi đã ném nó vào đó như một vật đề phòng và để điều chỉnh thêm.


3
Giải pháp tuyệt vời. Hãy nhớ rằng các hàm các đối tượng chính thức trong JavaScript, vì vậy resizeListenercó thể được chuyển trực tiếp đến setTimeout()thay vì sử dụng chuỗi ký tự "resizeListener();".
yên tĩnh

Cảm ơn vì mẹo đó, @ user113215. Tôi đã cập nhật mã dựa trên đề xuất của bạn.
brentonstrine

Phương pháp tuyệt vời mà không sử dụng bất kỳ biến thêm hoặc nếu phát biểu
Ergec

@brentonstrine Điều này đã giải quyết được vấn đề $(window).resize()treo trên IE8 của tôi. Hoạt động như một sự quyến rũ. Cảm ơn!
Sithu

5

Tôi đã giải quyết nó bằng cách hủy liên kết hàm thay đổi kích thước, xây dựng lại trang và sau đó liên kết lại hàm thay đổi kích thước:

function rebuild() {
   $(window).unbind('resize');
   /* do stuff here */
   $(window).bind('resize',rebuild);
}

$(window).bind('resize',rebuild);

BIÊN TẬP

Bind và unbind không hoạt động tốt với IE8. Mặc dù Microsoft thậm chí đã từ bỏ IE8, bạn có thể muốn thử điều này (chưa được kiểm tra!):

function rebuild(){
   if(!window.resizing) return false;
   window.resizing=true;
   /* do stuff here */
   window.resizing=false;
}

window.resizing=false;
document.body.onresize=rebuild;

Đây có vẻ là giải pháp thanh lịch nhất, nhưng có vẻ như không thực sự hiệu quả với tôi. Tôi đang thử nghiệm trong IE 8 trên Windows XP và Chrome 36 trên OS X 10.9.
Sina

Vâng, ràng buộc và hủy liên kết jQuery không đi đôi với nhau tốt với IE8. Tôi nghi ngờ họ (jQuery) sẽ sửa nó vì ngay cả Microsoft cũng không hỗ trợ IE8 / XP nữa kể từ ngày 8 tháng 4 năm 2014 ...
Patrick

1
Một giải pháp khác có thể là đặt một tham số toàn cục khi bắt đầu xây dựng lại hàm mà bạn kiểm tra trước khi thay đổi kích thước: function build lại () {if (window.resizing) return false; window.resizing = true; / * làm công cụ ở đây * / window.resizing = false;); => đã chỉnh sửa câu trả lời cho dễ đọc
Patrick

4

Câu trả lời của @ AamirAfridi.com đã giải quyết được vấn đề của tôi.

Bạn nên viết một hàm chung để giải quyết những thứ như vậy:

function onWindowResize(callback) {
    var width = $(window).width(),
        height = $(window).height();

    $(window).resize(function() {
        var newWidth = $(window).width(),
            newHeight = $(window).height();

        if (newWidth !== width || newHeight !== height) {
            width = newWidth;
            height = newHeight;
            callback();
        }
    });
}

Sử dụng nó như thế này và bạn không phải lo lắng về các hành vi khác nhau trong IE nữa:

onWindowResize(function() {
    // do something
});

1
Tốt hơn để kiểm tra sử dụng callback với setTimeout chỉ để chắc chắn rằng người dùng đã hoàn thành thay đổi kích thước cửa sổ
Aamir Afridi

1

Tôi gặp sự cố này hôm nay và quyết định đặt phần sau ở đầu tệp javascript bao gồm toàn cầu của tôi:

var savedHeight = 0;
var savedWidth = 0;
Event.observe(window, 'resize', function (e) {
    if (window.innerHeight == savedHeight && 
        window.innerWidth == savedWidth) { e.stop(); }
    savedHeight = window.innerHeight;
    savedWidth = window.innerWidth;
});

Nhân tiện, điều đó yêu cầu Nguyên mẫu.


1

Sự kết hợp của unbind/ bindmethod với một cuộc gọi bị trì hoãn. Nó hoạt động trong Internet Explorer 8 trở xuống, ngăn chặn vòng lặp xấu và treo trên phiên bản 6 và 7.

function resizeViewport()
{
    // Unbind and rebind only for IE < 9
    var isOldIE = document.all && !document.getElementsByClassName;

    if( isOldIE )
        $(window).unbind( 'resize', resizeViewport );

    // ...

    if( isOldIE )
    {
        setTimeout(function(){
            $(window).resize( resizeViewport );
        }, 100);
    }
}

$(window).resize( resizeViewport );

1

Bạn có thể thử điều này:

Constructor:

this.clientWidth = null;
this.clientHeight = null;

Một số chức năng:

var clientWidth = window.innerWidth || document.documentElement.clientWidth; 
var clientHeight = window.innerHeight || document.documentElement.clientHeight;
if (clientWidth != this.clientWidth || clientHeight != this.clientHeight ) {
    this.clientWidth = clientWidth;
    this.clientHeight = clientHeight;

    ... YOUR CODE ...
} 

Đối với Internet Explorer, Chrome, Firefox, Opera và Safari:

window.innerHeight - the inner height of the browser window
window.innerWidth - the inner width of the browser window

Đối với Internet Explorer 8, 7, 6, 5:

document.documentElement.clientHeight
document.documentElement.clientWidth
    or
document.body.clientHeight
document.body.clientWidth

0
(function ($){
     //if ie8 -> return;
     var lastHeight = 0;
     var lastWidth = 0;
     $(window).resize(function(event){
         if (window.innerHeight == lastHeight && window.innerWidth == lastWidth)
             { event.stopImmediatePropagation(); }
         lastHeight = window.innerHeight;
         lastHeight = window.innerWidth;
     });
})();

có lừa cho tôi ...


0
<pre>



var cont = 0;
var tmRsize = 100;
var lastWindowWidth = $(window).width();
var lastWindowHeight = $(window).height();

/*****redimensionamiento**********/
$(window).resize(function()
{
    if($(window).width() != lastWindowWidth || $(window).height() != lastWindowHeight)
    {
        clearTimeout(this.id);
        this.tiempo = tmRsize;
        this.id = setTimeout(doResize, this.tiempo);
    }
});

function doResize()
{
    lastWindowWidth = $(window).width();
    lastWindowHeight = $(window).height();

    $('#destino_1').html(cont++);
}


0

Đây là cách tôi giải quyết việc tìm hiểu xem sự kiện thay đổi kích thước có được kích hoạt bởi một phần tử hay bằng cách thực sự thay đổi kích thước cửa sổ:

Nếu target.nodeType của sự kiện không tồn tại, rất có thể đó là cửa sổ, vì bất kỳ phần tử nào khác trên trang sẽ có nodeType.

Vì vậy, đây là mã giả (sử dụng jQuery) với kiểm tra được thêm vào:

$(window).resize(function(event){
    if ( $(event.target.nodeType).length == 0 ){
        // Anything here is run when the window was resized
        // not executed when an element triggered the resize
    }
});

-1

Tôi không thể kích hoạt sự kiện thay đổi kích thước khi một phần tử được thay đổi kích thước (chỉ thử trong IE8).

Tuy nhiên, những gì targettrên đối tượng sự kiện khi bạn gặp sự cố này, bạn có thể làm gì không:

$(window).resize(function(e) {
    if( e.target != window ) return;
    // your stuff here
});

2
Điều này không hoạt động, bởi vì khi một phần tử kích hoạt window.resize, thì mục tiêu trên window.resize luôn là window. Đây là lý do tại sao tôi bắt đầu nghi ngờ rằng nó thực sự không thể được thực hiện ...
MissingLinq

-1

Bản vá của tôi:

<!--[if lte IE 7]>
<script type="text/javascript">
  window.onresize = null;       // patch to prevent infinite loop in IE6 and IE7
</script>
<![endif]-->

Tôi không bao giờ khuyên bạn nên làm rối với các đối tượng cửa sổ như thế này.
Aamir Afridi

-2

Tùy thuộc vào cách nội dung trên sự kiện thay đổi kích thước.

Tôi đã tìm ra cách giải quyết ở trên chỉ khi một trang bao gồm nội dung tĩnh, không phải nội dung động. Trong trường hợp động mà nội dung hiện có sẽ được hiển thị lại bởi một số sự kiện kích hoạt như hàm tải lại nội dung, chúng ta cần sử dụng $ (document) .width () hoặc $ (document) .height () để thay thế.

Điều này là do thanh cuộn của cửa sổ. Nếu một trang có thanh cuộn và nội dung chính sẽ được hiển thị lại bằng cách nhấp vào nút “Tải lại”, thanh cuộn sẽ biến mất trong sự kiện. Trong trường hợp đó, $ (window) .width () hoặc $ (window) .height () được thay đổi bởi nội dung hiển thị, không phải do thay đổi kích thước cửa sổ thực tế.

http://www.tech-step.net/?p=466


-3
$(window).resize(function(event)
{
    if (typeof event.target.tagName == 'undefined')
    {
        // ...
    }
});

Điều gì về câu trả lời này thêm / cải thiện các câu trả lời được đánh giá cao khác? Một câu trả lời chỉ có mã là không tốt. Cung cấp lời giải thích.
random_user_name 26/10/12
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.