微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用按钮点击和文本框加载 JSON 数据

如何解决使用按钮点击和文本框加载 JSON 数据

所以我正在学习 javascript 并且我正在尝试创建一个电影数据库用户在文本框中输入电影 ID 并单击“加载电影按钮”,该按钮加载有关具有该特定 ID 的电影的信息。

我收到了一个 json 文件,其中包含电影的元素,例如 ID、标题、上映日期等。我无法将点击处理程序添加到我的电影请求按钮,该按钮创建一个 XMLHttpRequest 对象并提交一个特定电影的“GET”请求。如果此请求成功,我的回调函数中可用的响应文本将是包含以下格式的电影信息的 JSON 字符串。所以在控制台中它会打印出来:

{
  "Title": "Guardians of the galaxy Vol. 2","Year": "2017","Rated": "PG-13","Released": "05 May 2017","Runtime": "136 min","imdbID": "tt3896198","Response": "True"
}

它应该只是在加载的 html 页面中将标题和运行时打印为常规文本,因为这就是我在 javascript 文件中请求的内容

为简单起见,这个 json 文件只包含 1 部电影,但我的原始 json 文件将包含数千部电影的信息,所以当我搜索特定的电影 ID 时,它应该只加载一部电影的信息而不是所有电影的信息json 文件中的电影。因此,如果我在文本框中输入“tt3896198”,此 id 应加载电影“银河护卫队 2”的数据,因为这是与这部电影匹配的 id,如 json 文件中所示。

我尝试查找如何使用 XMLHttpRequests 和 JSON 解析从 json 文件中打印特定信息,但问题是我在网上看到的示例能够通过执行诸如“movie.title”之类的操作来访问其 json 文件中的变量,因为他们的变量是小写的。我的 JSON 文件中的所有变量似乎都是大写的,我认为不允许做 movie.Title。

此外,我想知道如何根据用户输入的 ID 加载电影?有 1000 部具有唯一 ID 的电影,我不确定如何仅加载一部其 ID 与文本框中输入的 ID 匹配的电影。

现在我的页面显示一个文本框和一个按钮,但按钮不起作用。任何帮助将不胜感激,当我单击按钮时,我遇到的主要问题主要是从 json 文件获取数据以显示在控制台以及 HTML 页面上。如果有人可以帮助或指导我让电影 id 元素工作,那也将不胜感激!

电影.html:

<html>
    <head>
        <title>Movies page</title>
    </head>

    <body onload="init()">
        <div>
            <input type="text" placeholder="Search" name="textBox">
            <button type="button" id="retrieveMovies">Load a movie</button>
        </div>
        <br />
        <div id="moviediv">

        </div>

    <script src="movies.js"></script>
    </body>

</html>

movie.js:

let movies = [];

function init(){
    document.getElementById("retrieveMovies").onclick = loadMovies;
    loadMovies();
}

function loadMovies(){
    let xhttp = new XMLHttpRequest();

    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            let responSEObject = JSON.parse(xhttp.responseText);
            movies = responSEObject.results;
            render();
        }
    };

    xhttp.open("GET","movie.json",true);
    xhttp.send();
}

function render(){
    let content = "";
    movies.forEach(movie =>{
        content += `
            <div>
                <p> Movie: ${movie.Title}</p>
                <br/>
                <p> Runtime: ${movie.Runtime}</p>
            </div>
        `
    })
    document.getElementById("moviediv").innerHTML = content;
}

movie.json:

{"Title":"Guardians of the galaxy Vol. 2","Year":"2017","Rated":"PG-13","Released":"05 May 2017","Runtime":"136 min","imdbID":"tt3896198","Response":"True"}

更新:所以我尝试创建一个服务器来运行应用程序,而不是直接从我的目录中打开 html 文件

server.js:

const http = require('http');
const fs = require('fs');

