Как правильно проверить наличие переменной в шаблоне EJS (с помощью ExpressJS)?


122

На странице Github EJS есть один-единственный простой пример: https://github.com/visionmedia/ejs

пример

<% if (user) { %>
    <h2><%= user.name %></h2>
<% } %>

Кажется, это проверяет наличие переменной с именем user, и если она существует, сделайте что-нибудь. Ага, правда?

У меня вопрос: с какой стати Node выдает ошибку ReferenceError, если пользовательская переменная не существует? Это делает приведенный выше пример бесполезным. Как лучше всего проверить наличие переменной? Ожидается ли, что я буду использовать механизм try / catch и получить эту ошибку ReferenceError?

ReferenceError: user is not defined
    at IncomingMessage.anonymous (eval at <anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:140:12))
    at IncomingMessage.<anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:142:15)
    at Object.render (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:177:13)
    at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.7/package/lib/express/view.js:334:22)
    at Object.<anonymous> (/Users/me/Dropbox/Projects/myproject/server.js:188:9)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)
    at pass (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:162:10)
    at /usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:152:27
    at Object.restrict (/Users/me/Dropbox/Projects/myproject/server.js:94:5)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)

Я понимаю, что могу устранить эту ошибку, просто добавив локальную переменную "user" в код моего сервера, но все дело в том, что я хочу проверять наличие таких переменных во время выполнения, используя ваш каждый день if / else образец типа nullcheck. Мне кажется смешным исключение для несуществующей переменной.

Ответы:


149

Вы можете сделать это так же, как и с чем-либо в js, typeof foo == 'undefined'или, поскольку «locals» - это имя объекта, который их содержит if (locals.foo). Это просто необработанный js: p


3
Я начинаю задумываться, есть ли у меня более серьезная проблема. Это также вызывает эталонную ошибку: <% alert ('test'); %>
— Aashay Desai

1
@Aashay alertявляется частью объекта браузера windowи недоступен в node.js. Альтернативой является console.log, хотя я не знаю, доступна ли она в шаблоне ejs, если вы не передадите ее через locals.
— Zikes

2
@Zikes В данном случае я ищу именно EJS, так что он находится на странице браузера. Но, как сказал TJ, typeof foo == 'undefined' работает. Я узнал, что могу добавить простой !! foo, если foo был определен, но имеет значение null или пусто.
— Aashay Desai

21
Есть ли это сокращение? Почему EJS просто не учитывает случай if (foo)?
— mattdlockyer

5
if (locals.user){ }FTW
— s2t2

26

Попробуйте добавить переменную с помощью locals

Пример: if(locals.user){}



13

Вы можете создать помощник просмотра, который проверяет наличие "obj === void 0", это для express.js:

res.locals.get = function() {
    var args = Array.prototype.slice.call(arguments, 0);
    var path = args[0].split('.');
    var root = this;
    for (var i = 0; i < path.length; i++) {
        if(root[path[i]] === void 0) {
            return args[1]?args[1]:null;
        } else {
            root = root[path[i]];
        }
    };
    return root;
}

Затем используйте его в представлении, например

<%- get('deep.nested.non.existent.value') %>  //returns: null
<%- get('deep.nested.non.existent.value', "default value") %> //returns: default value

3
Не уверен, почему это было отклонено, на мой взгляд, это довольно элегантно.
— joseym

В чем разница между <%=и <%-?
— NobleUplift

2
@NobleUplift Согласно документации , в разделе «Теги»: <%=HTML сначала экранирует значение; <%-выводит неэкранированное значение. Таким образом <b>, при использовании тег будет выделен жирным шрифтом <%-, а при использовании будет просто текст «<b>»<%=
— Матеус

Спасибо! Я понятия не имел, что <% - это даже действительный тег.
— NobleUplift

13

Чтобы проверить, определен ли пользователь, вам нужно сделать это:

<% if (this.user) { %>
   here, user is defined
<% } %>

3
Это не работает в самой последней версии библиотеки EJS (1.0.0). Несмотря на то, что Javascript является действительным, EJS отказывается действовать должным образом.
— Axoren

5
У меня не работает. Несмотря на то, что я определил foo, предложение else все еще оценивается. Протестировано с EJS 2.3.4 EDIT: использование localsвместо thisработ
— X_Trust

