בעיה בהעברת אובייקט שלם מ-Node ל-ejs
-
אני רוצה להריץ סקריפט על לקוח מסויים.
בNode אני מעביר אובייקט של לקוח לרינדור, כך:
res.render('client/details', { client });
ובקובץ HTML אני רוצה לקבל את כל האובייקט client, על ידי ejs, כדי שהסקריפט processClient.js ירוץ עליו, ויעבד כל מיני מאפיינים שלו, באופן הבא:
<script> const myClient = <%-client%>; </script> <script src="/processClient.js"></script>
אבל VSCode מכניס רווח מעצבן בתג של ejs בשורה 2, והופך אותה ל:
const myClient = <% -client %>;
מה שגורם ל-VSCode להציג את השגיאה Expression expected בשורה זו, וכמובן לא לאכלס את האובייקט כראוי. מישהו נתקל בתופעה זו? (יש לי את התוסף EJS Language Support מותקן.)
הערה: אני לא נכנס לשיקולים של אבטחה האם זה כדאי להעביר אובייקט שלם.
-
@odeddvir יש קו אדום מתחת ל<% ?
אם כן כנראה הבעיה היא זאת:
EJS tags within <script> tags in a .ejs file appear as errors.זה בעיה בסיסית מאוד והיא מטילה צל על התוסף + על השפה.
למה בחרת בEJS? ברירת מחדל?עריכה: למרות שהמקרה של השאלה לגיטימי לחלוטין,
משהו בניסוח "להריץ סקריפט על לקוח מסויים" מושך אותי לשאול, מה בעצם אתה מנסה לעשות. -
@dovid אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
יש קו אדום מתחת ל<% ?
כן
למה בחרת בEJS? ברירת מחדל?
משהו כזה. רציתי משהו שיתן לי פונקציונאליות בלי ללמוד תחביר חדש מעבר ל-JS, וזה מה שהכרתי במדריך שממנו למדתי. אני יודע שיש מנועים אחרים, כמו Mustache, אבל לא טרחתי לבדוק האם הם עדיפים.
עריכה: למרות שהמקרה של השאלה לגיטימי לחלוטין,
משהו בניסוח "להריץ סקריפט על לקוח מסויים" מושך אותי לשאול, מה בעצם אתה מנסה לעשות.האמת שזה לא אובייקט של לקוח, הפשטתי את המקרה המדובר.
בפועל אני משתמש בסקריפט החיצוני processClient.js בחלק מהמאפיינים של האובייקט client כדי לאתחל אובייקט אחר, וחשבתי שיהיה יותר קל להעביר את כל האובייקט ולא רק את השדות הרלוונטיים. -
@OdedDvir
א) לא הבנתי מה פה השאלה. השאלה היא איך האדם יכול להשתלט על המכונה ולהכריח את vscode לא להכניס רווח במקום הלא נכון? מאריכות השאלה היה משמע שאתה מבקש משהו מעבר לכך.
ב) לפום ריהטא הקוד שלך בכלל לא אמור לעבוד. אני חשבתי שתגי EJS פולטים מחרוזות. אם אתה מעביר לתג בטוי שמחזיר אובייקט, לכאורה זה יפלוט את התוצאה של המרת האובייקט למחרוזת שבד"כ יהיה[object Object]
או משהו כזה. ואם כן התוצאה של:const myClient = <%-client%>;
אמור להיות:
const myClient = [object Object];
האם אני טועה?
@dovid אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
זה בעיה בסיסית מאוד והיא מטילה צל על התוסף + על השפה.
וואו, אתה הולך רחוק. למה מטיל צל על השפה? אם הבנתי נכון זו רק בעיה קוסמטית בתוסף.
-
@yossiz
א. זו שאלתו להבנתי. באמת שינוי הסיומת מejs לסיומת אחרת פנויה כמו ejshtml תפתור את ה"תמיכה" של VSCODE. אפשר לשים את הסקריפט בקובץ נפרד כדי למזער את הנזק של חוסר התמיכה.ב. גם אם כן, אתה נטפל לבעיה אחרת אותה הוא יפתור בקלות אחרי שהוא יזכה לראות את הפלט.
וואו, אתה הולך רחוק. למה מטיל צל על השפה? אם הבנתי נכון זו רק בעיה קוסמטית בתוסף.
באג בתמיכה של הVSCODE, כ"כ בסיסי מוכיח חוסר פופולריות מדאיגה.
אני באמת חוזר בי מהטלת הצל על EJS, הצל נופל על כל הTemplate Engine של Express.
לפעמים עושר באפשרויות מוכיח שאין אפילו אחת טובה, וזה בדיוק המצב בTemplate engine של Express, אם להשוות את מספר המשתמשים בהם לעומת המקבילים של פלטפורמות אחרות, אז בExpress אין בכלל את המוביל שנחשב סוס מנצח, כל אחד מביא את החסרונות שלו. -
@yossiz אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
לפום ריהטא הקוד שלך בכלל לא אמור לעבוד.... ...האם אני טועה?
צודק. בינתיים, הואיל ו-ejs לא מתערב לי בתוך מחרוזות שמוגדרות בסקריפט, עקפתי את הבעיה בצורה הלא אלגנטית:
const myClient = JSON.parse('<%-JSON.stringify(client)%>');
איכס...
@dovid אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
לפעמים עושר באפשרויות מוכיח שאין אפילו אחת טובה, וזה בדיוק המצב בTemplate engine של Express
אז מה עושים? ממשיכים להשתמש ומצפים לישועה? לא אכפת לי להחליף engine כיון שאני מתחיל ואני מחפש את דרך המלך.
-
@dovid אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
לפעמים עושר באפשרויות מוכיח שאין אפילו אחת טובה, וזה בדיוק המצב בTemplate engine של Express
למה להאשים את Express? המצב לא קשור אליהם. הם תומכים במה שקיים. Express לא אמור להיות פריימוורק שלם. זה יותר בכיוון של ספרייה או micro framework.
נראה לי שאפשר להניח שרוב אפליקצייות נוד לא משתמשות ברינדור צד שרת אז מובן שאין המון משתמשים.
אולי אפשר לומר שהבעיה בנוד הוא זה שאין פריימוורק ראוי לשמו. זו גם בעיה וגם יתרון. תבחר לעצמך איך אתה רוצה להשתמש בעובדה זו.@odeddvir אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
אז מה עושים? ממשיכים להשתמש ומצפים לישועה?
איזה ישועה? תיקון לבעיה קוסמטית בתוסף של עורך אחד? האם אתם לא מגזימים קצת את גודל הבעיה?
-
@yossiz אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
אתה מנסה לעשות משהו ש-EJS לא נועד לו
באמת יש לי הרגשה כזו מההתחלה.
אז איך באמת אני אמור להעביר אובייקט שלם לסקריפט? אולי בכלל זו לא גישה נכונה...@yossiz אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
האם אתם לא מגזימים קצת את גודל הבעיה?
היה משתמע מדברי @dovid שאין שום תוסף ראוי לרינדור באקספרס...
-
@odeddvir אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
אז איך באמת אני אמור להעביר אובייקט שלם לסקריפט?
לא התחברתי לניסוח של "להעביר אובייקט לסקריפט". אתה מנסה לכתוב סקריפט בצורה דינאמית. אין פה באמת "העברה" של האובייקט כמו העברה של פרמטר לפונקציה. אם היה לי צורך כזה באמת הייתי עושה מה שעשית --
JSON.parse(JSON.stringify)
-- אולי הייתי גם מגיב באימוג'י שמבטא שאט נפש. ואז הייתי ממשיך בחיים.אני לא חושב שהמצב יותר טוב בשפות אחרות.
אם אני מבין נכון, אתה מנסה לעשות משהו ממוצע בין רינדור צד שרת לרינדור צד לקוח.
כלומר, ברינדור צד לקוח טהור, הדפדפן מקבל דף סטטי שלא משתנה כלל. וכל המידע הדינאמי מתקבלת בקריאות AJAX. ברינדור צד שרת טהור גם אין את הצורך שלך, כי כל התנהגות שתלוי במידע דינאמי מורנדר בצד שרת.
ממילא מובן שזה לא הסיטואציה הכי נתמכת.@odeddvir אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
היה משתמע מדברי @dovid שאין שום תוסף ראוי לרינדור באקספרס...
אני לא יכול להגיב על זה כי אין לי נסיון ברינדור צד שרת. באיזה שפה יש מנוע טמפלייטים יותר טוב שאין לו מקביל בנוד? לא חשבתי שהמצב בנוד כל כך גרוע, אבל ייתכן שאני טועה.
-
@odeddvir אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
const myClient = JSON.parse('<%-JSON.stringify(client)%>');
האם אפשר להשמיט את הגרשים ואת הקריאה ל-JSON.parse, ולנצל את העובדה שאובייקט בתחביר JSON הוא גם אובייקט JS חוקי?
אגב, גיגול זה: ejs pass object to client side script מביא פתרונות דומים לשלך.
-
@yossiz אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
האם אפשר להשמיט את הגרשים ואת הקריאה ל-JSON.parse, ולנצל את העובדה שאובייקט בתחביר JSON הוא גם אובייקט JS חוקי?
זה לא עובד, יש לי באובייקט שדה
_id
שמכיל Guid שמתחיל בספרה, והוא לא מוקף גרשים, ואני מקבל SyntaxError בדפדפן כי זה לא JSON תקני. -
@odeddvir אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
זה לא עובד, יש לי באובייקט שדה
_id
שמכיל Guid שמתחיל בספרה, והוא לא מוקף גרשים, ואני מקבל SyntaxError בדפדפן כי זה לא JSON תקני.נסה לעשות את הstringify בצד השרת:
res.render('client/details', { client: JSON.stringify(client) });
-
@yossiz זה בדיוק מה שאמרתי, שבגלל שרוב משתמשי אקספרס לרוב לא משתמשים ברנדור צד שרת ממילא כשצריך אותו (וכשצריך אז צריך) המצב קשה. אני לא יודע איפה ראית שהאשמתי את אקספרס אבל אני אכן מאשים אותם. למה שהם יעשו? למה לא כל מפתח בעולם אחר? זה בדיוק הבעיה שיש יותר מידי אחרים, וזו בעיה שהם יצרו. אני הייתי מצפה מהמקרו פרימוורק הזה לתת מנוע תצוגה אחד שעובד מעולה, במקום דמוקרטיזציה מעצבנת בה הם זונחים לגמרי את התחום לחסדי ספריות לא יציבות שהתחרות ביניהם רק פוגעת מאשר עוזרת. תחרות זה גורם חיובי רק בתחום פופולרי מספיק לקנאת סופרים.
@OdedDvir זה בהחלט לגיטימי לרנדר אובייקט ישירות לסקריפט, וזה לדעתי בהחלט חלק מהייעוד של EJS לתת את היכולת הזו.
-
@zvizvi אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
@odeddvir אמר בבעיה בהעברת אובייקט שלם מ-Node ל-ejs:
זה לא עובד, יש לי באובייקט שדה
_id
שמכיל Guid שמתחיל בספרה, והוא לא מוקף גרשים, ואני מקבל SyntaxError בדפדפן כי זה לא JSON תקני.נסה לעשות את הstringify בצד השרת:
res.render('client/details', { client: JSON.stringify(client) });
לצערי לא הבנתי לא את הבעיה ולא את הפתרון. אבל זה לא קשור ישירות לנושא.
-
למרות שזה לא הנושא הישיר אתן סקירה קטנה מנסיוני.
מנועי התצוגה (Template engine) בNode מתחלקים לשניים:-
אלה שמשתמשים במילים ופקודות שמורות משלהן עבור כל פקודה, והן שואבות השראה ממנועים אחרים בשפות אחרות (שם הדבר מפותח מאוד ובשימוש רב).
במנועים אלה האפשרויות מצומצמות למספר מילים שמורות בלבד(if, else, switch)
וכד'. יש גם "פילטרים" שמאפשרים לשנות את הערך של משתנה המודפס לדוגמה:{{ count | add: 1}}
כאשר רוצים להציב תנאי מורכב או להציג ערך קומבינציה שמורכב מכמה פרמטרים יש צורך לבנות רכיב תצוגה מיוחד ולהעביר אותו לפקודת הRender בדומה להעברת שאר הData מצד השרת לטמפלט.
שיטה זו דומה למנועים אחרים רבים הקיימים בשפות אחרות, דוגמת Django של פייתון או Laravel של PHP, ERB ברובי וכן הלאה. -
אלה שמאפשרים לשים פקודות Javascript מלאות בין חלקי הhtml בקובץ, כמו כן ניתן לשים תנאים מורכבים שתלויים בהרבה משתנים, ולא צריך לבנות לזה רכיב תצוגה במיוחד.
שיטה זו דומה לכתיב של php טהור בקבצי html.
בקבוצת המנועים הראשונה ניתן למנות את Pug (Jade לשעבר), Handlebars, mustache.js, ועוד,
בקבוצה השניה יש את Ejs (לדעתי זהו היחיד שקיים).סגנון התחביר להכנסת פקודות בין חלקי הhtml משתנה בין הספריות השונות, יש כמה סגנונות מקובלים (ובכל שפת תכנות יש כמה שלקחו השראה מכל סגנון כזה)
באיזה מנוע כדאי להשתמש?
מנסיוני, כאשר מדובר בפרויקט קטן ושהטפמלט אינו דורש מניפולציות מורכבות, יש עדיפות גדולה לקבוצה הראשונה, השימוש בה נותן פחות אפשרויות, הכתיב מוגדר יותר ולכן הוא פחות מאפשר לבלגן את הקוד.
אבל כשצריך מניפלציות מורכבות יש יתרון מסוים להשתמש בEjs ולהציב את כל תוכן קוד הבנייה של הערך בבלוק עצמו. כדי לחסוך בנייה של פונקציות רבות שעושות את ההרכבה ולהעביר כל אחת לתוך הטמפלט בנפרד. -
-
בלי להעיב על הפירוט המעולה של @zvizvi שמעליי, ועם דעתי ההדיוטית:
@OdedDvir התנסתי הרבה עם HBS (handlebars) - כן זה עם השפם (אם אני משער נכון זה על המשקל של mustache שהיא באה להחליף?)
הוא מעולה.
ועד כמה שאני זוכר נכון (ומסתכל בקוד שקיים אצלי במחשב וזה נראה ש=) הוא נותן בקלות להעביר אובייקטים לתוך משתנים בפרונט-אנדJS. ממה שאני רואה אצלי בקוד (שוב: רק ממבט מלמעלה) זה פשוט להעביר את זה ממש בצורה הרגילה - להכניס את זה בשלב הרינדור לפקודה כקונטקסט, ובתוך הטמפלייט להכניס את זה ב {{ }}
עריכה טעות שלי (אולי זה אפשרי, בכל אופן אני לא מכיר) עי' יוסי להלןאגב @yossiz שאלת או אמרת באיזה עוד פלטפורמות יש מנועים כאלה (לפחות הידועים שבהם) אז כמובן מדובר על דג'אנגו, שזה מובנה בו וזה צורת העבודה איתו מלכתחילה
סורי שהפרעתי ותודה ל @zvizvi על הפוסט הבהיר