如何在 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()
的選項對象的屬性 定義,我們正在設置一個屬性 filteredAlbums
到 albums
大批。這是設置默認 filteredAlbums
的值 國家財產。狀態是我們組件內部的臨時數據,僅在頁面刷新之前存在。
向下移動到 render
函數,我們是 return
生成一個呈現 <ul></ul>
的 HTML 字符串 (無序列表)標籤,它將顯示我們的專輯列表。列出這些項目——對傳遞給 render
的第一個參數使用 JavaScript 解構 函數——我們去掉 each
和 state
來自我們組件實例的屬性(這個實例是傳遞給 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
,它將被過濾出數組。在這裡,得到那個 true
或 false
值,我們檢查 .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 框架的庫來幫助我們呈現要過濾的專輯列表,以及我們可以用來按流派過濾該列表的選擇輸入。