Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带Express的Node.js:在Jade视图中使用脚本标记导入客户端javascript?_Javascript_Node.js_Express_Pug - Fatal编程技术网

带Express的Node.js:在Jade视图中使用脚本标记导入客户端javascript?

带Express的Node.js:在Jade视图中使用脚本标记导入客户端javascript?,javascript,node.js,express,pug,Javascript,Node.js,Express,Pug,我有一个node.js express服务器,运行着Jade模板引擎 我有一个布局jade文件,它导入了各个视图的主体,如下所示: !!! html head title= title || 'Title not set.' body #header h1 Header. #content!= body //- this renders the body of an individual view

我有一个node.js express服务器,运行着Jade模板引擎

我有一个布局jade文件,它导入了各个视图的主体,如下所示:

!!!
html

    head
        title= title || 'Title not set.'

    body
        #header
            h1 Header.

        #content!= body //- this renders the body of an individual view

        #footer
            p Footer.
例如,以下索引页:

p Welcome to the front page.

p This page serves as a now.js test.
这个很好用。但是,我现在想为这个索引页面专门包含两个客户端javascript库(因此不是每个页面,这就是为什么我不能把它放在布局的开头)

这项工作:

//- import jquery
script(type='text/javascript', src='./jquery-1.5.2.min.js');

//- import now.js (hosts itself)
script(type='text/javascript', src='/nowjs/now.js')

//- import the chat client
script(type='text/javascript', src='./indexChatClient.js')

p Welcome to the front page.

p This page serves as a now.js test.
但是,这会将脚本加载到完整页面的主体中,这不是有效的HTML,对吗

据我所知,如果我想正确地执行,脚本应该加载到head中,但是head部分由布局文件处理


那么,我如何正确地包含这些专门用于特定视图/页面的客户端javascript库呢?

我已经使用此线程中的解决方案完成了同样的工作:

您可以在视图选项中声明“scripts”变量:

app.js:

app.set('view options', { locals: { scripts: ['jquery.js'] } });  // You can declare the scripts that you will need to render in EVERY page
app.dynamicHelpers({
    scripts: function() {
        //scripts to load on every page
        return ['js/jquery.min.js','js/jquery-ui.min.js','js/all.js'];
    }
});
这样,就可以有一个助手将脚本标记渲染到布局的头部

renderScriptTags()帮助程序代码:

app.helpers({ renderScriptTags: function(scripts) {
  return scripts.map(function(script) {
    return '<script src="scripts/' + script + '"></script>';
  }).join('\n ');
现在,要在head标签上添加脚本,只需将脚本推入jade内容模板(body模板)上的“scripts”变量:

这样,页面将把jquery.js和myscript.js呈现到页面的头部

更新

似乎最新的express版本以不同的方式处理本地人,要使其正常工作,您可以这样做(但我不确定这是否是最佳解决方案,我需要对此进行一点挖掘)

您可以像以前一样在布局模板中使用上一个方法的renderScriptTags()辅助对象

但不要将脚本变量设置为局部变量,而是创建一个动态帮助器,使脚本变量在我们的模板中可用:

app.dynamicHelpers({
  scripts: function(req, res){
    return ['jquery.js']; //this will be available in all views
  }
});
然后,要添加特定脚本,请从您的主体模板(与前面完全相同):


现在,对于这个特定视图,应该正确呈现jquery.js和myscript.js

您可以在布局上放置它们,并指定要在“控制器”上加载哪些库

以及您的“控制器”:


我假设问题(简单阅读本文)在于您没有“刷新”数组,而是将其.length设置为0以删除旧值,因此每个请求可能只是推送越来越多的字符串,这里有一种替代方法(使用ShadowCloud的答案)。通过泛化一点,您可以指定本地和远程脚本,然后将它们延迟到页面加载之后:

app.js:

app.set('view options', { locals: { scripts: ['jquery.js'] } });  // You can declare the scripts that you will need to render in EVERY page
app.dynamicHelpers({
    scripts: function() {
        //scripts to load on every page
        return ['js/jquery.min.js','js/jquery-ui.min.js','js/all.js'];
    }
});
然后,您可以在视图中的任何位置添加本地或远程脚本

//- local script
- scripts.push('js/myPage.js');
//- remote script ( note: this is a schemeless url. You can use http(s)? ones too )
- scripts.push('//platform.twitter.com/widgets.js')
jade:(我把它放在身体的末端,首先装载可见的东西,但它真的可以去任何地方)


在最新的Jade(0.28.1)中,通过将所有内容保存在模板/视图中,而不在其他地方对页面内容(脚本链接)进行黑客攻击,可以以正确的方式(tm)完成此操作:

  • 在模板中将头部声明为命名块:
doctype 5 html 头 //命名块允许我们在每个页面中附加自定义标题条目 堵头 头衔 链接(rel='stylesheet',href='/css/style.css') 脚本(type=“text/javascript”,src=“/js/some default script.js”) 身体 块内容
  • 在视图中附加特定于页面的标题元素(包括脚本标记):
扩展布局 //这里我们引用模板头并附加到它 块附加头 meta(name=“something”,content=“blah”) 链接(href=“/css/other.css”,rel=“stylesheet”,type=“text/css”) 风格 福娃{ 位置:绝对位置; } 脚本(src=“/js/page-specific script.js”) 块内容 #页面内容如下
我不确定到目前为止这些方法的意义是什么。对我来说,做以下事情要干净得多

layout.jade:

doctype html
html
  head
    title= title
    block headscripts  // placeholder for scripts that need to be in the <head>
    link(rel='stylesheet', href='/styles/style.css')
    block styles       // placeholder for styles
  body
    block content
    script(src='/libs/jquery/dist/jquery.min.js') // this will render before all scripts in every page
    block scripts  // placeholder for scripts that go in the body
doctype html
html
头
头衔
块头脚本//需要在中的脚本的占位符
链接(rel='stylesheet',href='/styles/style.css')
块样式//样式的占位符
身体
块内容
脚本(src='/libs/jquery/dist/jquery.min.js')//这将在每个页面中的所有脚本之前呈现
阻止脚本//正文中脚本的占位符
somepage.jade:

extends layout

block styles  // this will render in the <head>
  link(rel='stylesheet', href='/styles/films.css')
  link(rel='stylesheet', href='/styles/pagination.css')

block headscripts  // this will also render in the <head>
  script(src='/js/somescript.js')

block content
  h1= title
  div.someotherstuff

block scripts  // this will render at the end of the body
  script(src='/js/libs/someotherscript.js')
  scirpt(src='/libs/doT/doT.js')
扩展布局
块样式//这将在
链接(rel='stylesheet',href='/styles/films.css')
链接(rel='stylesheet',href='/styles/pagination.css')
块头脚本//这也将在
脚本(src='/js/somescript.js')
块内容
h1=标题
什么别的
块脚本//这将在正文末尾渲染
脚本(src='/js/libs/someotherscript.js')
scirpt(src='/libs/doT/doT.js')

这样,无论在
.jade
页面的何处放置块,它们都将始终呈现在正确的位置。

您只需将它们添加到常规脚本列表中,然后将这些脚本添加到常规布局文件的头部。但是,我需要为特定视图设置特定脚本。您可以通过将视图特定脚本推入脚本变量,将其设置到视图中,以便在布局标头中呈现,这不正是您试图实现的吗?@ShadowCloud,我不确定,您将脚本推到哪里?这是否会导致脚本在其他视图中加载,以及脚本变量似乎在主作用域中声明?@Tom:我注意到,在较新版本的express中,局部变量的处理方式有所不同,我在更新的答案中为您提供了一个修改后的解决方案(可能有更好的解决方案,但它应该可以工作)@ShadowCloud在哪里调用script.push?在特定视图中?我想这会更好,因为脚本不应该在视图中设置,而应该在控制器中设置。我更喜欢在控制器上设置脚本,这样您就可以轻松地重用代码。您是怎么做的
//- local script
- scripts.push('js/myPage.js');
//- remote script ( note: this is a schemeless url. You can use http(s)? ones too )
- scripts.push('//platform.twitter.com/widgets.js')
//- Bring the scripts into a client-side array,
//-    and attach them to the DOM one by one on page load
script
    var page_scripts = !{'["' + scripts.join('","') + '"]'};
    function loadJS() {
        for(var i in page_scripts) {
            var e = document.createElement("script");
            e.src = page_scripts[i];
            document.body.appendChild(e);
        }
    }
    // Check for browser support of event handling capability
    if (window.addEventListener)
        window.addEventListener("load", loadJS, false);
    else if (window.attachEvent)
        window.attachEvent("onload", loadJS);
    else window.onload = loadJS;
doctype 5 html head // named block allows us to append custom head entries in each page block head title= title link( rel='stylesheet', href='/css/style.css' ) script( type="text/javascript", src="/js/some-default-script.js" ) body block content extends layout // here we reference the template head and append to it block append head meta( name="something", content="blah" ) link( href="/css/another.css", rel="stylesheet", type="text/css" ) style div.foo { position: absolute; } script( src="/js/page-specific-script.js" ) block content #page-contents-follows
doctype html
html
  head
    title= title
    block headscripts  // placeholder for scripts that need to be in the <head>
    link(rel='stylesheet', href='/styles/style.css')
    block styles       // placeholder for styles
  body
    block content
    script(src='/libs/jquery/dist/jquery.min.js') // this will render before all scripts in every page
    block scripts  // placeholder for scripts that go in the body
extends layout

block styles  // this will render in the <head>
  link(rel='stylesheet', href='/styles/films.css')
  link(rel='stylesheet', href='/styles/pagination.css')

block headscripts  // this will also render in the <head>
  script(src='/js/somescript.js')

block content
  h1= title
  div.someotherstuff

block scripts  // this will render at the end of the body
  script(src='/js/libs/someotherscript.js')
  scirpt(src='/libs/doT/doT.js')