Який правильний спосіб перевірити наявність змінної в шаблоні EJS (за допомогою ExpressJS)?


121

На сторінці github EJS є один і лише один простий приклад: https://github.com/visionmedia/ejs

Приклад

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

Це, здається, перевіряє наявність змінної з іменем користувача, і якщо вона існує, зробіть деякі речі. Ду, так?

Моє запитання: чому в світі 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" у свій код сервера, але вся справа в тому, що я хочу перевірити наявність таких змінних під час виконання, використовуючи щодня, якщо / ще nullcheck типу візерунка. Виняток для змінної, яка не існує, мені здається смішною.

Відповіді:


149

Так само, як ви зробили це з чим-небудь у js, typeof foo == 'undefined'або оскільки "localals" - це ім'я об'єкта, який їх містить, ви можете зробити 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 було визначено, але воно є нульовим або порожнім.
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 відмовиться діяти так, як очікувалося.
Аксорен

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

8

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

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

не вдалося виконати "Неможливо прочитати властивість" ім'я "з нуля". Тоді я помітив, що мені потрібно зробити перевірку так:

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. Це робиться лише оцінити частину, яка слідує &&, якщо частина зліва від && НЕ визначена. Він також не видає помилку, коли ліва частина IS є 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.