const server = http.createServer(function (request,response) {
    if(request.method === "GET" && (request.url === "/index.html" || request.url === "/")){
        fs.readFile('index.html','utf8',function(err,contents) {
            if(err){
                response.writeHead(500,{ "Content-Type": "text/html"})
                response.end();
                return;
            }
            response.writeHead(200,{ "Content-Type": "text/html"})
            response.end(contents);
        });
    }else if(request.method === "GET" && request.url === "/style.css"){
        fs.readFile('style.css',{ "Content-Type": "text/css"})
                response.end();
                return;
            }
            response.writeHead(200,{ "Content-Type": "text/css"})
            response.end(contents);
        });
    }else if(request.method === "GET" && request.url === "/movies.js"){
        fs.readFile('movies.js',{ "Content-Type": "application/javascript"})
                response.end();
                return;
            }
            response.writeHead(200,{ "Content-Type": "application/javascript"})
            response.end(contents);
        });
    }
});

server.listen(3000);
console.log('Server running at http://127.0.0.1:3000/');

我在我的谷歌浏览器中输入 localhost:3000,它会引导我到 html 页面。虽然这解决了我之前遇到的错误,但单击添加按钮似乎仍然没有任何作用。

解决方法

确保在调用 movies.js 之前加载您的 init 文件。我会将脚本包含在 <head> 中,并立即添加 init 事件作为 DOMContentLoadeddocument 事件的回调。

注意: id 和类选择器名称还应使用“kebob-case”与“camelCase”。

index.html

将您的输入包装在一个表单中并监听 submit 事件。确保您可以访问您的查询词,例如IMDb ID。我预先加载了 "tt3896198" 以便初始提取将基于它进行过滤。如果删除文本,则不会过滤任何内容。如果有一个词,它会过滤。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Movies page</title>
    <link rel="stylesheet" href="style.css">
    <script type="text/javascript" src="movies.js"></script>
    <script type="text/javascript">
      document.addEventListener('DOMContentLoaded',init);
    </script>
  </head>
  <body>
    <form name="movie-search" onsubmit="return false">
      <input type="text" id="query" name="query" placeholder="Search" value="tt3896198" />
      <button id="retrieve-movies">Load a movie</button>
    </form>
    <br />
    <div id="movie-results"></div>
  </body>
</html>

movies.js

使用 fetch 而不是 XMLHttpRequest 加载电影。监听表单的 submit 事件并确保在 HTML 中返回 false,以避免服务器端提交/重定向。我还将变量存储在上下文数据结构中。这使得代码更容易遵循。

const context = {
  elements: {
    searchForm: null,results: null
  },movies: []
};

const init = () => {
  Object.assign(context.elements,{
    searchForm: document.forms['movie-search'],results: document.querySelector("#movie-results")
  });

  context.elements.searchForm.addEventListener('submit',loadMovies);
  loadMovies();
};

const loadMovies = () => {
  fetch("movies.json")
      .then(response => response.json())
      .then(onLoad);
};

const onLoad = (movies) => {
  const query = context.elements.searchForm.elements.query.value.trim();
  context.movies = query ? movies.filter(({ imdbID }) => imdbID === query) : movies;
  render();
};

const render = () => {
  context.elements.results.innerHTML = context.movies.map(renderMovie).join('');
};

const renderMovie = (movie) => {
  const { imdbID,Rated,Released,Runtime,Title,Year } = movie;
  return `
    <div class="movie">
      <h2>${Title} (${Year})</h2>
      <p>${Rated} | ${formatRuntime(Runtime)} | ${Released}</p>
      <p><strong>IMDb ID:</strong> ${imdbID}</p>
    </div>
  `
};

const formatRuntime = (runtime) => {
  const
    [,mins] = runtime.match(/^(\d+) min$/),hours = Math.floor(mins / 60),minutes = mins % 60;
  return [ hours,minutes ].map(t => ('' + t).padStart(2,'0')).join(':');
};

style.css

将您的结果设置为卡片网格列。

#movie-results {
  display: grid;
  grid-auto-flow: row;
  justify-content: center;
  align-items: center;
}

.movie {
  border : thin solid grey;
  padding: 0.5em;
  margin: 0.25em 0;
}

movies.json

这应该是一个对象数组。

[
  {
    "Title": "Guardians of the Galaxy","Year": "2014","Rated": "PG-13","Released": "01 August 2014","Runtime": "121 min","imdbID": "tt2015381","Response": "True"
  },{
    "Title": "Guardians of the Galaxy Vol. 2","Year": "2017","Released": "05 May 2017","Runtime": "136 min","imdbID": "tt3896198","Response": "True"
  }
]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。