2016-10-13 3 views
2

Я кодирую приложение на экспресс, и я использую ejs в качестве механизма просмотра/шаблона.Не удается отобразить шаблон EJS на клиенте

На пути /artists, я представляю вид artists.ejs, который имеет обложки для художников. При нажатии на обложку мне нужен вызов AJAX для получения соответствующих данных, поместите его в мой шаблон/представление для исполнителя artist.ejs и покажите этот шаблон в своем HTML под обложкой.

Я видел this Связанный вопрос, но он не решил мой прецедент.

Все кажется ясным, но я не могу отобразить данные с помощью шаблона. Я хотел бы скомпилировать серверную часть шаблона, отправить его клиенту, готовому к использованию, а затем заполнить его, когда это необходимо, с данными, полученными от вызова 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 
}); 

Я заботилась о преобразовании файла в строку, так как EJS компилятор работает только с Последовательностью (по сравнению с Джейд .compileFile)

Тогда на стороне клиента, я захватить функцию:

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

Тогда на другой сценарий, я извлечь данные с вызова AJAX:

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

Но когда я делаю вызов, я получаю:

Uncaught ReferenceError: fn is not defined

Когда я называю шаблон, fn, я получить:

Uncaught ReferenceError: opts is not defined.

ли функция fn жестко? Я прочитал документацию EJS и Jade, но в отношении моей проблемы мало информации.

Возможно, мне нужен шаблон на стороне клиента?

ответ

0

При компиляции для клиента вам необходимо использовать опцию client на стороне сервера. Из документов:

  • client When true , compiles a function that can be rendered in the browser without needing to load the EJS Runtime

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}); 
}); 
+0

Привет, Райан, спасибо за ваш ответ. В приведенном ниже ответе обходной путь я объяснил, и он работает хорошо, но я также хотел попробовать эту технику, скомпилировать серверную часть шаблона и запустить ее на стороне клиента, но невозможно заставить его работать! Не могли бы вы немного помочь мне в этом вопросе? Благодаря! –

0

в конце концов я нашел обходной путь, на мой вопрос, и я понял, с ответом, который вы могли бы действуйте двумя разными способами:

1) Что я сделал: прочитайте и сохраните шаблон в виде строки, а затем визуализируйте его на стороне клиента с помощью сценария Runtime 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 
}); 

Таким образом, я посылаю все мои шаблоны на первой загрузке страницы, а затем я сделать запрошенную страницу на стороне клиента.Интерес к тому, что я читал, заключается в том, что вы отправляете только объект JSON (ваши данные) через вызовы AJAX, а не всю страницу, что упрощает запрос. Только первый груз тяжелый со всеми вашими шаблонами.

2) Что я хотел бы сделать в соответствии с ответом @RyanZim: компилируя серверные части шаблонов в функции, отправляя их, а затем вызывайте их на стороне клиента: шаблон (данные). Если я хорошо понимал, что нет необходимости в клиентской библиотеки EJS в этом случае, и мои шаблоны больше не являются строками, а функции:

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

не работает. они являются функциями на сервере, прежде чем отправлять их, но я не знаю, как их восстановить. У вас есть идея?

Я попробовал обходной путь, изменяя их в строки перед отправкой их:

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

Но это не будет работайте.

У вас есть идея, что мне здесь не хватает? И, наконец, согласны ли вы с тем, что компиляция их на стороне сервера перед использованием функций лучше с точки зрения вычисления, чем рендеринга каждого клиентского клиента?

Спасибо за помощь и надеюсь, что это поможет кому-нибудь еще!

Смежные вопросы