简体   繁体   中英

best way to inject html using javascript

I'm hoping that this isn't too subjective. I feel there is a definitive answer so here goes.

I want to create this html on the fly using JS (no libraries):

<a href="#" id="playButton">Play</a>
<a href="javascript: void(0)" id="muteUnmute">Mute</a>
<div id="progressBarOuter"> 
  <div id="bytesLoaded"></div>
    <div id="progressBar"></div>
</div>
<div id="currentTime">0:00</div>
<div id="totalTime">0:00</div>

using javascript. I know I can do this using createElement etc but it seems extremely long winded to do this for each element. Can anyone suggest a way to do this with more brevity.

I do not have access to a library in this project....so no jquery etc.

Keep your markup separate from your code:

You can embed the HTML snippets that you'll be using as hidden templates inside your HTML page and clone them on demand:

<style type="text/css">
#templates { display: none }
</style>
...
<script type="text/javascript">
var node = document.getElementById("tmp_audio").cloneNode(true);
node.id = ""; // Don't forget :)
// modify node contents with DOM manipulation
container.appendChild(node);
</script>
...
<div id="templates">
    <div id="tmp_audio">
        <a href="#" class="playButton">Play</a>
        <a href="#" class="muteUnmute">Mute</a>
        <div class="progressBarOuter"> 
            <div class="bytesLoaded"></div>
            <div class="progressBar"></div>
        </div>
        <div class="currentTime">0:00</div>
        <div class="totalTime">0:00</div>
    </div>
</div>

Update: Note that I've converted the id attributes in the template to class attributes. This is to avoid having multiple elements on your page with the same ids. You probably don't even need the classes. You can access elements with:

node.getElementsByTagName("div")[4].innerHTML =
    format(data.currentTime);

Alternatively, you can act on the HTML of the template:

<script type="text/javascript">
var tmp = document.getElementById("tmp_audio").innerHTML;
// modify template HTML with token replacement
container.innerHTML += tmp;
</script>

Shove the entire thing into a JS variable:

var html = '<a href="#" id="playButton">Play</a>';
html += '<a href="javascript: void(0)" id="muteUnmute">Mute</a>';
html += '<div id="progressBarOuter"><div id="bytesLoaded"></div><div id="progressBar"></div></div>';
html += '<div id="currentTime">0:00</div>';
html += '<div id="totalTime">0:00</div>';

Then:

document.getElementById("parentElement").innerHTML = html;

if you want theN:

document.getElementById("totalTime").innerHTML = "5:00";

You can use

<script type="text/javascript">
    function appendHTML() {
        var wrapper = document.createElement("div");
        wrapper.innerHTML = '\
<a href="#" id="playButton">Play</a>\
<a href="javascript: void(0)" id="muteUnmute">Mute</a>\
<div id="progressBarOuter"> \
<div id="bytesLoaded"></div>\
    <div id="progressBar"></div>\
</div>\
<div id="currentTime">0:00</div>\
<div id="totalTime">0:00</div>\
';
        document.body.appendChild(wrapper);
    }
</script>

If you live in 2019 and beyond read here.

With JavaScript es6 you can use string literals to create templates.

create a function that returns a string/template literal

function videoPlayerTemplate(data) {
    return `
        <h1>${data.header}</h1>
        <p>${data.subheader}</p>
        <a href="#" id="playButton">Play</a>
        <a href="javascript: void(0)" id="muteUnmute">Mute</a>
        <div id="progressBarOuter"> 
            <div id="bytesLoaded"></div>
            <div id="progressBar"></div>
        </div>
        <time id="currentTime">0:00</time>
        <time id="totalTime">0:00</time>
    `
}

Create a JSON object containing the data you want to display

var data = {
     header: 'My video player',
     subheader: 'Version 2 coming soon'
}

add that to whatever element you like

const videoplayer = videoPlayerTemplate(data);
document.getElementById('myRandomElement').insertAdjacentHTML("afterbegin", videoplayer);

You can read more about string literals here

edit: HTML import is now deprecated .

Now with Web Components you can inject HTML using an HTML import .

The syntax looks like this:

<link rel="import" href="component.html" >

This will just load the content of the html file in the href attribute inline in the order it appears. You can any valid html in the loaded file, so you can even load other scripts if you want.

To inject that from JavaScript you could do something of the likes of:

var importTag = document.createElement('link');
importTag.setAttribute('rel', 'import');
importTag.setAttribute('href', 'component.html');
document.body.appendChild(importTag);

At the time I am writing this, Chrome and Opera support HTML imports. You can see an up to date compatibility table here http://caniuse.com/#feat=imports

But don't worry about browsers not supporting it, you can use it in them anyway with the webcomponentsjs polyfill.

For more info about HTML imports checkhttp://webcomponents.org/articles/introduction-to-html-imports/

If you don't need any validation for your syntax (which is what makes createElement() so nice) then you could always default to simply setting theinnerHTML property of the element you want to insert your markup inside of.

Personally, I would stick with using createElement() . It is more verbose but there are far less things to worry about that way.

您可以连接原始 HTML 字符串(小心转义文本并防止 XSS 漏洞),或者您可以重写 jQuery(或类似的东西)

If performance is a concern, stay away from innerHTML. You should create the whole object tree using document.createElement() as many times as needed, including for nested elements.

Finally, append it to the document with one statement, not many statements.

In my informal testing over the years, this will give you the best performance (some browsers may differ).

If HTML is ever declared in a variable, it should be simple and for a very specific purpose. Usually, this is not the right approach.

here's 2 possible cases:

  1. Your HTML is static
  2. Your HTML is dynamic

solution 1

In this case, wrap your HTML in double quotes , make it a string and save it in a variable. then push it inside HTML, here's a demo

HTML

<div id="test"></div>

JavaScript

let selector = document.querySelector("#test");

let demo_1 = "<div id='child'> hello and welcome</div>"
selector.innerHTML = demo_1;

solution 2

In this case, wrap your HTML in back ticks , make it a template literal and save it in a variable. then push it inside HTML, here, you can use variables to change your content. here's a demo

HTML

<div id="test"></div>

JavaScript

let selector = document.querySelector("#test");

let changes = 'hello and welcome'
let demo_1 = `<div id='child'>${changes}</div>`
selector.innerHTML = demo_1;

I have a situation where I pass text into a third party library, but if my model isPrivate, I'd like to add an element to the text.

return { id: item.id, text: (item.isPrivate == true) ? "<i class=\"icon-lock\" title=\"Private group.\"></i> " + item.label : item.label };

This creates issues with the way the third party library builds up its markup.

This is never a good idea, but third party libraries are there so that we don't have to write everything ourselves. In a situation like this, you have to rely on passing markup though javascript.

When i find a proper solution to this, I will give you an update

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM