JavaScript:从JSON文件中替换HTML字符串(无需jQuery)

3

texts.json文件:

[{
  "PageTextKeyId": 1,
  "PageTextKeyName": "page-first-text",
  "PageTextValueName": "Lorem ipsum dolor sit amet"
}, {
  "PageTextKeyId": 2,
  "PageTextKeyName": "after-page-first-text",
  "PageTextValueName": "Consectetuer adipiscing elit"
}, {
  "PageTextKeyId": 3,
  "PageTextKeyName": "third-text-on-json",
  "PageTextValueName": "Sed diam nonummy nibh"
}, {
  "PageTextKeyId": 4,
  "PageTextKeyName": "this-is-the-forth",
  "PageTextValueName": "Euismod tincidunt ut laoreet"
}, {
  "PageTextKeyId": 5,
  "PageTextKeyName": "last-text-from-the-file",
  "PageTextValueName": "Dolore magna aliquam erat volutpat"
}]

index.html文件:

<!DOCTYPE html>
<html>
    <head>
        <title>Text from JSON</title>
        <meta charset="UTF-8">
        <meta name="format-detection" content="telephone=no">
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    </head>
    <body>
        <div id="container" class="some-class">
            <p>[page-first-text] - [page-first-text]</p>
            <div id="creatives">
                <b>[after-page-first-text]</b>
                <div>
                    <span>
                        <i>[third-text-on-json]</i>
                    </span>
                </div>
            </div>
            <div class="holder">
                <div id="sfc">
                    <div id="designer">
                        <a href="#">[this-is-the-forth]</a>
                    </div>
                    <div id="developer">
                        <div>
                            <div class="designer-class">
                                <a href="#">
                                    <span>[last-text-from-the-file]</span>
                                </a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <script src="script.js" ></script>
        </div>
    </body>
</html>

这只是一个示例的 html,它也可以在没有 idclass 的 DOM 中有很多的 [text-here]

这是 script.js

(function() {
    var jsonRequest = new XMLHttpRequest();
    jsonRequest.open('GET', 'texts.json');
    jsonRequest.setRequestHeader("Content-Type", "application/json");
    jsonRequest.onload = function() {
        var jsonContent = JSON.parse(jsonRequest.responseText);

        /* NEED HELP HERE */

    }
    jsonRequest.send();
})();

我希望能够动态替换网页中以"["和"]"开头结尾的html字符串,将其中的值替换成json文件中对应的值(仅在浏览器中查看页面时进行替换),不做永久更改。

浏览器上的示例输出:

...
   <body>
        <div id="container">
            <p>Lorem ipsum dolor sit amet</p>
            <div id="creatives">
                <b>Consectetuer adipiscing elit</b>
                <div>
                    <span>
                        <i>Sed diam nonummy nibh</i>
                    </span>
                </div>
            </div>
            <div id="holder">
                <div id="sfc">
                    <div id="designer">
                        <a href="#">Euismod tincidunt ut laoreet</a>
                    </div>
...

我希望可能有一个正则表达式的解决方案,例如:

var everyDom = document.getElementsByTagName('*');
for (var i=0; i<everyDom.length;i++) {
    /*
    check with regex if dom value starts with "[" and end with "]"
    if true replace value with json value from key-name
    else go and look for other doms
    */
} 

最好考虑使用AngularJS https://www.w3schools.com/angular/tryit.asp?filename=try_ng_http_get - Richardson. M
谢谢,但是我的公司只使用纯JavaScript,所以我别无选择,只能用它来修复它。 - Neo Genesis
3个回答

1
你可以给想要获取数据的元素添加一个id。
<div id="creatives">
   <b id="firstText">Consectetuer adipiscing elit</b>
</div>

在您的JavaScript中,您可以像这样访问此元素:
document.getElementById("firstText").innerHTML = YOUR JSON ELEMENT VALUE

