JavaScript >> Javascript 文檔 >  >> JavaScript

如何在 JavaScript 中使用過濾器動態過濾數組

如何使用 JavaScript Array.Filter 方法選擇性地過濾或刪除數組中的項目。

開始使用

在本教程中,我們將使用 CheatCode 的全棧 JavaScript 框架 Joystick。 Joystick 將前端 UI 框架與用於構建應用的 Node.js 後端結合在一起。

首先,我們要通過 NPM 安裝 Joystick。確保在安裝之前使用 Node.js 16+ 以確保兼容性(如果您需要學習如何安裝 Node.js 或在計算機上運行多個版本,請先閱讀本教程):

終端

npm i -g @joystick.js/cli

這將在您的計算機上全局安裝操縱桿。安裝好之後,接下來我們新建一個項目:

終端

joystick create app

幾秒鐘後,您將看到一條消息已註銷到 cd 進入你的新項目並運行 joystick start

終端

cd app && joystick start

在此之後,您的應用應該可以運行了,我們可以開始了。

連接 UI

首先,在我們過濾我們的數組之前,我們將設置一個 UI 來對我們的工作進行上下文化。我們的目標是創建一個音樂專輯列表,我們可以根據每個專輯的流派進行過濾。

在我們運行 joystick create app 時剛剛為我們創建的應用程序中 ,在 /ui/pages/index/index.js 為我們創建了一個示例組件 .現在讓我們打開它,用過濾 UI 的骨架替換現有內容。

/ui/pages/index/index.js

import ui from '@joystick.js/ui';

const albums = [
  { id: 1, artist: 'Queens of the Stone Age', title: 'Songs for the Deaf', year: 2002, genre: 'rock' },
  { id: 2, artist: 'David Bazan', title: 'Havasu', year: 2022, genre: 'rock' },
  { id: 3, artist: 'Dwight Yoakam', title: 'This Time', year: 1993, genre: 'country' },
  { id: 4, artist: 'Sion', title: 'Sion', year: 2021, genre: 'metal' },
  { id: 5, artist: 'Every Time I Die', title: 'Low Teens', year: 2016, genre: 'metal' },
  { id: 6, artist: 'Cannonball Adderley', title: 'Somethin\' Else', year: 1958, genre: 'jazz' },
  { id: 7, artist: 'The Bad Plus', title: 'Suspicious Activity?', year: 2005, genre: 'jazz' },
  { id: 8, artist: 'Cory Hale', title: 'Soft', year: 2020, genre: 'electronic' },
  { id: 9, artist: 'Rezz', title: 'Spiral', year: 2021, genre: 'electronic' },
  { id: 10, artist: 'Autolux', title: 'Future Perfect', year: 2004, genre: 'experimental' },
];

const Index = ui.component({
  state: {
    filteredAlbums: albums,
  },
  render: ({ each, state }) => {
    return `
      <div>
        <ul>
          ${each(state.filteredAlbums, (album) => `
            <li>${album.artist} - ${album.title} (${album.year}) <span>#${album.genre.toLowerCase()}</span></li>
          `)}
        </ul>
      </div>
    `;
  },
});

export default Index;

在這裡,我們使用 @joystick.js/ui 編寫組件 庫,它是操縱桿框架的一部分。組件是返回在用戶瀏覽器中呈現的 HTML 字符串的函數,每當動態數據 inside 時更新 組件發生變化。

首先,我們在這裡做了兩件大事:就在 ui 的導入下方 @joystick.js/ui 中的對象 包中,我們定義了一個對像數組,每個對象代表我們列表中的一張專輯。我們在這裡創建了這個,因為我們需要能夠引用我們列表的未修改副本(這會更有意義)。

state 我們傳遞給 ui.component() 的選項對象的屬性 定義,我們正在設置一個屬性 filteredAlbumsalbums 大批。這是設置默認 filteredAlbums 的值 國家財產。狀態是我們組件內部的臨時數據,僅在頁面刷新之前存在。

向下移動到 render 函數,我們是 return 生成一個呈現 <ul></ul> 的 HTML 字符串 (無序列表)標籤,它將顯示我們的專輯列表。列出這些項目——對傳遞給 render 的第一個參數使用 JavaScript 解構 函數——我們去掉 eachstate 來自我們組件實例的屬性(這個實例是傳遞給 render 的第一個參數 函數)。

<ul></ul> 的 HTML 內部 標記,我們使用 JavaScript 插值來表示“在字符串中的這一點,注入這個值”。我們要注入的值是調用each()的結果 我們剛剛從組件實例中提取的函數(它本身返回一個 HTML 字符串)。

到那個each 函數,我們傳遞一個項目數組,在本例中是我們的 filteredAlbums state 中的值 以及將為數組中的每個項目調用的函數。該函數應為數組中的每個值返回一個 HTML 字符串。這裡,數組中的每一項都是一個 album 我們想返回一個 <li></li> 每個專輯的(列表項)標籤。

在該函數內部,我們返回一個與主 return 相同的字符串 對於我們的 render 函數,傳遞我們的 <li></li> 用我們專輯的部分填充的標籤——使用相同的 JavaScript 插值標籤 ${} 我們剛剛學習了將值注入字符串。此代碼運行的最終結果將如下所示:

<ul>
  <li>Queens of the Stone Age - Songs for the Deaf (2002) <span>#rock</span></li>
  <li>David Bazan - Havasu (2022) <span>#rock</span></li>
  <li>Dwight Yoakam - This Time (1993) <span>#country</span></li>
  ...
</ul>

現在我們有了列表渲染,接下來,我們要開始連接我們的過濾器。要做到這一點,首先,我們需要有一種機制,通過它我們可以真正過濾 我們的清單。

連接一個數組來過濾

就像我們之前暗示的那樣,我們的目標是按 genre 過濾我們的專輯數組 .為了開始這個過程,現在,我們將添加一個自定義方法函數,該函數從我們的每個專輯中檢索流派並將其填充到 <select></select> 用於過濾列表的標籤。

/ui/pages/index/index.js

import ui from '@joystick.js/ui';

const albums = [
  { id: 1, artist: 'Queens of the Stone Age', title: 'Songs for the Deaf', year: 2002, genre: 'rock' },
  { id: 2, artist: 'David Bazan', title: 'Havasu', year: 2022, genre: 'rock' },
  { id: 3, artist: 'Dwight Yoakam', title: 'This Time', year: 1993, genre: 'country' },
  { id: 4, artist: 'Sion', title: 'Sion', year: 2021, genre: 'metal' },
  { id: 5, artist: 'Every Time I Die', title: 'Low Teens', year: 2016, genre: 'metal' },
  { id: 6, artist: 'Cannonball Adderley', title: 'Somethin\' Else', year: 1958, genre: 'jazz' },
  { id: 7, artist: 'The Bad Plus', title: 'Suspicious Activity?', year: 2005, genre: 'jazz' },
  { id: 8, artist: 'Cory Hale', title: 'Soft', year: 2020, genre: 'electronic' },
  { id: 9, artist: 'Rezz', title: 'Spiral', year: 2021, genre: 'electronic' },
  { id: 10, artist: 'Autolux', title: 'Future Perfect', year: 2004, genre: 'experimental' },
];

const Index = ui.component({
  state: {
    filteredAlbums: albums,
  },
  methods: {
    getAlbumGenres: () => {
      const genres = albums.map(({ genre }) => {
        const capitalizedGenre = genre.charAt(0).toUpperCase() + genre.slice(1);
        return capitalizedGenre;
      });

      return Array.from(new Set(genres));
    },
  },
  render: ({ each, state, methods }) => {
    return `
      <div>
        <select>
          <option value="all">All</option>
          ${each(methods.getAlbumGenres(), (genre) => {
            return `
              <option value="${genre.toLowerCase()}">${genre}</option>
            `;
          })}
        </select>
        <ul>
          ${each(state.filteredAlbums, (album) => `
            <li>${album.artist} - ${album.title} (${album.year}) <span>#${album.genre.toLowerCase()}</span></li>
          `)}
        </ul>
      </div>
    `;
  },
});

export default Index;

專注於methods 我們添加到傳遞給 ui.component() 的選項的屬性 ,在這裡,我們添加了一個名為 getAlbumGenres 的方法(您可以在操縱桿組件上調用的其他函數) .

當我們調用它時,我們創建了一個名為 genres 的變量 設置為 JavaScript .map() 使用 JavaScript 解構來提取 genre albums 中每個對象的屬性 我們文件頂部的數組。在地圖內部,我們將流派的名稱大寫(在我們的 albums 數組,它是小寫的)用於在我們的 UI 中顯示。

一旦我們有了 capitalizedGenre ,我們從 .map() 返回 .這應該讓我們得到這樣的結果:

['Rock', 'Rock', 'Country', 'Metal', 'Metal', 'Jazz', 'Jazz', 'Electronic', 'Electronic', 'Experimental']

這讓我們在其中取得了部分進展,但有一個明顯的問題:我們有很多重複項。為了解決這個問題,我們將數組放入 genres 變量,來自我們的 getAlbumGenres() 我們使用 new Set() 的函數 類構造函數,傳入我們的 genres 多變的。這將為我們提供一個 JavaScript Set 作為回報,它是一個僅包含唯一值的對象,如下所示:

{ 'Rock', 'Country', 'Metal', 'Jazz', 'Electronic', 'Experimental' }

儘管它可能看起來不像傳統的 JavaScript 對象(一組鍵/值對),但 JavaScript 可以識別它(Set 只是 Object 的一種特殊類型,從語言中的主要 Object 原型擴展而來)。雖然這讓我們更近了一步,因為我們需要能夠遍歷這個列表,所以我們獲取調用 new Set(genres) 的結果 並將其直接傳遞給 Array.from() 以數組的形式取回我們的唯一列表:

['Rock', 'Country', 'Metal', 'Jazz', 'Electronic', 'Experimental']

回到 render 函數,我們可以看到我們在<select></select>中添加了 我們在上面暗示的標籤。在裡面,我們添加一個 <option></option> 值為 all 的標記 和“All”的文本內容(這將允許我們從過濾列表移回完整列表)。

在此之下,我們使用 each() 再次使用 JavaScript 插值函數來循環調用 methods.getAlbumGenres() 的結果 我們剛剛編寫的函數(注意我們添加了 methods 作為我們從傳遞給 render 的組件實例中提取的值之一 函數)。

對於每個 genre ,我們輸出一個 <option></option> 帶有 genre 小寫版本的標記 對於 value 屬性和大寫的 genre 為文本內容。

快完成了。現在,我們準備過濾我們的列表。為此,我們將在 <select></select> 上添加一個事件監聽器 我們剛剛添加到 render 的標籤 :

/ui/pages/index/index.js

import ui from '@joystick.js/ui';

const albums = [ ... ];

const Index = ui.component({
  state: {
    filteredAlbums: albums,
  },
  methods: { ... },
  events: {
    'change select': (event, component) => {
      const filterByGenre = event.target.value;
      component.setState({
        filteredAlbums: filterByGenre === 'all' ? albums : albums.filter((album) => {
          return album.genre === filterByGenre;
        })
      });
    },
  },
  render: ({ each, state, methods }) => {
    return `
      <div>
        <select>
          <option value="all">All</option>
          ${each(methods.getAlbumGenres(), (genre) => {
            return `
              <option value="${genre.toLowerCase()}">${genre}</option>
            `;
          })}
        </select>
        <ul>
          ${each(state.filteredAlbums, (album) => `
            <li>${album.artist} - ${album.title} (${album.year}) <span>#${album.genre.toLowerCase()}</span></li>
          `)}
        </ul>
      </div>
    `;
  },
});

