首页 > 解决方案 > 转义从 onclick javascript 函数返回的 JSON

问题描述

我目前在从 onclick 函数返回 JSON 时遇到问题。有时从调用返回的 JSON 是有效的并且会正确显示,有时它会由于被读取为结束引号或类似内容而中断。

生成 HTML 的位置:

    newsapi.v2.everything({
q: 'football transfer',
language: 'en',
from: '2020-01-30',
to: '2020-01-31',
sortBy: 'relevancy',
pageSize: 100
}).then(response => {
    var news = response
    var parentNode = document.getElementsByClassName("Content")[0];
    var i = 0; 
    while(i < news.articles.length) {

        var curArticle = JSON.stringify(news.articles[i])

        parentNode.insertAdjacentHTML("beforeend", "<a href='#' onclick='toggleSide("+ curArticle +")'> <div class='NewsItem newsID"+i+"'> <p> <b>" + news.articles[i].title +  "</b> </p>" +
        "<p> <i>" + news.articles[i].description + "</i> </p>" +
        "<p> <a href='"+ news.articles[i].url +"' target='_blank'>Source</a> </p> <hr> </div> </a> " )
        i++
    }
});

toggleSide 功能:

global.toggleSide = function(newsArticle) {

var newsItems = document.getElementsByClassName("Content").length
var newsElems = document.querySelectorAll(".Content");

if (document.getElementById("Sidebar") == null) {
    if(newsItems > 0) {
        [].forEach.call(newsElems, function(el) {
            el.classList.remove("Content");
            el.classList.add("ContentMinimised");
        });
        var sidebar = document.createElement("div");
        sidebar.setAttribute('id', 'Sidebar');
        document.body.appendChild(sidebar);
        var parentNode = document.getElementById("Sidebar");
        parentNode.insertAdjacentHTML("beforeend", "<div id='NewsInfo'> <br> <h3>" + 
            "<a href='" + newsArticle.url + "' target='_blank' >" + 
            newsArticle.title + "</a> </h3>" +
            "<p>" + newsArticle.author + " — " + newsArticle.source.name + "</p>" +
            "<p>" + newsArticle.description + "</p>" +
            "<img src='" + newsArticle.urlToImage + "' class='NewsImage'>" +
            "<p>" + newsArticle.publishedAt + "</p>" +
            "<p> Content: <br>" + newsArticle.content + "</p>" + "<a href='#' onclick='closeSidebar()'> <img class='CloseButton' src='./close.png' alt='Close'> </a>")
        }

这是生成的 HTML 的屏幕截图。如您所见,一些被解析为完全有效的 JSON,而另一些则提前中断。

JSON 通过 HTML 传递

研究了几种转义 JSON 的方法,但很难将它们应用到我的代码中。仍处于学习阶段,因此我们将不胜感激!

标签: javascripthtmljsononclickescaping

解决方案


这看起来像一个XY 问题。更好的方法是根本不将您的 JSON 插入 HTML。相反,您可以使用 将事件侦听器绑定到元素addEventListener,这样会更干净。这是一个例子:

// Not doing a request here, but for the purpose of this demo...
requestCallback({"status":"ok","totalResults":10,"articles":[{"source":{"id":null,"name":"Nytimes.com"},"author":"Motoko Rich","title":"‘We’re in a Petri Dish’: How a Coronavirus Ravaged a Cruise Ship - The New York Times","description":"More than three days passed before Japan imposed a quarantine. That delay and other missteps helped produce the largest outbreak of the virus beyond China.","url":"https://www.nytimes.com/2020/02/22/world/asia/coronavirus-japan-cruise-ship.html","urlToImage":"https://static01.nyt.com/images/2020/02/22/world/22ship-reconstruct-still/22ship-reconstruct-still-facebookJumbo.jpg","publishedAt":"2020-02-22T10:23:00Z","content":"She was told that it was up to the Japanese health ministry, and that no tests were available on board. After a day passed, her husband, John, called the U.S. Embassy in Tokyo and tried to convince an official that everybody needed to be tested.\r\nWere in a pe… [+1119 chars]"},{"source":{"id":null,"name":"Tomsguide.com"},"author":"Philip Michaels","title":"Samsung Galaxy S20 Ultra benchmarks: The new Android phone to beat - Tom's Guide","description":"The Galaxy S20 Ultra benchmarks are in, and there's a new standard for Android phones","url":"https://www.tomsguide.com/news/galaxy-s20-ultra-benchmarks","urlToImage":"https://cdn.mos.cms.futurecdn.net/yQ3UVFY7KyVXW8gREVjpP7-1200-80.jpg","publishedAt":"2020-02-22T07:00:00Z","content":"The Galaxy S20 Ultra still can't top Apple's latest iPhones for performance. But the gap between the leading Android phone and Apple's pace-setting flagships is more narrow than it was before Samsung's latest phone came along.\r\nThat's our takeaway after we ha… [+6593 chars]"},{"source":{"id":"cnn","name":"CNN"},"author":"Helen Regan, CNN","title":"Fears over containing novel coronavirus grow as cases outside China spike - CNN","description":"Concerns are growing over the global spread of the novel coronavirus after a spike in cases outside of mainland China among people with no connection to China or the city of Wuhan, ground zero for the outbreak.","url":"https://www.cnn.com/2020/02/22/asia/novel-coronavirus-covid-19-update-intl-hnk/index.html","urlToImage":"https://cdn.cnn.com/cnnnext/dam/assets/200222123543-coronavirus-seoul-medic-super-tease.jpg","publishedAt":"2020-02-22T06:09:00Z","content":"Hong Kong (CNN)Concerns are growing over the global spread of the novel coronavirus after a spike in cases outside of mainland China among people with no connection to China or the city of Wuhan, ground zero for the outbreak.\r\nWorld Health Organization (WHO) … [+6697 chars]"},{"source":{"id":"cnbc","name":"CNBC"},"author":"Reuters","title":"Trump plans to raise issue of religious freedom with Indian Prime Minister Modi, official says - CNBC","description":"Modi's government has faced large scale-protests at home and criticism abroad for enacting a citizenship law that is seen as discriminating against Muslims.","url":"https://www.cnbc.com/2020/02/22/trump-to-raise-issue-of-religious-freedom-with-indias-modi-official.html","urlToImage":"https://image.cnbcfm.com/api/v1/image/105993990-1561731409119gettyimages-1152448893.jpeg?v=1582349930","publishedAt":"2020-02-22T05:39:00Z","content":"U.S. President Donald Trump will raise the issue of religious freedom in India during his meetings with Prime Minister Narendra Modi next week, a senior administration official said, a sensitive subject for the Indian government.\r\nModi's government has faced … [+2829 chars]"},{"source":{"id":"fox-news","name":"Fox News"},"author":"Victor Garcia","title":"Laura Ingraham mocks Dems' inability to guarantee same-day Nevada results: 'Are we a Third World country?' - Fox News","description":"Do Saturday's Nevada Democratic primary caucuses even matter? That's the question Fox News host Laura Ingraham raised Friday night, on the eve of the voting -- as many other questions hovered over the contest.","url":"https://www.foxnews.com/media/laura-ingraham-bernie-is-sure-to-win-tomorrow-in-nevada","urlToImage":"https://cf-images.us-east-1.prod.boltdns.net/v1/static/694940094001/81ab5314-6aa2-4ab7-a31f-1b1d7dc30576/78a3c690-cfb5-4608-ac03-2baf258d8318/1280x720/match/image.jpg","publishedAt":"2020-02-22T05:37:29Z","content":"Do Saturday's Nevada Democratic primary caucuses even matter? That's the question Fox News host Laura Ingraham raised Friday night, on the eve of the voting -- as many other questions hovered over the contest.\r\n\"And it looks like Democrats could be facing a r… [+1773 chars]"}]});

function requestCallback(news) {
    var parentNode = document.querySelector(".Content");
    news.articles.forEach(function (article) {
      var link = document.createElement('a');
      link.href = '#';
      link.innerHTML = 
           '<div class="NewsItem">'
         +   '<p><b>' + article.title +  '</b></p>'
         +   '<p><i>' + article.description + '</i></p>'
         +   '<p><a href="' + article.url + '" target="_blank">Source</a></p><hr>'
         + '</div>';
      parentNode.appendChild(link);
      link.addEventListener('click', function (e) {
        toggleSide(article); 
        e.preventDefault(); // Prevent jumping to the top of the page
      });
    });
}

// I don't know what your toggleSide does because you didn't post HTML,
// so this is just to show you you can use the provided article
function toggleSide(article) {
  document.getElementById('Sidebar').innerHTML =
             '<h3>' + article.title +  '</h3>'
         +   '<p><i>' + article.author + ' — ' + article.source.name + '</i></p>'
         +   '<p>' + article.description + '</p>'
         +   '<img src="' + article.urlToImage + '"/>'
         +   '<p>' + article.content + '</p>';
}
/* Irrelevant to the question */ *{box-sizing:border-box}body{font-family:Arial,Helvetica,sans-serif}.Content{width:60%}.Content>a{display:block}#Sidebar{background:#fff;padding:.5em;position:fixed;top:0;right:0;height:100%;width:40%;overflow-y:auto;border-left:1px solid #bbb;box-shadow:0 0 10px rgba(0,0,0,.2)}img{display:block;width:100%}
<div class="Content"></div>
<div id="Sidebar">← Click on an article</div>


推荐阅读