8

Я столкнулся с той же проблемой, используя node.js с mongoose / express / ejs при установлении связи между двумя коллекциями вместе с mongoose populate (), в этом случае admins.user_id существовал, но был связан с несуществующим users._id.
Итак, я не мог понять, почему:

if ( typeof users.user_id.name == 'undefined' ) ...

не удалось прочитать свойство 'name', равное нулю. Затем я заметил, что мне нужно выполнить проверку следующим образом:

if ( typeof users.user_id == 'undefined' ) ...

Мне нужно было проверить "контейнер" имени, так что это сработало!
После этого все работало так же:

if ( !users.user_id ) ...  

Надеюсь, поможет.


В любом случае, не могу поверить, что официальной документации по EJS так мало ... они не обновляют свою документацию с 2010 года !!!
— aesede

3

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

 <h2><%= user.name ? property.escrow.emailAddress : '' %></h2>

1
Это опасно использовать, потому что, если объект user не имеет свойства name, рендеринг ejs завершится ошибкой.
— Марко Рочевски


0

Я просто передаю объект по умолчанию, который я называю 'data' = '', и передаю его всем моим шаблонам ejs. Если вам нужно передать реальные данные в шаблон ejs, добавьте их как свойство объекта data.

Таким образом, объект 'data' всегда определяется, и вы никогда не получите неопределенное сообщение об ошибке, даже если свойство 'data' существует в вашем шаблоне ejs, но не в экспресс-маршруте вашего узла.


0

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

На стороне моего сервера / контроллера (это из Node.js / Express):

return res.render('result', {survey_result : req.session.survey_result&&req.session.survey_result.survey }); 

Видишь, что я там делал? Символ &&, который следует после возможно неопределенной переменной (т. Е. request.session.survey_resultОбъекта, который может иметь или не иметь данных формы), является сокращенной нотацией в JS. Он оценивает только ту часть, которая следует за &&, если часть слева от && НЕ определена. Также не выдает ошибку, когда левая часть ЕСТЬ undefined. Он просто игнорирует это.

Теперь в моем шаблоне (помните, что я передал объект req.session.survey_result_surveyобъекта в свое представление как survey_result), а затем визуализировал поля как:

<table>
    <tr>
        <td> Name:</td>
        <td> <%=survey_result&&survey_result.name%></td>
    </tr>
    <tr>
        <td> Dojo Location:</td>
        <td> <%=survey_result&&survey_result.dojo_loc%></td>
    </tr>
    <tr>
        <td> Favourite Language:</td>
        <td> <%=survey_result&&survey_result.fave_lang%></td>
    </tr>

Я также применил там короткое замыкание, на всякий случай.

Когда я попробовал это с помощью предложенных ранее способов, просто:

<% if (typeof survey_result !== undefined) { %>
... <!-- some js and/or html code here -->
<% } %>

Иногда он все равно пытается оценить свойства в операторе IF ... Может быть, кто-то может предложить объяснение, почему?

Кроме того, я хотел исправить это undefinedбез одинарных кавычек, как я видел в предыдущих примерах. Потому что условие никогда не будет оцениваться как значение true, поскольку вы сравниваете значение String 'undefined'с типом данных undefined.


0

Вы можете использовать этот трюк:

user.name // stops code execution,if user is undefined
(scope.user||0).name // === undefined

где область видимости - родительский объект пользователя


0

если вы планируете часто использовать один и тот же объект, вы можете использовать такую ​​функцию:

<% function userObj(obj){
    //replace user with what you name your object
    if(typeof user === 'object'){
        let result = user;
        if(obj){
            obj = obj.split('.');
            for(let i = 0; i < obj.length; i++){
                if(obj[i] && obj[i].trim() !== '' && result[obj[i]]){
                    result = result[obj[i]];
                }else{
                    result = false;
                    break;
                }
            }
        }
        return result;
    }
    return false;
} %>

использование:

<% if(userObj('name')){
    <h2><%= userObj('name') %></h2>
} %>

0

Я придумал другое решение.

<% if(user){ %>
   <% if(user.name){ %>
     <h1><%= user.name %></h1>
<%}}%>

Надеюсь, это поможет.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.