export default Index;

重要部分的時間。在這裡,我們添加了一個 events ui.component() 的選項 在它上面,我們定義了一個事件監聽器,它說“當 change 在任何 select 上檢測到事件 組件中的元素,調用這里分配的函數。”

在該函數內部,對於第一個參數,我們接收 change 時創建的 DOM 事件對象 事件發生並且 component 實例作為第二個參數。

在我們執行過濾器之前,首先,我們確保抓住我們試圖過濾的類型——這將是 value <select></select> 的屬性 或 event.target 事件的來源——並將其存儲在 filterByGenre 變量。

接下來,我們調用 component.setState() 在組件的 state 上傳遞我們想要修改的屬性對象 ,在這種情況下,filteredAlbums .我們設置的filteredAlbums 取決於 filterByGenre 的值 .如果 filterByGenre 設置為 all 那麼我們 想要過濾我們的列表。在這裡,我們使用一個 JavaScript 三元運算符來表示,如果值為 'all' ,返回未修改的 albums 大批。否則,或者,否則 : 我們要調用 .filter() albums 上的方法 數組。

albums.filter() 我們傳遞一個為數組中的每個項目調用的函數。如果該函數返回的值是布爾 true ,該項目將保留在數組中。如果返回的值是布爾 false ,它將被過濾出數組。在這裡,得到那個 truefalse 值,我們檢查 .genre 我們當前循環匹配的專輯的屬性 filterByGenre .如果是這樣,它就是一個守門員。如果沒有,我們就扔掉它。

因為我們將調用傳遞給 albums.filter() 直接到 filteredAlbums 在我們傳遞給 component.setState() 的對像上 ,假設我們的用戶沒有選擇 all 選項,我們將更新 filteredAlbums on state 只包含一個對像數組,其中 genre 每個對象的屬性都與 <select></select> 中選擇的內容相匹配 流派列表。

在操縱桿組件中,更改為 state 觸發重新渲染,意味著我們的 render() 在我們調用 component.setState() 之後會立即再次調用該函數 , 傳入新的 state.filteredAlbums 價值。

而已!現在,如果我們在瀏覽器中查看,我們應該能夠按預期過濾我們的列表:

總結

在本教程中,我們學習瞭如何使用 JavaScript Array.Filter 方法過濾數組。為了將我們的工作與上下文聯繫起來,我們使用 @joystick.js/ui 創建了一個用戶界面 來自 Joystick 框架的庫來幫助我們呈現要過濾的專輯列表,以及我們可以用來按流派過濾該列表的選擇輸入。


Tutorial JavaScript 教程
  1. 我建立了副項目幫助你找到很酷的開源項目並加入他們

  2. 在 JavaScript 中結束

  3. 如果你有測試方面,你如何開始創建你的 js 代碼?

  4. React 中的低級圖表

  5. `new Object()` 和對象字面量表示法有什麼區別?

  6. 讓我們來看看 2019 年的 JS 中的 CSS 和 React - 樣式化的組件

  7. 從tiptap v.1 遷移到tiptap v.2

  1. 網絡抓取:使用 scrapy 和 Scraper API 管理代理和驗證碼

  2. Angular 入門:適合初學者的 12 大教程

  3. 如何使用 JavaScript 模擬點擊?

  4. Python datetime 模塊:處理日期和時間

  5. 嘗試...抓住...最終在 JavaScript 中

  6. TensorFlow.js 簡介:機器學習可在 JavaScript 中訪問。

  7. JavaScript - onClick 獲取被點擊按鈕的ID

  1. 編碼概念 - 吊裝

  2. 帶有 Kendo UI 原生組件的 Vue 中的動態表單

  3. 使用 StencilJS 創建 WebComponents 並在不同的項目中重用它們

  4. 🔑 使用 Next.js、Prisma 和 next-auth 進行無密碼身份驗證