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

发布于 2024-10-31 21:21:52 字数 1037 浏览 6 评论 0原文

我有一个使用 Jade 模板引擎运行的 Node.js Express 服务器。

我有一个布局 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,对吗?

据我所知,如果我想正确执行的话,应该将脚本加载到头部,但是头部部分是由布局文件处理的。

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

I've got a node.js express server running with the Jade template engine.

I've got a layout jade file which imports the body of individual views like so:

!!!
html

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

    body
        #header
            h1 Header.

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

        #footer
            p Footer.

For example, the following index page:

p Welcome to the front page.

p This page serves as a now.js test.

This works fine. However, I now want to include two client-side javascript libraries specifically for this index page (and thus not very every page, which is why I cannot put it in the head of layout).

This works:

//- 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.

However, this loads the scripts to the body of the complete page, which is not valid HTML, right?

As far as I know, the scripts should be loaded into the head if I want to do it properly, but the head section is handled by the layout file.

So, how would I properly include these client-side javascript libraries specifically for a certain view/page?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

溺渁∝ 2024-11-07 21:21:52

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

// layout.jade
!!!
html

    head
        title= title || 'Title not set.'
        -each script in scripts 
          script(type='text/javascript', src= script)
    body
        #header
            h1 Header.

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

        #footer
            p Footer.

还有你的“控制器”:

// app.js
app.get('/', function (req, res) {
  res.render({
    scripts: ['jquery.min.js', '/nowjs/now.js']
  }
}

You can have them on the layout and specify which libraries to load on the "controllers".

// layout.jade
!!!
html

    head
        title= title || 'Title not set.'
        -each script in scripts 
          script(type='text/javascript', src= script)
    body
        #header
            h1 Header.

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

        #footer
            p Footer.

And your "controller":

// app.js
app.get('/', function (req, res) {
  res.render({
    scripts: ['jquery.min.js', '/nowjs/now.js']
  }
}
路还长,别太狂 2024-11-07 21:21:52

我使用此线程中的解决方案完成了相同的操作:

http: //groups.google.com/group/express-js/browse_thread/thread/8c2006dc7bab37b1/f9a273c836e0a2ac

您可以在视图选项中声明一个“脚本”变量:

app.js:

app.set('view options', { locals: { scripts: ['jquery.js'] } });  // You can declare the scripts that you will need to render in EVERY page

您可以有一个助手来呈现将脚本标签放入布局的头部

renderScriptTags() 辅助代码:

app.helpers({ renderScriptTags: function(scripts) {
  return scripts.map(function(script) {
    return '<script src="scripts/' + script + '"></script>';
  }).join('\n ');

将脚本标签放入 head 部分的布局模板中,您将拥有:

- renderScriptTags(scripts)

现在,要在 head 标签上添加脚本,您只需将脚本推入“scripts” " 玉石内容模板(正文模板)上的变量:

- scripts.push('myscript.js'); 

这样页面会将 jquery.js 和 myscript.js 渲染到页面的头部

更新

看来最新的 Express 版本可以处理以下本地内容:另一种方式,为了使其正常工作,您可以这样做(尽管我不确定这是最佳解决方案,我需要对此进行深入研究)

您可以使用renderScriptTags() 像以前一样,布局模板中先前方法的帮助程序。

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

app.dynamicHelpers({
  scripts: function(req, res){
    return ['jquery.js']; //this will be available in all views
  }
});

然后,从您的正文模板中添加特定脚本(完全相同)之前):

- scripts.push('myscript.js'); 

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

I've done the same using the solution from this thread:

http://groups.google.com/group/express-js/browse_thread/thread/8c2006dc7bab37b1/f9a273c836e0a2ac

You can declare a "scripts" variable into view options:

app.js:

app.set('view options', { locals: { scripts: ['jquery.js'] } });  // You can declare the scripts that you will need to render in EVERY page

Than you can have an helper that renders the script tags into the head of the layout

renderScriptTags() Helper code:

app.helpers({ renderScriptTags: function(scripts) {
  return scripts.map(function(script) {
    return '<script src="scripts/' + script + '"></script>';
  }).join('\n ');

Into the layout template in the head section you will have:

- renderScriptTags(scripts)

Now, to add a script on the head tag, you'll just need to push the script into the "scripts" variable on your jade content template (body template):

- scripts.push('myscript.js'); 

In this way the page will render jquery.js and myscript.js into the head of the page

UPDATE

It seems that newest express version handles the locals in a different way, to make this work properly, you can do this (I'm not sure it is the optimal solution though, I'd need to dig this a little)

You can use the renderScriptTags() helper of the previous method in your layout template like before.

But don't set the scripts variables into locals, instead create a dynamic helper that will make a scripts variable available in our templates:

app.dynamicHelpers({
  scripts: function(req, res){
    return ['jquery.js']; //this will be available in all views
  }
});

And then, to add a specific script, from your body template (exactly as before):

- scripts.push('myscript.js'); 

Now, for this specific view, you should have jquery.js and myscript.js rendered properly

五里雾 2024-11-07 21:21:52

通过将其全部保留在模板/视图内,可以在最新的 Jade (0.28.1) 中以正确的方式 (tm) 做到这一点,而无需在其他地方破解页面内容(脚本链接):

  • 将头部声明为模板中的命名块:
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

It's possible to do it The Right Way (tm) in the latest Jade (0.28.1) by keeping it all inside templates/views, without hacking page contents (script links) elsewhere:

  • Declare the head as a named block in your template:
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
  • Append your page-specific head elements (including script tags) in your views:
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
公布 2024-11-07 21:21:52

我认为问题(通过简要阅读本文)是您没有“刷新”数组,将其 .length 设置为 0 以删除旧值,因此每个请求可能只是推送越来越多的字符串

I assume the problem (from briefly reading this) is that you are not "flushing" the array, setting its .length to 0 to remove old values, so each request could just be pushing more and more strings

只为守护你 2024-11-07 21:21:52

这是另一种方法(使用 ShadowCloud 的答案)。通过概括一下,您可以指定本地和远程脚本,然后将它们推迟到页面加载后:

app.js:

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')

layout.jade:(我把它在正文的末尾首先加载可见的东西,但它实际上可以去任何地方)

//- 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;

Here is an alternate way to do it ( using ShadowCloud's answer ). By generalizing a bit, you can specify both local and remote scripts, and then defer them until after page load:

app.js:

app.dynamicHelpers({
    scripts: function() {
        //scripts to load on every page
        return ['js/jquery.min.js','js/jquery-ui.min.js','js/all.js'];
    }
});

then, you can add local or remote scripts at any point inside a view

//- 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')

layout.jade: ( I put it at the end of body to load the visible stuff first, but it can go anywhere really )

//- 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;
秋叶绚丽 2024-11-07 21:21:52

我不确定到目前为止这些方法的意义是什么。对我来说,执行以下操作要干净得多...

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

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')

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

I'm not sure what the point of the approaches so far are. To me it is much cleaner to do the following...

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

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')

This way it doesn't matter where in your .jade pages you put your blocks, they will always render in the correct places.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文