无法在客户端上呈现EJS模板 [英] Can't Render EJS Template on Client

查看:108
本文介绍了无法在客户端上呈现EJS模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在路径 / artists ,我正在渲染视图 artists.ejs 有艺术家封面。当点击封面时,我想要一个AJAX调用来检索相应的数据,将它放在我的模板/视图中,用于艺术家 artist.ejs 并在我的HTML下显示该模板封面。



我见过这个相关的问题,但它还没有解决我的用例。



一切似乎都很清楚,但我无法使用模板渲染数据。我想编译模板服务器端,将其发送到准备使用的客户端,然后在需要时使用从AJAX调用接收的数据填写它。



我做了什么:



当调用 / artists 时,使用<$ c $在服务器端编译c> ejs.compile(str,opt):

  router.get('/ artists' ,function(req,res){

//编译艺术家模板
fs.readFile('views / artist.ejs',utf-8,function(err,template){ //将模板文件转换为字符串
artist_template = ejs.compile(template); //编译模板

res.render('artists.ejs',{template:artist_template}); / / render page with compiled template
});

我负责将文件转换为字符串,因为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未定义


当我调用模板 fn 时,我会收到:


未捕获的ReferenceError:未定义opts。


函数是否为 fn 硬编码?我读过EJS和Jade文档,但关于我的问题几乎没有相关信息。



我也许还需要客户端的模板?

解决方案

我最终找到了一个解决方法来解决我的问题,我理解你的问题回答那个哟你可以用两种不同的方式进行:



1)我做了什么:读取并将模板保存为字符串,然后使用ejs Runtime脚本将其呈现在客户端。

  //在controller.js 
var templates = {};
templates.template1 = fs.readFileSync(filePath1,'utf-8'); //将模板作为字符串读取
templates.template2 = fs.readFileSync(filePath2,'utf-8');
...
res.render('app.ejs',{templates:templates}); //在视图中发送模板

//在视图app.ejs
< script type =text / javascript>
var templates =<% - JSON.stringify(templates)%> ;; //获取模板对象(字符串对象)
< / script>
< script type =text / javascriptsrc =/ JS / ejs.min.js>< / script> <! - 加载ejs RunTime - >

//在site.js中 - javascript客户端/公共文件
$ .get('/ artists',function(data){
var html = ejs.render(templates) .template1,data); //使用EJS脚本渲染ejs客户端(template1对应于艺术家模板)
$('#artists-wrapper')。html(html); //设置HTML
});

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



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

  //在controller.js 
var templates = {};
templates.template1 = ejs.compile(fs.readFileSync(filePath1,'utf-8'),{client:true}); //获取模板作为函数
templates.template2 = ejs.compile(fs.readFileSync(filePath2,'utf-8'),{client:true});
...
res.render('app.ejs',{templates:templates}); //在视图中发送模板

但是,我无法在我的视图中获取它们:

 < script type =text / javascript> 
var templates =<% - JSON.stringify(templates)%> ;; //获取模板对象(函数对象)
< / script>

不起作用。它们是我发送之前在服务器上的功能,但我不知道如何恢复它们。你有什么想法吗?



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

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

发送它们然后发送客户端,将它们转换回函数:

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

但这也无效。



<你知道我在这里缺少什么吗?
最后,你是否同意在使用函数之前编译服务器端在计算方面比渲染每个模板客户端更好?



谢谢你帮助,希望能帮助其他人!


I'm coding an application on express, and I'm using ejs as a view/template engine.

At path /artists, I'm rendering the view artists.ejs which has artists covers. When clicking on a cover, I want an AJAX call to retrieve the corresponding data, place it in my template/view for artist artist.ejs and display this template in my HTML under the cover.

I've seen this related question but it has not solved my use case.

Everything seems clear, but I can't render the data with the template. I would like to compile the template server-side, send it to the client ready to use, and then fill it in when needed with the data received from the AJAX call.

What I've done:

When calling /artists, compile on server-side using 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
});

I took care of converting the file into String, as ejs compiler only works with String (compared to Jade .compileFile)

Then on client-side, I grab the function:

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

Then on another script, I retrieve the data with an AJAX call:

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

But when I make the call, I receive:

Uncaught ReferenceError: fn is not defined

When I call the template, fn, I receive:

Uncaught ReferenceError: opts is not defined.

Is the function fn hard-coded? I've read the EJS and Jade documentation but there was little relevant information in regards to my issue.

Do I perhaps need the template on client-side also?

解决方案

I eventually found a workaround to my question, and I understood with your answer that you could proceed in 2 different ways:

1) What I did: read and save template as a string, then render it client-side with ejs Runtime script.

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

Thus, I send all my templates on first page load, and then I render the requested page on the client side. The interest, according to what I've read, is that you only send JSON object (your data) through AJAX calls, and not the entire page, making your request light. Only the first load is heavy with all your templates.

2) What I would like to do according to @RyanZim answer: compiling templates server side into functions, send them, and then call them on the client side : template(data). If I understood well, there is no need of EJS client library in this case, and my templates are no longer strings but functions:

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

However, I can't get them in my view:

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

is not working. they are functions on the server before I send them, but I don't know how to recover them. Do you have an idea ?

I tried a workaround, by changing them into String before sending them:

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

Send them and then client side, transform them back in functions:

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

But that won't work either.

Do you have an idea what I'm missing here? And last, do you agree that compiling them server side before using the functions is better in terms of computation than rendering each template client-side?

Thanks for the help, and hope that will help anybody else!

这篇关于无法在客户端上呈现EJS模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