一个JS文件的多个页面
我通常把所有的JavaScript脚本放到一个文件中,例如scripts.js
(HTTP请求越less越好)。 所以,正如所料,一些页面需要一些脚本,有些则不是。
要定位一个特定的页面,我使用类似于:
if ($("body#share").length > 0) { // Place the logic pertaining to the page with ID 'share' here... } // The file / script continues...
其他或更好的build议? 谢谢!
澄清:我没有find合并多个JS文件到一个大文件和保留多个单独的JS文件之间的利弊。 答案肯定是“取决于情况”(我们知道)。 我的问题是,假设我所有的JS逻辑都放在一个大文件中,那么只有当相应的页面被加载时,我如何才能使一个特定的(块)脚本运行? 我曾经使用的一种方法是使用if ($('#id-of-target-element')) { /* run the script */}
; 有没有更好的办法?
我喜欢保罗·爱尔兰的方法 ……你不必完全按照它,但总的想法是非常稳固的。
这可能看起来像这样的例子
HTML
<body id="share">
您的网页特定的JavaScript
YourNamespace = { share : { init : function(){ // Place the logic pertaining to the page with ID 'share' here... } } }
保罗·爱尔兰人的Javascript使魔术发生
UTIL = { fire : function(func,funcname, args){ var namespace = YourNamespace; // indicate your obj literal namespace here funcname = (funcname === undefined) ? 'init' : funcname; if (func !== '' && namespace[func] && typeof namespace[func][funcname] == 'function'){ namespace[func][funcname](args); } }, loadEvents : function(){ var bodyId = document.body.id; // hit up common first. UTIL.fire('common'); // do all the classes too. $.each(document.body.className.split(/\s+/),function(i,classnm){ UTIL.fire(classnm); UTIL.fire(classnm,bodyId); }); UTIL.fire('common','finalize'); } }; // kick it all off here $(document).ready(UTIL.loadEvents);
所以你直接在上面看到的行将启动以下
YourNamespace.common.init() YourNamespace.share.init() YourNamespace.common.finalize()
阅读他的博客文章和一些与之相关的变化。
类似的问题已经被问到,正确的答案是,而且总是会的
这取决于实际情况。
但是,如果您的担心是关于最小化往返时间 (RTT),那么肯定是这样
将外部脚本合并为尽可能less的文件可减lessRTT,并延迟下载其他资源。
保持尽可能less是件好事,但不一定要严格保存在一个文件中。
让我们来看看为什么是这样。
虽然将代码分区到模块化的软件组件是一个很好的工程实践,但是将模块一次一个地导入HTML页面可能会大大增加页面加载时间。 首先,对于空caching的客户端,浏览器必须为每个资源发出一个HTTP请求,并产生相关的往返时间。 其次,大多数浏览器会阻止在下载和parsingJavaScript文件时加载页面的其余部分。
这些图像更清楚地表明了为什么将大量JavaScript文件合并到更less的输出文件中可以显着减less延迟:
所有文件都是连续下载的,共需要4.46秒才能完成。
将13个js文件合并成2个文件后: 同样的729千字节现在只需要1.87秒的下载
在Siku-Siku.Com给出的澄清之后编辑:对不起! 我完全误解了你的问题。 我不知道有什么更好的方法来使一个特定的(块)脚本只有当相应的页面加载时运行。 我认为你的方式是够好的。
另一个select是你可以在HTML代码中
<script> callYourJSFunctionHere(); /*Things you would want to happen on Page load*/ </script>
这将遵循页面的正常stream程。 因此,如果您正在使用页面上的元素,则在浏览器加载所有元素之后,您需要将此<script>
部分放置在页面的底部。
我不是100%确定这是比当前的解决scheme更有效,但另一方面,它会告诉某人看着你的HTML页面,当页面加载时将运行JavaScript。 这在维护方面可能会有所帮助….没有太多的猜测游戏是在页面加载时运行的脚本。
希望这可以帮助!
你的build议似乎没问题。 然而,我将使用HTML 5数据属性来标记每个页面,如下所示:
<body data-title="my_page_title">
你可以通过检查这个属性(jQuery 1.4.3以上版本)来编写有条件的JavaScript代码:
if ($("body").data("title") === "my_page_title") { // Place the logic pertaining to the page with title 'my_page_title' here... }
这可以让您以合理的方式系统地将某个页面的所有代码分组
好。 让我们希望,代码示例会说得更好,而不是文本墙:
你的one-and-only.js
文件:
var MY_SITE = { // you have one namespace-object where you hold all your stuff main_page: { // inside you have smaller chunks, for specific pages or widgets // this one is for main page _init: function () { ... }, ... showSplashScreen: function () { ... } }, ... // but there are other pages contacts: { ... }, // or widgets cool_menu: { ... }, // and maybe you want to put common functions into dedicated block global_utilities: { ... }, // and of course - the loader _start: function () { // here we simply call one _init of the page module that was specified this[PAGE_TYPE]._init(); // and more tricky stuff - we can search the page for elements // that contain special data-attribute, collect them var widgets = $('[data-our-widget]').each().getAttributeValue( 'data-or-widget' ); // and then _init each of those widgets just like we did with main page widgets.forEach( function (v) { this[v]._init(); } } }; document.on('ready', MY_SITE.start); // here we assume some random js framework
页面上的<script>
标签:
<script>var PAGE_TYPE = 'main_page';</script> <script src="one-and-only.js" />
您网页上的“魔术”元素:
<div id="whatever" data-our-widget="cool_menu"> ... </div>
免责声明: 这是高层次的概述! 实施细节可能也应该有所不同,具体取决于您的需求。
你的问题是问如何只加载基于特定页面的脚本块。 然而,既然你所说的目标是尽量减lessHTTP请求(和stream量,我假设),我认为我的独特(复杂)实现至less与这个问题有关,如果不是你的方法的一个很好的替代/补充。
我在一个embedded式应用程序中使用它,在这个应用程序中,我将所有的javascript文件合并为一个大的文件,以减lesshttp请求 我也必须弄清楚caching方法。 一个120kb的JavaScript文件,除了几张大小适中的图片需要一段时间才能加载,当使用一个准系统50kb的networking服务器。
首先,我使用YUI Compressor来压缩我的JavaScript文件,因为这是一个简单的方法来节省带宽。
我发现一个很酷的“function”是,如果你链接到任何东西(css,js,img),就像下面这样,你只需加载文件并忽略通过'?'的参数。 在'src'中:
<script type="text/Javascript" src="js/all.js?2382a97f099f42cc43c1b616cd24f281"></script>
现在,这个看似随机的数字和字母混杂,实际上就是javascript文件的md5校验和了! 然后,我修改了我的服务器的相关扩展(CSS,JS,IMG等)的响应头永不过期。 这个头文件不会被发送到html文件,因为我们总是想要这些文件的最新版本。
Cache-Control:max-age=290304000
这意味着客户端将只加载一次JavaScript文件,直到校验和发生变化。 caching通过查看整个请求,包括文件参数。
我实际上用C代码编译我的html / js / css /图像文件,所以我有一个perl脚本在编译之前自动将这些md5校验和插入到html文件中。 这显然不适用于你的情况,但只要你有一个服务器端的语言来帮助你,你可以用任何方式来处理它。 例如,你可以让php计算校验和,或者你可以让php将校验和存储在数据库或平面文件中,以便轻松查找它们。 为了标记php重新计算校验和,可以检查文件时间,或者删除数据库条目/平面文件。
我意识到这是很多前期工作,可能不是你所追求的,但对我来说却是奇妙的。 对我来说性能上的提升是不可思议的。 第一页加载非常慢(8.5秒),但在此之后,所有的脚本,CSS和图像都被caching了。 在相同的应用程序内加载的新页面下降到〜300ms。
如何testingwindow.location
? 这似乎是我明显的方式。
或者就像你已经做的那样,testing所需的元素在那里。 这是一个相当强大的方法,我没有看到任何错误的。
这将是一个高层次的概述,但我build议使用Backbone来组织每个“视图”(或页面)的逻辑。我使用根元素并更改该元素的类以在其他视图(或状态)的布局。 然后,您可以按类组织次要样式,并在ID下保留主要样式。
HTML
<div id="layout" class="default"> <!-- PUT DEFAULT HTML IN HERE --> </div> <script id="shareTemplate" type="text/html"> <!-- PUT SHARE HTML IN HERE --> </script>
CSS
#layout { /* primary style */ } #layout.share { /* secondary style */ }
JavaScript的
window.LayoutView = Backbone.View.extend({ el: "#layout", shareTemplate: _.template($("#shareTemplate").html()), initialize: function() { this.render(shareTemplate, data); this.el.className = "share"; }, render: function(template, data) { $(this.el).html(template(data)); return this; } }); window.Layout = new LayoutView;
正如你所说的那样,分割/合并文件的想法确实取决于情况。
我不认为可以有更好的解决scheme ,因为我已经看到许多大网站实施类似的战略,虽然比CSS更多的CSS。
例如(摘自facebook):
<body class="hasLeftCol home fbx hasSlimHeader safari4 win Locale_en_US defaultScrollbar">
你可以从中获得更多的好处。 你可以有select地使用class属性将一些JS代码应用到页面组中。
即。
if $('body.pagesThatHaveThisClass').length > 0) {.... code ...} if $('body#singlePageWithThisId').length > 0) {.... code ...}
否则,有许多基于JS / jQ的菜单会自动为当前页面提供不同的样式。 您可以将window.location与特定的地址相匹配。
即。
if (window.top.location.href == 'http://domain.com/mypage1.html') { .... code ....}
甚至
switch (window.top.location.href) { case 'http://domain.com/mypage1.html' : { .... code ....} case 'http://domain.com/mypage2.html' : { .... code ....} }
我仍然会更喜欢你的技术,因为你可以将多个页面的代码组合在一起。 我能想到的使用第二种方法的唯一原因是当JS人无法访问页面的HTML来改变类/ ID等
希望这是你正在寻找的!
基于以下假设:您网站上的所有不同页面被分类或至less在逻辑上被分组到不同的“视图模型”中,以不同types的页面的不同视图模型(例如“search结果”,“博客post”,“首页“,”单一blogpost“等),你可以有一个单一的JavaScript文件,其中包含所有网站的共同脚本,并为每个视图模型(如果你认为是必要的)特定的脚本。
然后,您可以让服务器将视图模型的名称插入(例如)HTML数据标记,以供将来由JavaScript使用,并在主脚本库之后添加一个附加的脚本标记。
例如:
<head> <!-- Two JavaScript files, one for the common functionality, and one for the view model specfic --> <script type="text/javascript" src="path/to/scriptslib.js"></script> <script type="text/javascript" src="path/to/viewmodel.front_page.js"></script> </head> <body data-view-model="front_page"> ... </body>
在scriptslib.js
:
var GlobalSettings = {}, ViewModel = {}; $(function () { // Save the view model in a variable when the body's been loaded GlobalSettings.viewModel = $("body").attr("data-view-model"); // Assuming that the viewmodel JavaScript file has been loaded, call a method that it'll have by convention here ViewModel.initialize(); // Additionally, you can later test for specific view models and perform necessary actions, if needed if (viewModel === "front_page") { // ... } });
然后,在viewmodel.front_page.js
(或任何其他视图模型文件)中:
ViewModel.FrontPage = { // data and methods specific for this view model } ViewModel.initialize = function () { // do stuff specific for this view model this.FrontPage.someFunction(); };
请注意,我在这里描述的方法是依靠页面重新加载在网页之间切换的网站。 如果您使用Ajax在页面之间切换,则希望JavaScriptdynamic加载新视图模型并执行它们。
希望这可以为你工作;)
你可以按照你的方法,但是假设你的“鸡尾酒”JavaScript文件有20万行代码,并且把它包含在你的所有html文件中,甚至那些显示“404”或“500”带宽?
我select为每个HTML页面使用不同的js,以及跨多个页面使用的任何js将其转储到“utils.js”或任何你想调用它的地方,例如
\www \pages \index.html \dashboard.html \account.html \ ... \scripts \index.js <- for index.html \dashboard.js <- for dashboard.html \account.js <- for account.html \ ... \utils.js|shared.js|sharedlib.js <- used by all pages
所以基本上会导致:
- 1请求的HTML
- 1为页面脚本
- 1为共享脚本,如果使用
- n为CSS,但我认为是1
这只是我的两分钱..