如何使用Express/Jade在AJAX中正确呈现局部视图并加载JavaScript文件?
摘要 我正在为我的web应用程序使用Express+Jade,我正在努力为AJAX导航渲染部分视图 我有两个不同的问题,但它们是完全相连的,所以我把它们放在同一篇文章里。 我想这将是一篇很长的文章,但我保证如果你已经为同样的问题挣扎过的话,这会很有趣。如果有人花时间阅读并提出解决方案,我将不胜感激 TL;博士:2个问题如何使用Express/Jade在AJAX中正确呈现局部视图并加载JavaScript文件?,ajax,layout,express,pug,templating,Ajax,Layout,Express,Pug,Templating,摘要 我正在为我的web应用程序使用Express+Jade,我正在努力为AJAX导航渲染部分视图 我有两个不同的问题,但它们是完全相连的,所以我把它们放在同一篇文章里。 我想这将是一篇很长的文章,但我保证如果你已经为同样的问题挣扎过的话,这会很有趣。如果有人花时间阅读并提出解决方案,我将不胜感激 TL;博士:2个问题 对于使用Express+Jade的AJAX导航,渲染视图片段的最干净的和最快的方法是什么 如何加载与每个视图相关的JavaScript文件 要求 我的Web应用需要与已禁用
- 对于使用Express+Jade的AJAX导航,渲染视图片段的最干净的和最快的方法是什么
- 如何加载与每个视图相关的JavaScript文件李>
- 我的Web应用需要与已禁用的用户兼容
JavaScript - 如果启用了JavaScript,则只有页面本身的内容(而不是 整个布局)应该从服务器发送到客户端
- 该应用程序需要速度快,并加载尽可能少的字节
问题1:我尝试了什么 解决方案1:为AJAX和非AJAX请求提供不同的文件 我的布局。jade是:
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
我的页面已满。jade是:
extends layout.jade
block content
h1 Hey Welcome !
我的页面是:
h1 Hey Welcome
最后在router.js(Express)中:
缺点:
app.use(function (req, res, next) {
res.renderView = function (viewName, opts) {
res.render(viewName + req.xhr ? null : '_full', opts);
next();
};
});
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
else
block content
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
// Specific JS files go there
block extraJS
else
block content
// Specific JS files go there
block extraJS
- 正如你可能猜到的,每次我编辑视图时,我都必须编辑两次 我需要改变一下。相当令人沮丧
解决方案2:与“include”相同的技术` 我的布局。jade保持不变:
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
我的页面已满。jade现在是:
extends layout.jade
block content
include page.jade
My页面。jade包含实际内容,没有任何布局/块/扩展/包括:
h1 Hey Welcome
我现在在router.js(Express)中看到:
优势:
app.use(function (req, res, next) {
res.renderView = function (viewName, opts) {
res.render(viewName + req.xhr ? null : '_full', opts);
next();
};
});
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
else
block content
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
// Specific JS files go there
block extraJS
else
block content
// Specific JS files go there
block extraJS
- 现在我的内容只定义一次,这样更好
app.use(function (req, res, next) {
res.renderView = function (viewName, opts) {
res.render(viewName + req.xhr ? null : '_full', opts);
next();
};
});
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
else
block content
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
// Specific JS files go there
block extraJS
else
block content
// Specific JS files go there
block extraJS
- 我一页还需要两个文件
- 我必须在每条路线上的Express中使用相同的技巧。我 刚把我的代码重复问题从Jade转移到Express。啪
解决方案3:与解决方案2相同,但修复了代码重复问题。 使用,我可以在middleware.js中定义我自己的
渲染
函数:
app.use(function (req, res, next) {
res.renderView = function (viewName, opts) {
res.render(viewName + req.xhr ? null : '_full', opts);
next();
};
});
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
else
block content
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
// Specific JS files go there
block extraJS
else
block content
// Specific JS files go there
block extraJS
然后将router.js(Express)更改为:
保持其他文件不变
优势
- 它解决了代码重复问题
- 我一页还需要两个文件
- 定义我自己的
方法感觉有点脏。毕竟,我 希望我的模板引擎/框架能为我处理这个问题renderView
解决方案4:将逻辑转移到Jade 我不喜欢在一个页面上使用两个文件,所以如果我让Jade来决定渲染什么而不是Express呢?乍一看,我觉得很不舒服,因为我认为模板引擎应该而不是处理任何逻辑。但是让我们试试看 首先,我需要向Jade传递一个变量,该变量将告诉它请求的类型: 在middleware.js(Express)中 因此,现在我的布局。jade将与以前相同:
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
而我的页面。jade将是:
if (!locals.xhr)
extends layout.jade
block content
h1 Hey Welcome !
extends layout.jade
block content
h1 Hey Welcome !
block extraJS
script(src="js/page_a.js")
很好,嗯?但这不起作用,因为在Jade中条件扩展是不可能的。因此,我可以将测试从页面.jade移动到布局。jade:
app.use(function (req, res, next) {
res.renderView = function (viewName, opts) {
res.render(viewName + req.xhr ? null : '_full', opts);
next();
};
});
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
else
block content
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
// Specific JS files go there
block extraJS
else
block content
// Specific JS files go there
block extraJS
和页面。jade将返回:
extends layout.jade
block content
h1 Hey Welcome !
优势:
app.use(function (req, res, next) {
res.renderView = function (viewName, opts) {
res.render(viewName + req.xhr ? null : '_full', opts);
next();
};
});
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
else
block content
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
// Specific JS files go there
block extraJS
else
block content
// Specific JS files go there
block extraJS
- 现在,我每页只有一个文件
- 我不必在每条路线或每条路线上重复
测试 看法req.xhr
app.use(function (req, res, next) {
res.renderView = function (viewName, opts) {
res.render(viewName + req.xhr ? null : '_full', opts);
next();
};
});
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
else
block content
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
// Specific JS files go there
block extraJS
else
block content
// Specific JS files go there
block extraJS
- 我的模板中有逻辑。不好
总结 这些都是我想到并尝试过的技巧,但没有一种真正让我信服。我做错什么了吗?是否有更清洁的技术?还是应该使用其他模板引擎/框架?
问题2 如果视图有自己的JavaScript文件,会发生什么情况(使用任何这些解决方案)? 例如,使用解决方案#4,如果我有两个页面,page#a.jade和page#b.jade,它们都有自己的客户端JavaScript文件js/page#a.js和js/page#b.js,在AJAX中加载这些页面时会发生什么 首先,我需要在布局中定义一个
extraJS
块。jade:
app.use(function (req, res, next) {
res.renderView = function (viewName, opts) {
res.render(viewName + req.xhr ? null : '_full', opts);
next();
};
});
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
else
block content
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
// Shared JS files go here
script(src="js/jquery.min.js")
// Specific JS files go there
block extraJS
else
block content
// Specific JS files go there
block extraJS
然后页面a.jade将是:
if (!locals.xhr)
extends layout.jade
block content
h1 Hey Welcome !
extends layout.jade
block content
h1 Hey Welcome !
block extraJS
script(src="js/page_a.js")
如果我在我的URL栏(非AJAX请求)中键入localhost/page_a
,我将得到以下内容的编译版本:
doctype html
html(lang="fr")
head
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
h1 Hey Welcome A !
script(src="js/jquery.min.js")
script(src="js/page_a.js")
doctype html
html(lang="fr")
head
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
h1 Hey Welcome B !
script(src="js/page_b.js")
script(src="js/jquery.min.js")
script(src="js/page_a.js")
看起来不错。但是如果我现在使用AJAX导航进入page_b
,会发生什么呢?我的页面将是以下内容的编译版本:
doctype html
html(lang="fr")
head
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
h1 Hey Welcome A !
script(src="js/jquery.min.js")
script(src="js/page_a.js")
doctype html
html(lang="fr")
head
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
h1 Hey Welcome B !
script(src="js/page_b.js")
script(src="js/jquery.min.js")
script(src="js/page_a.js")
js/page_a.js和js/page_b.js都加载在同一页面上。如果存在冲突(相同的变量名等),会发生什么情况?
另外,如果我使用AJAX返回到localhost/page_a,我会得到以下结果:
doctype html
html(lang="fr")
head
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
h1 Hey Welcome B !
script(src="js/page_a.js")
script(src="js/jquery.min.js")
script(src="js/page_a.js")
相同的JavaScript文件(page_a.js)在同一页面上加载了两次!它是否会导致冲突,每次事件都会重复发生?
不管是不是这样,我不认为这是干净的代码
所以你可能会说特定的JS文件应该在我的块内容中
,这样当我转到另一个页面时,它们就会被删除。因此,我的布局.jade应该是:
if (!locals.xhr)
doctype html
html(lang="fr")
head
// Shared CSS files go here
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
block content
block extraJS
// Shared JS files go here
script(src="js/jquery.min.js")
else
block content
// Specific JS files go there
block extraJS
对吧??错误……如果我转到localhost/page\u a
,我将得到以下内容的编译版本:
doctype html
html(lang="fr")
head
link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
body
div#main_content
h1 Hey Welcome A !
script(src="js/page_a.js")
script(src="js/jquery.min.js")
正如您可能已经注意到的,js/page_a.js实际上是在b中加载的