基于JS实现新闻Feed实时搜索更新的技术问题求助
问题描述
我学JavaScript两周了,现在用Guardian API做新闻应用。目前能加载新闻图片、链接和标题,但实时搜索功能用不了。想要用户输入搜索内容时,页面能即时更新新闻Feed。控制台显示逻辑是对的,但页面上搜不到结果。
试过创建「搜索到的文章」新数组,太麻烦还没法实时更新Feed;也试过切换h1标题的可见性,一直报「not a function」错误。求可行的解决方案。
视图类(ArticlesView)
class ArticlesView { constructor(model, api) { this.model = model; this.api = api; this.articlesFromModel = this.model.getArticles(); this.newsFeed = document.querySelector("#news-feed"); this.clearFeedBtn = document.querySelector("#clear-feed-button"); this.refreshBtn = document.querySelector("#refresh-button"); this.searchInput = document.querySelector("#search-input"); this.allHeadlines = [document.querySelectorAll("h1")]; this.clearFeedBtn.addEventListener("click", () => { this.clearFeed(); }); this.searchInput.addEventListener("input", (e) => { this.articlesFromModel.forEach((article) => { const searchInput = e.target.value.toLowerCase(); const isVisible = article.webTitle.toLowerCase().includes(searchInput); if (!isVisible) { // 不知道这里该写什么 } console.log(searchInput); console.log(article.webTitle); console.log(isVisible); }); }); } displayArticlesFromApi() { this.api.loadArticles( (repoData) => { this.model.addArticle(repoData.response.results); this.displayArticles(); }, () => { this.displayError(); } ); } displayArticles() { this.articlesFromModel.forEach((article) => { this.addImage(article); this.addHeadline(article); }); } addHeadline(article) { const h1 = document.createElement("h1"); h1.className = "news-title"; h1.innerText = article.webTitle; h1.onclick = () => { window.location.href = article.webUrl; }; this.newsFeed.append(h1); } addImage(article) { const img = document.createElement("img"); img.className = "news-image"; img.setAttribute("id", article.id); img.src = article.fields.thumbnail; img.onclick = () => { window.location.href = article.webUrl; }; this.newsFeed.append(img); } displayError() { let errorMessage = document.createElement("div"); errorMessage.className = "error"; errorMessage.textContent = "Oops, something went wrong!"; this.newFeed.append(errorMessage); } clearFeed() { const images = document.querySelectorAll("img.news-image"); images.forEach((element) => { element.remove(); }); const headlines = document.querySelectorAll("h1.news-title"); headlines.forEach((element) => { element.remove(); }); } } module.exports = ArticlesView;
模型类(ArticlesModel)
class ArticlesModel { constructor() { this.articles = []; } getArticles() { return this.articles; } addArticle(article) { article.forEach((a) => { this.articles.push(a); }); } reset() { this.articles = []; } } module.exports = ArticlesModel;
API类(GuardianApi)
class GuardianApi { constructor() { this.apiURL = `https://content.guardianapis.com/search?api-key=${apikey}&show-fields=thumbnail`; } loadArticles(callback) { fetch(this.apiURL) .then((response) => response.json()) .then((data) => { callback(data); }); } } module.exports = GuardianApi;
入口文件(index.js)
console.log("the app is running"); const ArticlesModel = require("./src/ArticlesModel.js"); const ArticlesView = require("./src/ArticlesView.js"); const GuardianApi = require("./src/GuardianApi.js"); const client = new GuardianApi(); const model = new ArticlesModel(); const view = new ArticlesView(model, client); view.displayArticlesFromApi();
HTML文件
<!doctype html> <html> <head> <link rel="stylesheet" href="style.css"> <title> Your Daily News Feed</title> </head> <body> <h1>News Feed</h1> <input type="search" id="search-input" placeholder="e.g. Football..."> <br><br> <button onClick="window.location.reload();">Refresh Page</button> <button id="clear-feed-button">Clear Feed</button> <br> <br> <div id="news-feed"> </div> </body> <script src="bundle.js"></script> </html>
解决方案
核心问题分析
- 构造函数里的
articlesFromModel是初始空数组的引用,API加载新文章后不会自动更新,导致搜索时拿不到最新数据 - 没有把文章数据和对应的DOM元素绑定,找不到要控制可见性的元素
this.allHeadlines = [document.querySelectorAll("h1")];写法错误,把NodeList塞进数组,后续操作必然报错
具体修复步骤
1. 绑定文章数据与DOM元素
修改addHeadline和addImage方法,给元素加自定义属性关联文章ID:
addHeadline(article) { const h1 = document.createElement("h1"); h1.className = "news-title"; h1.innerText = article.webTitle; h1.dataset.articleId = article.id; // 绑定文章ID h1.onclick = () => { window.location.href = article.webUrl; }; this.newsFeed.append(h1); } addImage(article) { const img = document.createElement("img"); img.className = "news-image"; img.dataset.articleId = article.id; // 绑定文章ID img.src = article.fields.thumbnail; img.onclick = () => { window.location.href = article.webUrl; }; this.newsFeed.append(img); }
2. 修复搜索逻辑
每次输入时从模型拿最新文章,通过文章ID匹配DOM元素并控制显示:
this.searchInput.addEventListener("input", (e) => { const searchTerm = e.target.value.toLowerCase(); const allArticles = this.model.getArticles(); allArticles.forEach(article => { const isMatch = article.webTitle.toLowerCase().includes(searchTerm); // 通过自定义属性找对应元素 const headline = document.querySelector(`h1.news-title[data-article-id="${article.id}"]`); const image = document.querySelector(`img.news-image[data-article-id="${article.id}"]`); if (headline) headline.style.display = isMatch ? "block" : "none"; if (image) image.style.display = isMatch ? "block" : "none"; }); });
3. 确保获取最新文章数据
删掉构造函数里的this.articlesFromModel = this.model.getArticles();,每次需要文章时直接调用this.model.getArticles(),比如修改displayArticles:
displayArticles() { const allArticles = this.model.getArticles(); allArticles.forEach((article) => { this.addImage(article); this.addHeadline(article); }); }
4. 修复拼写错误
displayError里的this.newFeed应为this.newsFeed(少了一个s)
额外优化
给搜索加防抖,避免输入时频繁触发事件:
let debounceTimer; this.searchInput.addEventListener("input", (e) => { clearTimeout(debounceTimer); debounceTimer = setTimeout(() => { // 上面的搜索逻辑放这里 }, 300); });
内容的提问来源于stack exchange,提问作者Tardigrade77
相关产品推荐
相关产品推荐

