无法在客户端上呈现EJS模板

我正在快速编写应用程序,我使用ejs作为视图/模板引擎。

在path/artists ,我正在呈现艺术家涵盖的视图artists.ejs 。 当点击一个封面,我想要一个AJAX调用来检索相应的数据,把它放在我的艺术家artist.ejs模板/视图中,并在封面下的HTML中显示这个模板。

我已经看到这个相关的问题,但它并没有解决我的用例。

一切似乎清晰,但我不能用模板呈现数据。 我想编译模板服务器端,将其发送到客户端准备使用,然后在需要的时候用来自AJAX调用的数据填充它。

我做了什么:

当调用/artists ,使用ejs.compile(str, opt)在服务器端进行编译:

 router.get('/artists', function(req, res) { // Compile artist template fs.readFile('views/artist.ejs', "utf-8", function(err, template) { // Convert template file to string artist_template = ejs.compile(template); // Compile template res.render('artists.ejs', {template: artist_template}); // render page with compiled template }); 

我负责将文件转换为string,因为ejs编译器只能使用String(与Jade .compileFile相比)

然后在客户端,我抓取这个函数:

 <script> var template = <%= template %> </script> 

然后在另一个脚本中,我用AJAX调用来检索数据:

 $.get('/artists/'+artist_name, function(data) { var html = template({artist: data}); $('#artist-page').html(html); } 

但是当我打电话时,我收到:

未捕获的ReferenceError:fn未定义

当我打电话给模板时,我收到:

未捕获的ReferenceError:opts未定义。

函数fn硬编码的吗? 我已经阅读了EJS和Jade的文档,但是对于我的问题没有什么相关的信息。

我是否也需要客户端的模板?

在编译客户端时,需要在服务器端使用client选项。 从文档:

  • client如果为true ,则编译可在浏览器中呈现的function,而无需加载EJS运行系统

https://github.com/mde/ejs#options

你的服务器端代码片段应该是:

 // Compile artist template fs.readFile('views/artist.ejs', "utf-8", function(err, template) { artist_template = ejs.compile(template, {client: true}); // Use client option res.render('artists.ejs', {template: artist_template}); }); 

我最终find了一个解决方法来解决我的问题,我的理解是你可以用两种不同的方式来解决问题:

1)我做了什么:读取并保存模板作为string,然后使用ejs运行时脚本呈现客户端。

 // In controller.js var templates = {}; templates.template1 = fs.readFileSync(filePath1, 'utf-8'); // Read template as a string templates.template2 = fs.readFileSync(filePath2, 'utf-8'); ... res.render('app.ejs', {templates: templates}); // Send templates in view // In view app.ejs <script type="text/javascript"> var templates = <%- JSON.stringify(templates) %>; // Get templates object (object of strings) </script> <script type="text/javascript" src="/JS/ejs.min.js"></script> <!-- Load ejs RunTime --> // In site.js - javascript client/public file $.get('/artists', function(data) { var html = ejs.render(templates.template1, data); // Render ejs client side with EJS script (template1 corresponds to the artists template) $('#artists-wrapper').html(html); // Sets HTML }); 

因此,我发送所有我的模板在第一页加载,然后我在客户端呈现请求的页面。 根据我读到的兴趣,你只能通过AJAX调用发送JSON对象(你的数据),而不是整个页面,使你的请求轻。 所有的模板只有第一个负载很重。

2)我想按照@RyanZim的做法来回答:将模板服务器端编译成函数,发送它们,然后在客户端调用它们:template(data)。 如果我理解的很好,在这种情况下不需要EJS客户端库,我的模板不再是string,而是函数:

 // In controller.js var templates = {}; templates.template1 = ejs.compile(fs.readFileSync(filePath1, 'utf-8'), {client: true}); // Get template as a function templates.template2 = ejs.compile(fs.readFileSync(filePath2, 'utf-8'), {client: true}); ... res.render('app.ejs', {templates: templates}); // Send templates in view 

然而,我不能在他看来:

 <script type="text/javascript"> var templates = <%- JSON.stringify(templates) %>; // Get templates object (object of functions) </script> 

不pipe用。 他们是我发送之前在服务器上的function,但我不知道如何恢复它们。 你有好主意吗 ?

我尝试了一种解决方法,在发送之前将它们更改为string:

 templates.template1 = templates.template1.toString(); 

将它们发送给客户端,然后将其转换回来:

 var template = new Function(templates.template1); $.get('/artists', function(data) { var html = template(data); $('#artists-wrapper').html(html); // Sets HTML }); 

但是这也行不通。

你有什么想法我在这里失踪? 最后,你是否同意在使用函数之前编译服务器端在计算方面比渲染每个模板客户端更好?

感谢您的帮助,并希望能帮助其他人!