在window.onresize上有条件地加载脚本

时间:2014-07-30 03:47:18

标签: javascript jquery modernizr

我想根据窗口大小有条件地加载一些文件(javascript和css)。我希望这些文件是"交换"在窗口调整大小时,还要在网站首次加载时正确加载。我正在使用Modernizr与yepnope库这样做。但是,代码仅适用于加载,而不适用于调整大小。我使用警报检查了调整大小事件,它似乎正确触发,但该函数只运行onlaod。当我调整浏览器大小时,它似乎闪烁,就像它试图在不同文件之间切换一样。

我不是很擅长js,所以我无法弄清楚出了什么问题。任何帮助将不胜感激。这是我正在使用的代码:

<script src="scripts/modernizr.custom.js"></script> 
<script>
function myLoader(){

    Modernizr.load([
      {
      load: [  

      'scripts/jquery-1.11.1.min.js' 

      ]
    },
        {
            test: Modernizr.mq('(max-width:600px)'),
            yep: 
            [
                'css/jquery.mobile-1.4.3.min.css', 
                'css/custom.css',
                'scripts/jquery.mobile-1.4.3.min.js'
            ],
            nope:
            [
               'css/mystyle.css'
            ]
        }
    ]);
}

window.onresize = myLoader();
window.onload = myLoader();
</script>

3 个答案:

答案 0 :(得分:0)

所以这里的问题是你的括号

window.onresize = myLoader();
window.onload = myLoader();

您所说的是将window.onresize的值设置为myLoader上的返回值(您没有明确设置,因此它是undefined

您希望做什么,将其设置为参考 myLoader

考虑这个例子

function hello() {
    return 'world'
}

hello()等于world,其中hello等于function hello() {return 'world'}。没有括号表示返回函数本身,括号表示计算函数并返回其返回值。

要解决您的问题,只需删除

即可
window.onresize = myLoader;
window.onload = myLoader;

答案 1 :(得分:0)

我担心这个问题比帕特里克意识到的要复杂得多 - 但他对括号的看法是正确的。

tl; dr: 要么考虑使用单独的桌面和移动网站,要么尝试构建您的网站,以便所有窗口大小都使用相同的样式表和脚本


这就是为什么你尝试过的东西不起作用。

首先,Modernizr.load()只加载内容 - 它不会卸载它们。那么你所拥有的将会做到这样的事情:

# page loads
if screen width <= 600px:
  load 'css/jquery.mobile-1.4.3.min.css'
  load 'css/custom.css'
  load 'scripts/jquery.mobile-1.4.3.min.js'
else:
  load 'css/mystyle.css'

# page is resized
if screen width <= 600px:
  load 'css/jquery.mobile-1.4.3.min.css'
  load 'css/custom.css'
  load 'scripts/jquery.mobile-1.4.3.min.js'
else:
  load 'css/mystyle.css'

# page is resized again
if screen width <= 600px:
  load 'css/jquery.mobile-1.4.3.min.css'
  load 'css/custom.css'
  load 'scripts/jquery.mobile-1.4.3.min.js'
else:
  load 'css/mystyle.css'

# etc

即。他们会相互加载。

因此,如果屏幕上加载了320px,则会触发一个resize事件,然后宽度为800px,您将同时加载所有4个文件。这两组样式将同时出现,即使屏幕宽度超过600px,jQuery Mobile JS仍然会处于活动状态。

当您通过拖动浏览器的边缘来调整页面大小时,它实际上会触发调整大小事件的LOADS,所以实际上您可能实际上已经加载了每个文件的几十个副本。 JS将运行多次,这可能会导致稳定性问题(因为它只能运行一次)。

这可能不是你想要的。

如果你想在两者之间切换,你需要在屏幕调整大小时删除以前的CSS和JS。但事实并非那么简单。

CSS

CSS是声明性的。在任何给定时间DOM中的样式表被“添加”到一个样式树中,然后应用于DOM。这意味着重复的样式表可能不会导致任何问题(您只是重述相同的规则),但它肯定是不整洁的。这也意味着如果您删除样式表,则不再应用这些样式。

所以你可以做这样的事情:

function myLoader() {
  $('[href="css/jquery.mobile-1.4.3.min.css"]').remove();
  $('[href="css/custom.css"]').remove();
  $('[href="css/mystyle.css"]').remove();

  // then the rest
}

在(可能)加载其他样式表之前删除任何现有的样式表意味着您在任何给定时间只能拥有DOM中所期望的样式。

但这仅仅是一个例子。使用Media Queries会更加高效和灵活。

JS

JavaScript在这里更复杂。这是程序性的 - 当您执行JavaScript时,它会更改页面的状态。它可以定义函数,向DOM添加新元素,设置事件处理程序等等。

如果从DOM中删除脚本标记,则这些状态更改不会神奇地撤消。事实上,可靠地逆转脚本的效果是非常困难的。这有点像将一些奶油搅拌成鸡巴尔蒂,然后发现你有一个乳糖不耐症的人来吃晚餐......很难再把它拿出来。

撤消已执行脚本效果的唯一方法是刷新页面。显然这对于​​用户来说真的很烦人,在页面中失去位置,不得不等待它再次加载等等。

所以...

您有2个选项。

  1. 使两个版本(窄屏幕和宽屏幕)都使用相同的JS - 所以无论如何加载它(就像你使用jQuery一样)。这或者意味着让您的宽屏幕版本也可以与jQuery Mobile一起使用,或者使您的窄版本无需 jQuery Mobile。请注意我上面关于使用媒体查询为不同屏幕尺寸提供不同样式的评论。

  2. 放弃调整大小的动作。用户在会话期间调整屏幕大小的可能性有多大?如果您的网站不同,需要完全不同的样式和脚本,也许您只需检测页面加载,然后将它们发送到“桌面”或“移动”网站,然后在会话的其余部分保留它。

答案 2 :(得分:0)

感谢Patrick和Stu提供的非常有用的答案!

Stu:我确实注意到CSS重叠的问题,而且无法“卸载”。您对提出的解决方案也是正确的。从性能的角度来看,放弃调整大小是有道理的。但是,仅在理论基础上,您可以通过添加和删除特殊类来克服一旦加载后重叠的样式问题(如果它只是一个css的问题),然后用这些修改你的css。也许不是最有效或最优雅的解决方案,但它会是这样的:

<script src="scripts/modernizr.custom.js"></script>
         <script src="scripts/jquery-1.11.1.min.js"></script> 
<script>
      function myLoader(){
         Modernizr.load([
         {
              test: Modernizr.mq('only screen and (max-width:600px)'),
              yep:[
                'css/jquery.mobile-1.4.3.min.css', 
                'css/custom.css',
                'scripts/jquery.mobile-1.4.3.min.js'
               ],
               nope:[
               'css/mystyle.css'
               ],
               complete:function(){
                if(window.innerWidth<601){
                    $('body').removeClass('lrgScreen');
                    $('body').addClass('jqMobile');
                }else{
                  $('body').removeClass('jqMobile');
                  $('body').addClass('lrgScreen');
                }

               }
         }
         ]);
       }

      window.onresize = myLoader;
      window.onload = myLoader;
    </script>