在每个字符串上添加“ID”不是一个好的解决方案。如果我有一个大的html文件,里面有很多[text-here],我需要给每个单独的字符串都加上一个“ID”吗?我希望能够找到一个正则表达式的解决方案,类似于:var everyDom = document.getElementsByTagName('*'); for (var i=0; i - Neo Genesis

1
感谢alex提供matchText函数
我建议您使用以下键值对对象格式作为JSON数据。它将更简单、更快,并且使用更少的网络带宽。
您可以使用此函数将数据转换为键值对对象格式。
var map = {};
data.map(function(d) {
  map[d.PageTextKeyName] = d.PageTextValueName;
});

请查看

这个jsFiddle


// parsed JSON data from response
var map = {
    "page-first-text": "Lorem ipsum dolor sit amet",
    "after-page-first-text": "Consectetuer adipiscing elit",
    "third-text-on-json": "Sed diam nonummy nibh",
    "this-is-the-forth": "Euismod tincidunt ut laoreet",
    "last-text-from-the-file": "Dolore magna aliquam erat volutpat"
};

// find matching text in given nodeand apply the callback for replacement
var matchText = function(node, regex, callback, excludeElements) {
  excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas']);
  var child = node.firstChild;
  do {
    switch (child.nodeType) {
      case 1: // other html elements
        if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1) {
          continue;
        }
        // iterate next element
        matchText(child, regex, callback, excludeElements);
        break;
      case 3: // TextNode
        child.data = child.data.replace(regex, callback);
        break;
    }
  } while (!!(child = child.nextSibling));
  return node;
};

matchText(document.body, /\[(.*?)\]/gi, function(match) {
  var key = match.substring(1, match.length-1);
  return (!!map[key]) ? map[key] : match;
});

说明。

matchText函数从firstChild和它的兄弟节点(via nextSibling)开始迭代给定节点的子节点。

NodeType是一个Html元素(情况1)时,它调用matchText来递归地迭代节点。

当NodeType是一个TextNode(情况3)时,它调用回调函数来replace匹配的字符串。

/\[(.*?)\]/gi是一个RegExp,用于查找从'['到']'的任何内容。


哇,这个很好用!但是,你能否添加一下脚本的解释以及如何去掉多余的<span class="replace">?还有一个错误,当DOM中有<p>[text-one-here] - [text-two-here]</p>时,下一个包含[text-here]的DOM不会被转换。 - Neo Genesis
我已经更新了fiddle以修复这个bug,请检查。 - Sen Jacob
嗨@SenJacob,感谢您的解决方案,但我有一个问题,当我在我的页面上使用它时,出现错误“Uncaught TypeError:Cannot read property 'nodeType' of null”,您可以在此处检查:https://jsfiddle.net/kdgop88y/4/。 - Neo Genesis
非常感谢您提供的解决方案,非常感激。 - Neo Genesis

0

编辑:更新了解决方案以反映规范

您没有说明您对HTML模板有多少控制权(我假设全部),JSON文件内容有多大变化,但我会为HTML模板中相关元素附加idclass属性,然后使用document.getElementByIddocument.getElementsByClassName。然后您可以替换元素HTML。

  ...
  <b class="placeholder">[after-page-first-text]</b>
  ...

(function() {
  // find all elements with targeted class
  var placeholderElements = document.getElementsByClassName('placeholder');

  function replaceText(keyName, content) {
    for (var j = 0; j < placeholderElements.length; j++) {
        // see if text content matches [keyName]
        if(placeholderElements[j].textContent === '[' + keyName + ']') {
          console.log('found element', keyName);
          placeholderElements[j].innerHTML = content;
        break;
      }
    }
  };

  /* READ JSON */

  for (var i = 0; i < jsonContent.length; i++) {
    replaceText(jsonContent[i].PageTextKeyName, 
    jsonContent[i].PageTextValueName);
  };
})();

请查看此 fiddle 进行演示:https://jsfiddle.net/Perttu/wndL4fas/

谢谢您的解决方案,但正如我在 @Potato 的回答中提到的那样,为每个字符串添加“ID”不是一个好的解决方案。因为有时 html 有很多 [text-here],在所有这些地方都添加“ID”我认为是错误的做法。我在想也许我们可以使用正则表达式来检查DOM是否以 "[" 和 "]" 开头和结尾,然后将整个值从JSON中替换。 - Neo Genesis
@PerttuHeliseva非常感谢你的快速回答,但正如我在你的解决方案上的第一条评论中提到的那样,我们不能在所有带有 [text-here] 的 DOM 中添加ID,因为有时我们会遇到像 <p> [text-one],[text-two],[text-three]或更多</p> 这样的情况。 - Neo Genesis
那么就我所看到的,考虑到所有这些限制(顺便说一句,在原问题中提供这些信息会非常有用),您可行但不太有效的选择是替换DOM中的所有文本出现:document.body.innerHTML = document.body.innerHTML.replace('[' + keyName + ']', content); - Perttu Haliseva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接