• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

如何使用 JavaScript 过滤网页上的数据

过滤是各种网页上常用的功能。它允许用户使用提供的参数缩小数据(如类别、标签、其他特征)的范围。让我们创造我们自己的!

页面过滤的一个常见示例是允许用户根据尺寸、颜色、品牌等过滤产品的电子商务网站。

如何使用 JavaScript 过滤网页上的数据  第1张

在本教程中,我们将重新创建 作者页面并实现一个过滤器组件,以允许我们根据文章的类别过滤文章。 

数据过滤器演示

让我们来看看我们将构建什么——单击演示中的过滤器标签以切换显示的教程:

See the Pen  How to filter a list with a single param in JavaScript by Envato Tuts+ (@tutsplus)  on CodePen.

1.布局和样式

对于此演示,我们将克隆作者页面,以便直接从实时站点获取标记和样式。我们将关注的主要组件是过滤器和显示的帖子,因此我们将创建一个<div class="filter-container">和<div class="posts-container">并在 javascript 中定位它们。

我们将在 css 中设置这些容器及其内容的样式:

.posts-container {
  display: flex;
  flex-wrap: wrap;
}
.post {
  position: relative;
  width: 300px;
  margin-right: 30px;
  margin-bottom: 40px;
  border: 1px solid #e1e8ed;
  border-radius: 4px;
  margin-top: 13px;
  min-height: 300px;
  height: auto;
}
.filter-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 10px;
  padding: 32px 0;
  border-top: 1px solid #e4e4e4;
  border-bottom: 1px solid #e4e4e4;
  margin-bottom: 32px;
}
.filter-button {
  transition: background-color 200ms, color 200ms;
  background-color: transparent;
  font: inherit;
  cursor: pointer;
  display: inline-block;
  padding: 0 8px;
  color: #717171;
  border: 1px solid #9b9b9b;
  border-radius: 25px;
  font-size: 14px;
  white-space: nowrap;
}
.filter-button:hover {
  background-color: #f3f3f3;
  color: #3a3a3a;
}
.filter-button.is-active {
  background-color: #0085b6;
  border-color: #0085b6;
  color: #fff;
}

2.使用fetch api获取页面数据

在此演示中,我们将使用Fetch API检索从作者页面抓取并存储在Github gist中的模拟数据。


查看本教程,了解如何使用 JavaScript 从网页中抓取数据。

我们的模拟数据具有以下格式:

[
  {
    "title": "",
    "link": "",
    "image": "",
    "categories": [ ]
  },
  ...
]

  

这是从脚本中获取数据的脚本:

fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
).then(async (response) => {
  // handle response data 
});

一旦我们获得了获取的数据,我们就可以操作数据并将其附加到页面上。

3.向网页追加数据

对于我们获取的响应中的每个对象,我们将创建一个将在页面上显示数据的帖子 div。首先,让我们定义我们的全局变量:

let postsData = "";
const postsContainer = document.queryselector(".posts-container");

然后我们将创建一个函数createPost()来处理将新的 div 附加到 posts-container 元素。在此函数中,我们创建了一个新的 div 元素,其类名post并将其 innerhtml 设置为我们要显示的数据。

const createPost = (postData) => {
  const { title, link, image, categories } = postData;
  const post = document.createElement("div");
  post.className = "post";
  post.innerHTML = ` 
<a class="post-preview" href="${link}" target="_blank"> 
<img class="post-image" src="${image}"> 
</a> 
<div class="post-content"> 
<p class="post-title">${title}</p> 
<div class="post-tags"> 
${categories
            .map((category) => {
              return '<span class="post-tag">' + category + "</span>";
            })
            .join("")} 
</div> 
</div> 
`;
  postsContainer.append(post);
};

在我们的帖子 innerHTML 中,我们使用我们的join("")方法categories.map()删除每个数组中包含的“,”符号。

现在我们可以更新响应函数以createPost()在获取数据后调用该函数:

fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
).then(async (response) => {
  postsData = await response.json();
  postsData.map((post) => createPost(post));
});

4.从响应中获取过滤器参数

由于我们使用的是 javaScript,因此我们可以映射我们的响应以创建过滤器参数的动态列表。让我们为过滤器数据包含全局变量:

let filterData = "";
const filterContainer = document.querySelector(".filter-container");

现在我们要编写一个脚本,对每个响应对象中的类别数组进行排序并返回一个唯一列表。我们可以更新我们的响应对象来处理获取过滤器参数的唯一列表

fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
).then(async (response) => {
  postsData = await response.json();
  postsData.map((post) => createPost(post));
  filterData = [
    ...new Set(
      postsData
        .map((post) => post.categories)
        .reduce((acc, curVal) => acc.concat(curVal), [])
    )
  ];
});

分解我们的 filterData 的代码:

  • 我们[... new Set]用来创建一个唯一值数组。Set返回一个具有唯一值的对象,扩展语法 [...] 将该对象转换为一个数组。

  • 我们通过 postsData 进行映射,以获取数据响应中每个帖子对象的类别数组。

  • 我们使用该.reduce()方法将每个帖子对象的类别数组组合成一个数组。

一旦我们从帖子类别中获得了我们的唯一过滤器值数组,我们就可以创建一个函数来将每个过滤器附加到页面。我们将创建一个新的按钮元素并设置 innerText 和 className。我们还将设置一个“数据状态”属性来处理单击时更改按钮状态。

每个过滤器按钮都会有一个点击事件监听器设置为 handleButtonClick 函数,它将负责处理过滤逻辑。

const createFilter = (filter) => {
  const filterButton = document.createElement("button");
  filterButton.className = "filter-button";
  filterButton.innerText = filter;
  filterButton.setAttribute('data-state', 'inactive');
  filterButton.addeventListener("click", (e) =>
    handleButtonClick(e, filter)
  );
  filterContainer.append(filterButton);
};

并更新我们的响应函数以调用该createFilter()函数:

fetch("https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials"
).then(async (response) => {
  postsData = await response.json();
  postsData.map((post) => createPost(post));
  filterData = [
    ...new Set(
      postsData
        .map((post) => post.categories)
        .reduce((acc, curVal) => acc.concat(curVal), [])
    )
  ];
  filterData.map((filter) => createFilter(filter));
});

5.点击时处理过滤

现在我们已经获得了过滤按钮和初始数据,我们可以定义一个函数来处理单击按钮时过滤数据。这可以使用.filter()posts 数据数组上的方法来完成。

这是我们将用于过滤数据的逻辑:

  • 创建一个handleFilterPosts()接受过滤参数的函数

  • 使用该.filter()方法根据过滤器参数过滤我们的帖子数据

  • 清除 posts-container 中的所有元素并将新的 filteredData 附加到容器中。

const handleFilterPosts = (param) => {
  let filteredPosts = [...postsData].filter(post => post.categories.includes(param))
  
  postsContainer.innerHTML = "";
  filteredPosts.map(post => createPost(post))
};

我们想要检测按钮何时被点击并更新按钮状态。在本教程中,我们将切换按钮,如果单击一次,按钮将设置为活动状态,如果再次单击,按钮将设置为非活动状态。

const handleButtonClick = (e, param) => {
  const button = e.target;
  const buttonState = button.getAttribute('data-state');
  
  if (buttonState =='inactive') {
    button.classList.add('is-active');
    button.setAttribute('data-state', 'active');
  } else {
    button.classList.remove('is-active');
    button.setAttribute('data-state', 'inactive')
  }
}

我们还想确保一次只选择一个按钮,如果没有选择任何按钮,帖子应显示默认数据,以便我们可以创建函数来处理该逻辑:

const resetFilterButtons = (currentButton) => {
  const filterButtons = document.querySelectorAll('.filter-button');
  [...filterButtons].map(button => {
    if (button != currentButton) {
      button.classList.remove('is-active');
      button.setAttribute('data-state', 'inactive')
    }
  })
}
const resetPosts = () => {
  postsContainer.innerHTML = "";
  postsData.map((post) => createPost(post));
}

最后,我们可以更新我们的按钮点击功能:

const handleButtonClick = (e, param) => {
  const button = e.target;
  const buttonState = button.getAttribute('data-state');
  resetFilterButtons(button);
  
  if (buttonState =='inactive') {
    button.classList.add('is-active');
    button.setAttribute('data-state', 'active');
    handleFilterPosts(param)
  } else {
    button.classList.remove('is-active');
    button.setAttribute('data-state', 'inactive')
    resetPosts()
  }
}

结论

至此,我们已经使用原生 JavaScript 为网页上的数据完全构建了一个过滤组件!

See the Pen  How to filter a list with a single param in JavaScript by Envato Tuts+ (@tutsplus)  on CodePen.

文章目录
  • 数据过滤器演示
  • 1.布局和样式
  • 2.使用fetch api获取页面数据
  • 3.向网页追加数据
  • 4.从响应中获取过滤器参数
  • 5.点击时处理过滤
  • 结论
  • 发表评论