JavaScript >> Javascript 文檔 >  >> Tags >> object

如何修改 JavaScript 數組中的現有對象

一種使用 JavaScript 修改數組中特定對象的模式。

開始使用

對於本教程,我們將使用 CheatCode Next.js Boilerplate 為我們的工作提供一個起點。首先,讓我們克隆一個副本:

終端

git clone https://github.com/cheatcode/nextjs-boilerplate.git

接下來,安裝樣板的依賴項:

終端

cd nextjs-boilerplate && npm install

最後,啟動開發服務器:

終端

npm run dev

有了這個,我們就可以開始了。

構建一個用於測試的 React 組件

為了將我們的工作上下文化,我們將構建一個簡單的、基於類的 React 組件。這將給我們一種情況,即使用我們將學習的模式會更有意義。

/pages/index.js

import React from "react";
import PropTypes from "prop-types";
import usersFixture from "../lib/users";

class Index extends React.Component {
  state = {};

  render() {
    return <div></div>;
  }
}

Index.propTypes = {};

export default Index;

在這裡,我們只是為 React 中的類組件創建腳手架。我們要注意的部分是name 組件 Index 以及該文件 /pages/index.js 的路徑 .因為我們使用的是 Next.js,所以在這裡,我們通過將組件文件放在框架的 /pages 中來依賴 Next.js 路由器 目錄。

此處的文件和文件夾會自動轉換為路由。因為我們已經把它放在了 root 我們的 /pages 文件夾為 index.js ,這將呈現在 root 我們的應用程序的 URL,或者,http://localhost:5000/ .

接下來我們快速看一下那個usersFixture 我們在上面導入的文件:

/lib/users.js

const users = [
  {
    _id: "f91bbFE72aaDDd8c",
    emailAddress: "[email protected]",
    name: { first: "Phoebe", last: "Schamberger" },
    address: {
      streetAddress: "39473 David Mill",
      city: "Stammbury",
      state: "Michigan",
      zipCode: "91802",
    },
  },
  {
    _id: "E8c8f6d3fE6761dd",
    emailAddress: "[email protected]",
    name: { first: "Orin", last: "Balistreri" },
    address: {
      streetAddress: "27846 Collier Roads",
      city: "Schneiderton",
      state: "Kansas",
      zipCode: "49705-7399",
    },
  },
  {
    _id: "Cd9caEcb4fB1D558",
    emailAddress: "[email protected]",
    name: { first: "Chanelle", last: "Oberbrunner" },
    address: {
      streetAddress: "638 Fadel Cliffs",
      city: "Lake Thorahaven",
      state: "West Virginia",
      zipCode: "12349-0480",
    },
  },
  {
    _id: "BAf1DcEec4b4DBAc",
    emailAddress: "[email protected]",
    name: { first: "Briana", last: "White" },
    address: {
      streetAddress: "0540 Brown Meadow",
      city: "Port Jerad",
      state: "Oklahoma",
      zipCode: "14368",
    },
  },
  {
    _id: "1c4E8Aa24c37cBFA",
    emailAddress: "[email protected]",
    name: { first: "Vidal", last: "Stokes" },
    address: {
      streetAddress: "31028 Marquardt Forest",
      city: "North Bethany",
      state: "Indiana",
      zipCode: "32632",
    },
  },
];

export default users;

在這裡,我們有一個靜態的“用戶”列表(這些是由虛假數據組成的)。我們的目標是將這個用戶數組加載到我們的組件中,然後通過 JavaScript 對數組中的對象進行更改。

/pages/index.js

import React from "react";
import PropTypes from "prop-types";
import usersFixture from "../lib/users";

class Index extends React.Component {
  state = {
    users: usersFixture,
  };

  render() {
    const { users } = this.state;

    return (
      <div>
        <header className="page-header">
          <h4>Test</h4>
        </header>
        <div className="responsive-table">
          <table className="table align-middle">
            <thead>
              <tr>
                <th>Name</th>
                <th>Email Address</th>
                <th>Address</th>
                <th />
              </tr>
            </thead>
            <tbody>
              {users.map(({ _id, name, emailAddress, address }) => {
                return (
                  <tr key={_id}>
                    <td>
                      {name?.first} {name?.last}
                    </td>
                    <td>{emailAddress}</td>
                    <td>
                      {address?.streetAddress} {address?.city}, {address?.state}{" "}
                      {address?.zipCode}
                    </td>
                    <td>
                      <button
                        disabled={editingUser}
                        className="btn btn-primary"
                        onClick={() => {
                          this.setState({ editingUser: _id });
                        }}
                      >
                        Edit
                      </button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

Index.propTypes = {};

export default Index;

回到我們的組件,現在,我們採用了 usersFixture 我們之前導入並在我們組件的 state 上進行設置 值為 users .在render()中 函數,我們返回了一些 HTML 以在表格中呈現我們的用戶列表。在這裡,您看到的 CSS 類名稱取自 Bootstrap CSS 框架。這裡使用這些類不會影響我們的實際工作——它們只是用於演示。

我們關心的部分是當我們 .map()users 我們放置在狀態上的值(同樣,這是我們的用戶對象的靜態數組)。在我們的 render() 內部 方法,我們使用 JavaScript 解構來“拔掉”users 來自 this.state 然後在返回的 HTML 標記中(從技術上講,JSX 是一種特定於 React 的語言,看起來像 HTML) 我們渲染一個 <table></table> 使用我們的 users 列在正文中。

對於“列表”,我們保持簡單。在這裡,我們渲染出一個 <tr></tr> 每個用戶的表格行,顯示他們的 name , emailAddress , 和物理 address .同樣,這些值只是測試數據,以幫助我們將修改數組中對象的工作上下文化。

最後,我們為每個用戶添加了一個 <button></button> 單擊時會將用戶設置為 editingUser 關於狀態。在這裡,我們傳遞用戶的_id (他們在我們的“數據庫”中的唯一 ID)說“我們目前正在使用這個 _id 編輯用戶 .

接下來,讓我們連接編輯過程。

編輯數組中的用戶對象

有了我們的基礎組件集,現在讓我們添加上面提到的編輯功能:

/pages/index.js

import React from "react";
import PropTypes from "prop-types";
import usersFixture from "../lib/users";

class Index extends React.Component {
  state = {
    editingUser: null,
    users: usersFixture,
  };

  renderUserEditor = () => {
    const { editingUser, users } = this.state;
    const user = users.find(({ _id }) => _id === editingUser);

    return (
      <div
        className="edit-user"
        style={{
          border: "1px solid #ddd",
          padding: "20px",
          borderRadius: "3px",
          marginTop: "40px",
          marginBottom: "40px",
        }}
      >
        <form onSubmit={this.handleUpdateUser}>
          <div className="row">
            <div className="col-xs-12 col-sm-3">
              <div className="mb-3">
                <label className="form-label">First Name</label>
                <input
                  type="text"
                  className="form-control"
                  defaultValue={user?.name?.first}
                  name="firstName"
                />
              </div>
            </div>
            <div className="col-xs-12 col-sm-3">
              <div className="mb-3">
                <label className="form-label">Last Name</label>
                <input
                  type="text"
                  className="form-control"
                  defaultValue={user?.name?.last}
                  name="lastName"
                />
              </div>
            </div>
            <div className="col-xs-12 col-sm-6">
              <div className="mb-3">
                <label className="form-label">Email Address</label>
                <input
                  type="text"
                  className="form-control"
                  defaultValue={user?.emailAddress}
                  name="emailAddress"
                />
              </div>
            </div>
          </div>
          <div className="row">
            <div className="col-xs-12 col-sm-5">
              <label className="form-label">Street Address</label>
              <input
                disabled
                type="text"
                className="form-control"
                defaultValue={user?.address?.streetAddress}
                name="streetAddress"
              />
            </div>
            <div className="col-xs-12 col-sm-3">
              <label className="form-label">City</label>
              <input
                disabled
                type="text"
                className="form-control"
                defaultValue={user?.address?.city}
                name="city"
              />
            </div>
            <div className="col-xs-12 col-sm-2">
              <label className="form-label">State</label>
              <input
                disabled
                type="text"
                className="form-control"
                defaultValue={user?.address?.state}
                name="state"
              />
            </div>
            <div className="col-xs-12 col-sm-2">
              <label className="form-label">Zip Code</label>
              <input
                disabled
                type="text"
                className="form-control"
                defaultValue={user?.address?.zipCode}
                name="zipCode"
              />
            </div>
          </div>
          <footer className="mt-4">
            <button type="submit" className="btn btn-success">
              Save
            </button>
            <button
              type="button"
              className="btn btn-default"
              onClick={() => this.setState({ editingUser: null })}
            >
              Cancel
            </button>
          </footer>
        </form>
      </div>
    );
  };

  render() {
    const { editingUser, users } = this.state;

    return (
      <div>
        <header className="page-header">
          <h4>Test</h4>
        </header>
        {editingUser && this.renderUserEditor()}
        <div className="responsive-table">
          <table className="table align-middle">
            <thead>
              <tr>
                <th>Name</th>
                <th>Email Address</th>
                <th>Address</th>
                <th />
              </tr>
            </thead>
            <tbody>
              {users.map(({ _id, name, emailAddress, address }) => { ... })
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

Index.propTypes = {};

export default Index;

更進一步,現在我們添加了 editingUser 並將其設置為 null 在我們的默認 state 組件類頂部的對象。接下來,在我們的 render() 函數,我們添加了對 this.renderUserEditor() 的調用 並在功能中添加。這裡的想法是,當我們點擊用戶的“編輯”按鈕時,我們將設置他們的 _id on state(取自 users 中的用戶對象 數組),然後同時切換用戶編輯器的呈現 禁用用戶的所有編輯按鈕,直到用戶編輯器關閉(通過保存更改或取消更改)。

假設我們有一個 editingUser 設置和 renderUserEditor() 已經被調用了,看那個函數,我們關心的部分是最上面的:

const { editingUser, users } = this.state;
const user = users.find(({ _id }) => _id === editingUser);

請記住:我們正在處理 static 狀態用戶數組。在這裡,我們不是從服務器獲取數據,而是說“從 editingUserusers 從狀態數組,然後使用 JavaScript .find()users 數組來查找擁有 _id 的用戶 匹配 editingUser 我們設置狀態。”所以,當我們點擊用戶的“編輯”按鈕時,他們將變成 user 我們在這裡檢索。

一旦在 renderUserEditor() 內部檢索到 ,我們呈現一個表單,該表單將負責允許我們進行更改to 那個用戶。在這裡,我們可以看到我們的表單 - 再次使用 Bootstrap CSS 來清理我們的演示文稿 - 列出了用戶對像中可用的每個字段作為輸入及其 defaultValueuser 上設置為該字段的值 目的。為簡單起見,我們只允許對 name.first 進行編輯 , name.last , 和 emailAddress 為用戶;其他字段被禁用。

還有兩件事。一、在renderUserEditor()的底部 ,我們返回一個 <footer></footer> 有兩個按鈕,一個“保存”按鈕和一個“取消”按鈕。這裡的“取消”按鈕負責清除editingUser 單擊時處於打開狀態(請記住,這會切換用戶編輯器的呈現以及我們列表中用戶的編輯按鈕的禁用狀態)。更重要的按鈕“保存”設置為 type="submit" , 這意味著當點擊它會觸發 onSubmit <form></form> 的事件 這就是包裝它。

在這裡,我們可以看到 <form></form> 有一個 onSubmit 設置為函數 this.handleUpdateUser .現在讓我們連接這個函數,看看它是如何修改我們的數組的。

/pages/index.js

import React from "react";
import PropTypes from "prop-types";
import usersFixture from "../lib/users";

class Index extends React.Component {
  state = {
    editingUser: null,
    users: usersFixture,
  };

  handleUpdateUser = (event) => {
    event.preventDefault();

    const { editingUser, users } = this.state;
    const updatedUsers = [...users];
    let userToUpdate = updatedUsers.find(({ _id }) => _id === editingUser);

    if (userToUpdate) {
      userToUpdate.name = {
        first: event.target.firstName.value,
        last: event.target.lastName.value,
      };

      userToUpdate.emailAddress = event.target.emailAddress.value;
    }

    this.setState({ users: updatedUsers, editingUser: null });
  };

  renderUserEditor = () => {
    const { editingUser, users } = this.state;
    const user = users.find(({ _id }) => _id === editingUser);

    return (
      <div
        className="edit-user"
        style={{
          border: "1px solid #ddd",
          padding: "20px",
          borderRadius: "3px",
          marginTop: "40px",
          marginBottom: "40px",
        }}
      >
        <form onSubmit={this.handleUpdateUser}>
          ...
        </form>
      </div>
    );
  };

  render() {
    const { editingUser, users } = this.state;

    return (
      <div>
        <header className="page-header">
          <h4>Test</h4>
        </header>
        {editingUser && this.renderUserEditor()}
        <div className="responsive-table">
          <table className="table align-middle">
            <thead>
              <tr>
                <th>Name</th>
                <th>Email Address</th>
                <th>Address</th>
                <th />
              </tr>
            </thead>
            <tbody>
              {users.map(({ _id, name, emailAddress, address }) => { ... })}
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

Index.propTypes = {};

export default Index;

在我們新的 handleUpdateUser() 內部 函數,首先,我們傳入提交event 作為參數並立即調用它的 .preventDefault() 方法。這很重要,因為我們不希望提交事件觸發瀏覽器刷新——這會阻止它。

接下來,我們看到類似於我們在 renderUserEditor() 中看到的內容 .這是我們在本教程中關心的部分。在這裡,我們正在刪除 editingUserusers this.state 的數組 再次。請記住,我們的目標是編輯存在於數組中的對象。為了做到這一點,我們需要知道兩件事:

  1. 我們正在查看什麼數組?
  2. 我們如何在該數組中找到要更新的對象?

在這裡,我們將使用 _id 我們設置在 editingUser 當我們單擊一位用戶旁邊的“編輯”按鈕時。現在,我們需要再次強調,我們的目標是編輯一個對象因為它存在於一個數組中 .在這個例子中,數組是我們的 users 數組。

首先,在我們“找到”我們的用戶之前,我們創建一個 users 的副本 狀態數組(它超出了本教程的範圍,但 React 中的黃金法則是你不想直接改變狀態值)與 [...users] .在這裡,我們在一行中說“創建一個新數組 [] 然後使用 ... 展開運算符“解包”或複制 users 的內容 到那個新數組中。” 這個 是我們要修改的數組。

接下來,再次使用 JavaScript .find() 在我們的新 updatedUsers 數組,我們運行我們之前使用的相同測試,說“為我們找到一個具有 _id 的用戶 匹配 editingUser ." 假設我們 找到那個用戶,我們開始對他們進行更改。在這裡,我們設置 name 對象和 emailAddress userToUpdate 上的字段 .

雖然它可能看起來不像,因為我們使用了 JavaScript .find() 在這裡,我們實際上是在修改匹配的 userToUpdate updatedUsers 中存在的對象 內存中的數組。這意味著即使我們的代碼正在對 userToUpdate 進行更改 ,最終,它正在對 updatedUsers 進行更改 .

一旦這些更改完成(在這裡,我們只是使用 event.target.<fieldName>.value 將上述值設置為我們表單中的相應輸入 <fieldName>name="" 屬性),我們覆蓋我們的 users this.setState() 的狀態值 ,傳遞我們的 updatedUsers 數組。

最終結果?我們將看到我們的 users 在我們的表中更新列表,成功證明我們更新了數組中的一個對象。

總結

在本教程中,我們學習瞭如何修改 JavaScript 數組中的對象。為了使我們的工作上下文化,我們構建了一個 React 組件,它在狀態數組中修改用戶列表,然後將其設置回狀態,在 HTML 表格中呈現更新後的列表。


Tutorial JavaScript 教程
  1. 什麼是大 O 表示法?

  2. TypeScript + React:使用元組類型鍵入自定義鉤子

  3. 多個三元運算符

  4. 如何將二維碼和條形碼掃描儀添加到您的 Vue.js 應用程序

  5. React.js TypeError:無法讀取 null 的屬性“地圖”

  6. PBT 2021 的到來 - 第 18 天 - 解決方案

  7. 保存到localStorage的單一功能?

  1. Vue 3 — 關於 v-model 的更多信息

  2. 兩個promise,其中一個只有一個then

  3. 有條件地將屬性插入對象文字的最短方法

  4. 如何擺脫 Angular 編譯中的裝飾器不支持函數調用?

  5. 使用 JavaScript 或 CSS 檢測比例設置 (dpi)

  6. Flutter Web 和機器學習

  7. Angular – 在每次 forEach 迭代後插入值

  1. 如何編寫自定義 *ngIf 指令以僅顯示授權視圖

  2. 貝索斯計算器

  3. 使用 NodeJS 開發您的第一個 CLI(命令行界面)工具

  4. 安靜的革命:JSON 如何取代 XML