简体   繁体   中英

Using text-nodes to render JSON data into ready HTML page

I'm trying to achieve something similar to what JSRender does, but I'm not sure how to go about it. Consider the HTML "template" below:

<!DOCTYPE html>
    <body>
        <div class="content">
            <div class="notifications">{{:notifications}} notifications</div>
            <div class="something else">this is {{:something_else}} to show</div>
        </div>
    </body>
</html>

Supposed I have JSON data like so:

{"notifications": "3", "something_else": "some arbitrary data"}

How do I populated this data into the HTML page? The way JSRender does it seems to involve creating a separate template in a <script> tag, then populating the data into the template and finally copying the template into an empty container. Is there a way to avoid this template redefinition? I believe my HTML page can already act like a template as demonstrated above.

The Question : is it possible to display JSON data into a ready HTML page (such as above) with defined "data positions"? As part of the challenge, using $('.notifications').html() -related methods should be avoided since this would be cumbersome when handling large extensive data.

You can do that using top-level JsViews top-level data-linking - with an element such as a <span> for each insertion point.

<div class="content">
  <div >this is <span data-link="something_else></span> to show</div>
  ...

Code:

$.link(true, ".content", data);

In addition, the data is data-bound to the HTML.

Here is a sample which shows the data-binding by letting you actually change a data property dynamically:

It also shows data-linking to the src and title attributes of an <img> tag. See here for more information about different data-link targets.

 var data = {notifications: "3", something_else: "some arbitrary data", imgData: {img1: {src: "http://www.jsviews.com//icons/android-chrome-36x36.png", desc: "some image"}}}; $.link(true, ".content", data, {replace: true}); 
 <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jsviews/0.9.90/jsviews.js"></script> <div class="content"> <div ><span data-link="notifications"></span> notifications</div> <div >this is <span data-link="something_else"></span> to show</div> <img data-link="src{:imgData.img1.src} title{:imgData.img1.desc}"/> <br/>Edit: <input data-link="something_else"/> </div> 

While BorisMoore's answer addresses the question adequately, I crafted a "hack" that also appears to work with the ability to support attributes on almost all elements, though I don't know to what extent it is reliable.

However, this requires one to change the data structure to also indicate the type of element and even the part of it (attribute) where the data is to be inserted. The data would need to look like so:

 {"notifications": "span:|3", "something_else": "span:|some arbitrary data", "avatar":"img.alt:|A"}

Then in JQuery, one could do something like so:

$.each(data, function(key, value) {
    value = value.split(":|");
    var element = value[0];
    value = value[1];
    if(element.indexOf('.') == -1){
        var content = $(element + ':contains("{{:'+key+'}}")').last().html().replace("{{:"+key+"}}", value);
        $(element + ':contains("{{:'+key+'}}")').html(content);
    }else{
        element = element.split('.');
        var attribute = element[1];
        element = element[0];
        $(element + '['+attribute+'="{{:'+key+'}}"]').last().attr(attribute, value);
    }
});

EDIT : The main drawback of this method is that it unbinds all attached events when an elements property is modifed this way.

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