简体   繁体   English

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

[英]Node.js with Express: Importing client-side javascript using script tags in Jade views?

I've got a node.js express server running with the Jade template engine. 我有一个运行Jade模板引擎的node.js express服务器。

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). 但是,我现在想要专门为这个索引页面包含两个客户端javascript库(因此不是每个页面,这就是为什么我不能把它放在布局的头部)。

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? 但是,这会将脚本加载到完整页面的主体,这不是有效的HTML,对吧?

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. 据我所知,如果我想正确地执行它,脚本应该加载到头部,但是head部分由布局文件处理。

So, how would I properly include these client-side javascript libraries specifically for a certain view/page? 那么,我如何正确地包含这些客户端javascript库专门用于某个视图/页面?

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']
  }
}

I've done the same using the solution from this thread: 我使用这个线程的解决方案做了同样的事情:

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

You can declare a "scripts" variable into view options: 您可以在视图选项中声明“脚本”变量:

app.js: 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: renderScriptTags()帮助程序代码:

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: 进入head部分的布局模板,您将拥有:

- 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): 现在,要在head标记上添加脚本,您只需将脚本推送到jade内容模板(body模板)上的“scripts”变量中:

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

In this way the page will render jquery.js and myscript.js into the head of the page 通过这种方式,页面将jquery.js和myscript.js呈现在页面的头部

UPDATE 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. 您可以像以前一样在布局模板中使用上一个方法的renderScriptTags()帮助器。

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 现在,对于这个特定的视图,你应该正确地渲染jquery.js和myscript.js

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: 通过将所有内容保存在模板/视图中,可以在最新的Jade(0.28.1)中执行正确的方法(tm),而无需在其他地方黑客页面内容(脚本链接):

  • 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

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

Here is an alternate way to do it ( using ShadowCloud's answer ). 这是另一种方法(使用ShadowCloud的答案)。 By generalizing a bit, you can specify both local and remote scripts, and then defer them until after page load: 通过一般化,您可以指定本地和远程脚本,然后将它们推迟到页面加载之后:

app.js: 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 ) layout.jade :(我把它放在body的末尾,先加载可见的东西,但它可以去任何地方)

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

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: 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: 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. 这样,在你的.jade页面中放置块的位置并不重要,它们总是在正确的位置渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 用jade导入jQuery(使用node.js + express) - importing jQuery with jade(with node.js + express) 在Node.js项目上运行客户端javascript - Running client-side javascript on a Node.js project 使用Jasmine和node.js测试客户端javascript代码 - Testing client-side javascript code with Jasmine and node.js 如何使用Node.js在客户端运行可执行文件? - How to run an executable on client-side using Node.js? 从服务器端获取客户端变量(express.js,node.js) - Get variable on client-side from the server-side (express.js, node.js) 如何在Angular / Node.js / Express中将客户端参数传递给服务器端 - How to pass client-side parameters to the server-side in Angular/Node.js/Express 检查用户是否使用node.js登录并表达和更改客户端html的最佳方法 - Best way for checking if a user is logged with node.js and express and change client-side html 我可以在客户端使用PostgreSQL(pg)(express / node.js) - Can I use PostgreSQL (pg) in the client-side (express/node.js) 在客户端重用javascript代码(node.js,快速) - Reuse javascript code on client side (node.js, express) Heroku(Cedar)+ Node + Express + Jade子目录中的客户端javascript文件与foreman + curl本地工作,但在推送到Heroku时不能 - Heroku(Cedar) + Node + Express + Jade Client-side javascript files in subdirectory work locally with foreman+curl but not when pushed to Heroku
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM