У меня какая-то коварная проблема с JavaScript, с которой мне нужна помощь. Я генерирую HTML из структуры JSON. Идея состоит в том, что я должен быть в состоянии передать список как:
['b',{'class':'${class_name}'}, ['i', {}, 'Some text goes here']]
... и получите (если class_name = 'foo'
) ...
<b class='foo'><i>Some text goes here.</i></b>
Я использую следующие функции:
function replaceVariableSequences(str, vars) {
/* @TODO Compiling two regexes is probably suboptimal. */
var patIdent = /(\$\{\w+\})/; // For identification.
var patExtr = /\$\{(\w+)\}/; // For extraction.
var pieces = str.split(patIdent);
for(var i = 0; i < pieces.length; i++) {
if (matches = pieces[i].match(patExtr)) {
pieces[i] = vars[matches[1]];
}
}
return pieces.join('');
}
function renderLogicalElement(vars, doc) {
if (typeof(doc[0]) == 'string') {
/* Arg represents an element. */
/* First, perform variable substitution on the attribute values. */
if (doc[1] != {}) {
for(var i in doc[1]) {
doc[1][i] = replaceVariableSequences(doc[1][i], vars);
}
}
/* Create element and store in a placeholder variable so you can
append text or nodes later. */
var elementToReturn = createDOM(doc[0], doc[1]);
} else if (isArrayLike(doc[0])) {
/* Arg is a list of elements. */
return map(partial(renderLogicalElement, vars), doc);
}
if (typeof(doc[2]) == 'string') {
/* Arg is literal text used as innerHTML. */
elementToReturn.innerHTML = doc[2];
} else if (isArrayLike(doc[2])) {
/* Arg either (a) represents an element
or (b) represents a list of elements. */
appendChildNodes(elementToReturn, renderLogicalElement(vars, doc[2]));
}
return elementToReturn;
}
Иногда это прекрасно работает, но не у других. Пример из телефонного кода:
/* Correct; Works as expected. */
var siblings = findChildElements($('kv_body'), ['tr']);
var new_id = 4;
appendChildNodes($('kv_body'),
renderLogicalElement({'id': new_id},
templates['kveKeyValue']));
/* Incorrect; Substitutes "0" for the expression instead of the value of
`siblings.length` . */
var siblings = findChildElements($('kv_body'), ['tr']);
var new_id = siblings.length; // Notice change here!
appendChildNodes($('kv_body'),
renderLogicalElement({'id': new_id},
templates['kveKeyValue']));
Когда я ловлю первый аргумент renderLogicalElement()
, используя alert()
, я вижу ноль. Почему это?? Я чувствую, что это какая-то вещь типа JavaScript, возможно связанная с литералами объектов, о которой я не знаю.
Редактировать: Я подключил этот код к событию нажатия кнопки на моей странице. Каждый щелчок добавляет новую строку к элементу <tbody>
с идентификатором kv_body
. При первом вызове этой функции siblings
действительно равен нулю. Тем не менее, как только мы добавим <tr>
к миксу, siblings.length
оценивается до нужного значения, увеличиваясь при каждом добавлении <tr>
. Извините, что не яснее! :)
Заранее благодарим за любой совет, который вы можете дать.