ΠΡΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠΈ Handlebars Π² ΡΡΠ΅Π΄Π΅ ES6 ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΠ΅ Π²ΡΡΡΠΎΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠ° each
Π½Π° ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΌΠ°ΡΡΠΈΠ²ΠΎΠ² ΠΈ ΡΠ½ΠΈΠ²Π΅ΡΡΠ°Π»ΡΠ½ΡΡ
ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡΡ Π½Π΅ΡΠ΄ΠΎΠ±Π½ΡΠΌ. Π§ΡΠΎΠ±Ρ ΠΎΠ±ΠΎΠΉΡΠΈ ΡΡΠΎ, Ρ Π½Π°ΡΠ°Π» ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°ΡΡ ΡΠ²ΠΎΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΡ Π²Π΅ΡΡΠΈΡ ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊΠ° each
, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ ΠΌΠ°ΡΡΠΈΠ²Ρ, ΠΊΠ°ΡΡΡ, Π½Π°Π±ΠΎΡΡ, ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΠ΅ ΠΈΡΠ΅ΡΠ°ΡΠΈΠΈ ΠΈ ΡΠ½ΠΈΠ²Π΅ΡΡΠ°Π»ΡΠ½ΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ. ΠΡΠΎΡ ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊ Π½ΠΈΠΆΠ΅.
ΠΡΡΡ Π»ΠΈ ΠΏΠ»Π°Π½ ΠΈΠ»ΠΈ ΠΆΠ΅Π»Π°Π½ΠΈΠ΅ Π²Π½Π΅Π΄ΡΠΈΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ ΡΡΠΈΡ
ΡΠΈΠΏΠΎΠ² ΡΠΏΠΈΡΠΊΠΎΠ² Π²ΠΎ Π²ΡΡΡΠΎΠ΅Π½Π½ΡΠΉ ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊ each
? Π― ΡΠΏΡΠ°ΡΠΈΠ²Π°Ρ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ, ΡΡΠΎ Handlebars ΡΡΡΠ΅ΠΌΠΈΡΡΡ ΠΈΠ·Π±Π΅ΠΆΠ°ΡΡ ΠΏΠΎΠ»ΠΈΡΠΈΠ»Π»ΠΎΠ², ΠΈ Ρ ΠΏΠΎΠ»Π°Π³Π°Ρ, ΡΡΠΎ Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΡΠΉ ΡΠΏΠΎΡΠΎΠ± Π·Π°ΡΡΠ°Π²ΠΈΡΡ Π½ΠΎΠ²ΡΠΉ ΠΏΠΎΠΌΠΎΡΠ½ΠΈΠΊ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π±Π΅Π· ΡΡΠ΅ΡΠ±Π° Π΄Π»Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΈ Π±ΡΠ°ΡΠ·Π΅ΡΠ° β ΠΏΠΎΡΡΠ΅ΠΏΠ΅Π½Π½ΠΎ Π²ΠΊΠ»ΡΡΠ°ΡΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ
ΡΠΈΠΏΠΎΠ² ΡΠΏΠΈΡΠΊΠΎΠ² Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΎΠ΄Π½ΠΎΠΉ ΠΈΠ»ΠΈ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΠΎΠ»ΠΈΡΠΈΠ»Π»ΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΉ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΈ ΡΡΠ΅Π΄Ρ. Π΄Π»Ρ Set
, Map
ΠΈ Symbol
.
Handlebars.registerHelper("each", function (contexts, options) {
// Throw a runtime exception if options were not supplied.
if (!options) {
throw new Handlebars.Exception("Must pass iterator to #each");
}
// If the "list of contexts" is a function, execute it to get the actual list of contexts.
if (typeof contexts === "function") {
contexts = contexts.call(this);
}
// If data was supplied, frame it.
const data = options.data ? Object.assign({}, options.data, { _parent: options.data }) : undefined;
// Create the string into which the contexts will be handled and returned.
let string = "";
// Create a flag indicating whether or not string building has begun.
let stringExtensionStarted = false;
// Create a variable to hold the context to use during the next string extension. This is done to
// allow iteration through the supplied list of contexts one step out of sync as they are looped
// through later in this helper, ensuring a predictable sequence of value retrieval, string
// extension, value retrieval, string extension...
let nextContext;
// Create a function responsible for expanding the string.
const extendString = (final = false) => {
// If other contexts have been encountered...
if (nextContext) {
// Expand the string using the block function.
string += options.fn(nextContext.value, {
data: data ? Object.assign(data, {
index: nextContext.index,
key: nextContext.key,
first: !stringExtensionStarted,
last: final
}) : undefined,
blockParams: [nextContext.key, nextContext.value]
});
// Note that string extension has begun.
stringExtensionStarted = true;
// If no contexts have been encountered and this is the final extension...
} else if (final) {
// Expand the string using the "else" block function.
string += options.inverse(this);
}
};
// If a list of contexts was supplied...
if (contexts !== null && typeof contexts !== "undefined") {
// Start a counter.
let index = 0;
// If an array list was supplied...
if (Array.isArray(contexts)) {
// For each of the possible indexes in the supplied array...
for (const len = contexts.length; index < len; index++) {
// If the index is in the supplied array...
if (index in contexts) {
// Call the string extension function.
extendString();
// Define the context to use during the next string extension.
nextContext = {
index: index,
key: index,
value: contexts[index]
};
}
}
// If a map list was supplied...
} else if (contexts instanceof Map) {
// For each entry in the supplied map...
for (const [key, value] of contexts) {
// Call the string extension function.
extendString();
// Define the context to use during the next string extension.
nextContext = {
index: index,
key: key,
value: value
};
// Increment the counter.
index++;
}
// If an iterable list was supplied (including set lists)...
} else if (typeof contexts[Symbol.iterator] === "function") {
// Get an iterator from the iterable.
const iterator = contexts[Symbol.iterator]();
// Create a variable to hold the iterator's next return.
let next;
// Do the following...
do {
// Iterate and update the variable.
next = iterator.next();
// If there is anything left to iterate...
if (!next.done) {
// Call the string extension function.
extendString();
// Define the context to use during the next string extension.
nextContext = {
index: index,
key: index,
value: next.value
};
// Increment the counter.
index++;
}
// ... until there is nothing left to iterate.
} while (!next.done);
// If a list other than an array, map, or iterable was supplied...
} else {
// For each key in the supplied object...
for (const key of Object.keys(contexts)) {
// Call the string extension function.
extendString();
// Define the context to use during the next string extension.
nextContext = {
index: index,
key: key,
value: contexts[key]
};
// Increment the counter.
index++;
}
}
}
// Call the string extension a final time now that the last supplied context has been encountered.
extendString(true);
// Return the fully-extended string.
return string;
});
ΠΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΅ΠΉΡΠ°Ρ, Ρ # 1557
@nknapp ΠΏΠΎΡ
ΠΎΠΆΠ΅, ΡΡΠΎ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π² # 1557 Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π΄ΠΎΠ»ΠΆΠ½ΡΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ Map
. Π Π½Π°ΡΡΠΎΡΡΠ΅Π΅ Π²ΡΠ΅ΠΌΡ ΠΎΠ½ ΡΠΎΠ·Π΄Π°Π΅Ρ ΠΏΠΎΠ²ΡΠΎΡΡΡΡΠΈΠΉΡΡ ΡΠ»Π΅ΠΌΠ΅Π½Ρ, ΡΠ²Π»ΡΡΡΠΈΠΉΡΡ _entry_ Π² Map
, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΊΠΎΡΡΠ΅ΠΆΠ΅ΠΌ [key, value]
, ΡΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΡΠΉ Π²ΡΡΠ΅ ΠΏΡΠΈΠΌΠ΅Ρ ΠΊΠΎΠ΄Π° Π΄Π΅Π»Π°Π΅Ρ ΠΏΠΎΠ²ΡΠΎΡΡΠ΅ΠΌΡΠΉ ΡΠ»Π΅ΠΌΠ΅Π½Ρ value
ΠΈ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ @key
, ΡΡΠΎ Ρ _Π΄ΡΠΌΠ°Ρ_ ΠΏΡΠ΅Π΄ΠΏΠΎΡΡΠΈΡΠ΅Π»ΡΠ½Π΅Π΅. ΠΠ»Ρ ΠΌΠ΅Π½Ρ ΡΡΠΎ ΠΏΡΠ΅Π΄ΠΏΠΎΡΡΠΈΡΠ΅Π»ΡΠ½Π΅Π΅!
ΠΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΆΠ΅ΡΡΡ, ΡΡΠΎ Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΡ Π² Π½Π°ΡΡΠΎΡΡΠ΅Π΅ Π²ΡΠ΅ΠΌΡ Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ Map
, ΠΏΠΎΡΡΠΎΠΌΡ Π²Ρ Π½Π΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΡΠΊΠ°Π·Π°ΡΡ {{person.myMap.myMapKey}}
. Π― ΡΠ΅ΠΉΡΠ°Ρ Π±ΠΎΠ»ΡΡΠ΅ Π²Π½ΠΈΠΊΠ°Ρ Π² ΡΡΠΎΡ Π²ΠΎΠΏΡΠΎΡ.
Π‘ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ΠΌ lookupProperty
Π² runtime.js
ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΠΊΠ°ΡΡ ΡΠ²ΠΎΠΉΡΡΠ²Π° Π² Map
s:
lookupProperty: function(parent, propertyName) {
if (parent instanceof Map) {
return parent.get(propertyName)
}
ΠΡΡΡ Π»ΠΈ ΠΆΠ΅Π»Π°Π½ΠΈΠ΅ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΡΠ°ΠΊΡΡ ββΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΡ?
@karlvr Π― Π΄ΡΠΌΠ°Ρ, Π²Π°ΡΠ΅ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π·Π°ΡΠ»ΡΠΆΠΈΠ²Π°Π΅Ρ Π²Π½ΠΈΠΌΠ°Π½ΠΈΡ. ΠΠΎ Ρ Ρ ΠΎΡΠ΅Π» Π±Ρ ΡΡΠΎ ΠΎΠ±ΡΡΠ΄ΠΈΡΡ.
@karlvr , Π½Π΅ ΠΌΠΎΠ³Π»ΠΈ Π±Ρ Π²Ρ ΡΠΎΠ·Π΄Π°ΡΡ Π½ΠΎΠ²ΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Π΄Π»Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΈ ΠΊΠ°ΡΡ. Π§Π°ΡΡΡ ΡΡΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ ΡΠΆΠ΅ ΡΠ΅ΡΠ΅Π½Π°, ΠΈ Ρ Ρ ΠΎΡΠ΅Π» Π±Ρ Π½Π°ΡΠ°ΡΡ Ρ ΡΠΈΡΡΠΎΠ³ΠΎ Π»ΠΈΡΡΠ°.
@nknapp Π±ΠΎΠ»ΡΡΠΎΠ΅ ΡΠΏΠ°ΡΠΈΠ±ΠΎ Π·Π° Π±ΡΡΡΡΡΠΉ ΠΎΡΠ²Π΅Ρ; Π― ΡΠΎΠ»ΡΠΊΠΎ ΡΡΠΎ ΡΠ΄Π΅Π»Π°Π» PR Ρ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½Π½ΡΠΌΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡΠΌΠΈ. ΠΠΎΠΆΠ΅ΠΌ Π»ΠΈ ΠΌΡ ΠΎΠ±ΡΡΠ΄ΠΈΡΡ ΡΠ°ΠΌ? β1679
Π‘Π°ΠΌΡΠΉ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ
@karlvr , Π½Π΅ ΠΌΠΎΠ³Π»ΠΈ Π±Ρ Π²Ρ ΡΠΎΠ·Π΄Π°ΡΡ Π½ΠΎΠ²ΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Π΄Π»Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΈ ΠΊΠ°ΡΡ. Π§Π°ΡΡΡ ΡΡΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ ΡΠΆΠ΅ ΡΠ΅ΡΠ΅Π½Π°, ΠΈ Ρ Ρ ΠΎΡΠ΅Π» Π±Ρ Π½Π°ΡΠ°ΡΡ Ρ ΡΠΈΡΡΠΎΠ³ΠΎ Π»ΠΈΡΡΠ°.