2008-12-18 12 views
29

Hola, tengo un bloque de HTML que voy a usar repetidamente (en varias ocasiones durante una visita de un usuario, no de una vez). Creo que la mejor manera de lograr esto es crear un div HTML, ocultarlo, y cuando sea necesario tomar su innerHTML y hacer un replace() en varias palabras clave. Como ejemplo, un bloque de HTML ...Reemplazo eficiente de cadenas de Javascript

<div id='sample'> 
    <h4>%TITLE%</h4> 
    <p>Text text %KEYWORD% text</p> 
    <p>%CONTENT%</p> 
    <img src="images/%ID%/1.jpg" /> 
</div> 

¿Sería la mejor manera de reemplazar las palabras clave con datos dinámicos ser ir ...

template = document.getElementById('sample'); 
template = template.replace(/%TITLE%/, some_var_with_title); 
template = template.replace(/%KEYWORD%/, some_var_with_keyword); 
template = template.replace(/%CONTENT%/, some_var_with_content); 
template = template.replace(/%ID%/, some_var_with_id); 

Se siente como que he elegido una manera estúpida para hacer esto. ¿Alguien tiene alguna sugerencia sobre cómo hacer esto de una manera más rápida, más inteligente o mejor? Este código se ejecutará con bastante frecuencia durante la visita de un usuario, algunas veces una vez cada 3-4 segundos.

Gracias de antemano.

Respuesta

11

Dudo que haya algo más eficiente. La alternativa sería dividirla en partes y luego concatenar, pero no creo que sea mucho más eficiente. Quizás incluso menos, teniendo en cuenta que cada concatenación da como resultado una nueva cadena que tiene el mismo tamaño que sus operandos.

Agregado: Esta es probablemente la forma más elegante de escribir esto. Además, ¿qué te preocupa? ¿Uso de memoria? Es abundante y Javascript tiene un administrador de memoria decente. Velocidad de ejecución? Entonces debes tener una cuerda gigante. En mi humilde opinión esto es bueno.

+0

gracias por la respuesta. En realidad, este es un bloque mucho más grande con muchas más sustituciones, así que antes de comenzar quería asegurarme de que no me faltara algo. Gracias de nuevo. –

+4

um ... there is: encadenando – annakata

+1

Y hay mejores formas de implementarlo. – some

1

Puede hacerlo más eficiente encadenando las sustituciones en lugar de realizar todas estas asignaciones intermedias.

es decir

with(document.getElementById('sample')) 
{ 
    innerHTML = innerHTML.replace(a, A).replace(b, B).replace(c, C); //etc 
} 
+0

Quizás, pero ¿esto no empeora la legibilidad? Aunque podría apilar estas llamadas verticalmente ... –

+0

Te creo, pero ¿cómo cambia el rendimiento? – chills42

+1

-1, el rendimiento es el mismo – orip

17

Probablemente se podría adaptar este código para hacer lo que quiere:

var user = { 
    "firstName": "John", 
    "login": "john_doe", 
    "password": "test", 
}; 

var textbody = "" 
+"Hey {firstName},\n" 
+"\n" 
+"You recently requested your password.\n" 
+"login: {login}\n" 
+"password: {password}\n" 
+"\n" 
+"If you did not request your password, please disregard this message.\n" 
+""; 

textbody = textbody.replace(/{[^{}]+}/g, function(key){ 
    return user[key.replace(/[{}]+/g, "")] || ""; 
}); 

También puede ser que desee ver en JavaScriptTemplates

+1

Perfecto para lo que necesito - Gracias por compartir. – andyengle

+5

Para evitar la llamada de reemplazo adicional dentro de la función del controlador, simplemente agrupe la coincidencia de expresiones regulares: textbody.replace (/ {([^ {}] +)}/g, function (textMatched, key) {.... – Diego

75

Parece que desea utilizar una plantilla.

//Updated 28 October 2011: Now allows 0, NaN, false, null and undefined in output. 
function template(templateid, data){ 
    return document.getElementById(templateid).innerHTML 
     .replace(
     /%(\w*)%/g, // or /{(\w*)}/g for "{this} instead of %this%" 
     function(m, key){ 
      return data.hasOwnProperty(key) ? data[ key ] : ""; 
     } 
    ); 
} 

Explicación del código:

  • Espera templateid a ser el ID de un elemento existente.
  • Espera que data sea un objeto con los datos.
  • utiliza dos parámetros para reemplazar a hacer la sustitución:
  • La primera es una expresión regular que busca para todos %keys% (o {keys} si utiliza la versión alterna). La clave puede ser una combinación de A-Z, a-z, 0-9 y guion bajo _.
  • La segunda es una función anónima que recibe llamadas para cada coincidencia.
  • La función anónima busca en el objeto de datos la clave que encontró la expresión regular. Si la clave se encuentra en los datos, se devuelve el valor de la clave y ese valor reemplazará a la clave en el resultado final. Si no se encuentra la clave, se devuelve una cadena vacía.

Ejemplo de plantilla:

<div id="mytemplate"> 
    <p>%test%</p> 
    <p>%word%</p> 
</div> 

Ejemplo de llamada:

document.getElementById("my").innerHTML=template("mytemplate",{test:"MYTEST",word:"MYWORD"}); 
+1

Gracias, Esto está muy bien. Estaba a punto de incluir un plugin como "jQuery printf" en mi aplicación, pero esto es todo lo que realmente necesito :-) – rescdsk

+2

¡Excepto! ¡Que es incapaz de insertar el número cero! La función de reemplazo realmente debería verificar que el valor sea nulo/indefinido, en lugar de verídico. – rescdsk

+0

rescdsk: Tiene razón, no fue capaz de insertar ningún valor falso como 0, NaN, falso, nulo e indefinido. He actualizado el código para usar 'hasOwnProptery' en el objeto. Si la propiedad existe, se incluirá (incluso sin definir). Si la propiedad no existe, entonces será un espacio vacío. Puede cambiarlo a lo que desee insertando texto entre el último '" "'. – some

1

Si usted está dispuesto a utilizar el Prototype library, tienen buen construido en la funcionalidad de plantillas.

Eso se vería así:

element.innerHTML = (new Template(element.innerHTML)).evaluate({ 
    title: 'a title', 
    keyword: 'some keyword', 
    content: 'A bunch of content', 
    id: 'id here' 
}) 

Esto sería especialmente agradable si se ejecuta el código en un bucle debido a la facilidad de crear objetos JSON/javascript objetos literales.

Aún así, no esperaría ningún aumento de velocidad.

Además, usted tendría que cambiar su estilo de delimitador para #{keyword} en lugar de %keyword%

1

Su método es una forma estándar para implementar un sistema de plantillas de hombre pobre, así que está bien.

Puede valer la pena revisar algunas bibliotecas de plantillas de JavaScript, como JST.

0

Mustachejs es ideal para muy elegante plantillas:

<div id='sample'> 
    <h4>{{TITLE}}</h4> 
    <p>Text text {{KEYWORD}} text</p> 
    <p>{{CONTENT}}</p> 
    <img src="images/{{ID}}/1.jpg" /> 
</div> 

A continuación, puede utilizar la plantilla de algo como esto:

var template = document.getElementById(templateid).innerHTML; 
var newHtml = Mustache.render(template, { 
    TITLE: some_var_with_title, 
    KEYWORD: some_var_with_keyword, 
    CONTENT: some_var_with_content, 
    ID: some_var_with_id 
}); 
document.getElementById('sample').innerHTML = newHtml; 

Esto es especialmente funciona muy bien si usted está recibiendo JSON de vuelta de una llamada Ajax - Puede pasarlo directamente a la llamada Mustache.render().

Las pequeñas variaciones permiten ejecutar la misma plantilla en cada navegador o servidor. Vea https://github.com/janl/mustache.js para más detalles.

-1
var template = "<div id='sample'><h4>%VAR%</h4><p>Text text %VAR% text</p><p>%VAR%</p><img src="images/%VAR%/1.jpg" /></div>"; 

var replace = function(temp,replace){ 
temp = temp.split('%VAR%'); 
for(var i in replace){ 
      if(typeof temp[i] != 'undefined'){ 
      temp[i] = temp[i] + replace[i]; 
      } 
     } 
    return temp.join(''); 
} 

replace(template,['title','keyword','content','id']) 
+2

Agregue algunas explicaciones a su respuesta – Alex

+0

Sus presupuestos están rotos. –

0

Este enfoque genera plantillas de función que se pueden almacenar en caché:

function compileMessage (message) { 

    return new Function('obj', 'with(obj){ return \'' + 
    message.replace(/\n/g, '\\n').split(/{{([^{}]+)}}/g).map(function (expression, i) { 
     return i%2 ? ('\'+(' + expression.trim() + ')+\'') : expression; 
    }).join('') + 
    '\'; }'); 

} 

var renderMessage = compileMessage('Hi {{ recipient.first_name }},\n\n' + 

'Lorem ipsum dolor sit amet...\n\n' + 

'Best Regarts,\n\n' + 

'{{ sender.first_name }}'); 


renderMessage({ 
    recipient: { 
    first_name: 'John' 
    }, 
    sender: { 
    first_name: 'William' 
    } 
}); 

devuelve:

"Hi John, 

Lorem ipsum dolor sit amet... 

Best Regarts, 

William" 
Cuestiones relacionadas