【问题标题】:JavaScript: Replace html string from json file (no jQuery)JavaScript:从 json 文件替换 html 字符串(没有 jQuery)
【发布时间】:2017-08-20 00:38:27
【问题描述】:

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();
})();

我想用json文件中的值替换以“[”和“]”开头和结尾的html字符串(仅当我在浏览器上查看页面时)不永久。

浏览器上的示例输出:

...
   <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
    */
} 

【问题讨论】:

标签: javascript html json xmlhttprequest


【解决方案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 使用正则表达式检查 dom 值是否以“[”开头并以“]”结尾,如果为真,则用键名中的 json 值替换值 else去寻找其他的dom */ }
【解决方案2】:

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

您没有指定您对 HTML 模板的控制程度(我假设全部)以及 json 文件内容有多少差异,但我会将 idclass 属性附加到 HTML 中的相关元素模板,然后使用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);
  };
})();

请看这个小提琴的演示:https://jsfiddle.net/Perttu/wndL4fas/

【讨论】:

  • 感谢您的解决方案,但正如我在@Potato 的回答中提到的那样,为每个字符串添加“ID”并不是一个好的解决方案。因为有时html 有很多[text-here],在所有这些中添加“ID”是我认为错误的方法。我在想也许我们可以使用正则表达式来检查dom是否以“[”和“]”开头和结尾,然后替换json中的整个值。
  • @PerttuHeliseva 非常感谢您的快速回答,但正如我在对您的解决方案的第一条评论中提到的那样,我们无法在所有拥有 [text-here] 的 dom 中添加 ID,因为有时,我们有类似&lt;p&gt;[text-one], [text-two], [text-three] or more&lt;/p&gt;的东西。
  • 那么据我所知,所有这些限制(顺便说一句,在原始问题中很有用)你可行的,如果无效的选项是替换所有文本出现在DOM:document.body.innerHTML = document.body.innerHTML.replace('[' + keyName + ']', content);
【解决方案3】:

感谢alexthe matchText function

我想建议以下键值对象格式作为您的 JSON 数据。它将更简单、更快并且使用更少的网络带宽。

您可以使用此函数将数据转换为键值对象格式。

var map = {};
data.map(function(d) {
  map[d.PageTextKeyName] = d.PageTextValueName;
});

请看this 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 及其兄弟节点(通过nextSibling)迭代给定节点的子节点。

NodeType是一个Html元素时(案例1),它调用matchText递归迭代节点。

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

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

【讨论】:

  • 哇这个效果很好!但是,您能否解释一下这个脚本是如何工作的?我怎样才能删除上面多余的&lt;span class="replace"&gt;?还有一个错误,当一个 DOM 有这个 &lt;p&gt;[text-one-here] - [text-two-here]&lt;/p&gt; 时,下一个有 [text-here] 的 DOM 不会转换。
  • 我已更新小提琴以修复错误。请检查。
  • 嗨@SenJacob 谢谢你的解决方案,但我有一个问题,当我在我的页面上使用它时,我遇到了一个错误“未捕获的 TypeError:无法读取属性 'nodeType' of null”你可以在这里查看:jsfiddle.net/kdgop88y/4
  • 非常感谢您提供此解决方案,非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-04
  • 2012-03-08
  • 2018-05-04
  • 2012-10-03
  • 2022-11-14
  • 2016-02-21
  • 2018-11-09
相关资源
最近更新 更多