JavaScript >> Javascript 文檔 >  >> JavaScript

在操縱桿中創建加載器按鈕

如何基於props創建一個動態加載狀態的按鈕組件。

開始使用

在本教程中,我們將使用 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

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

添加圖標

在深入研究加載器按鈕之前,我們希望添加對 Font Awesome 圖標庫的支持。由此,我們將使用一個“微調器”圖標,當我們的按鈕處於加載狀態時我們可以顯示該圖標。

如果您沒有 Font Awesome 帳戶,請前往該網站並設置一個帳戶(它們不是垃圾郵件類型,因此不用擔心被轟炸)。登錄後,您應該被重定向到顯示“Kit Code”的屏幕,這是我們需要添加到我們的應用程序的腳本標籤。

如果你 已經有一個 Font Awesome 帳戶,只需前往 Kits 頁面,您將在頁面右上角看到一個藍色的“New Kit +”按鈕。單擊此按鈕可生成類似於您在上面看到的腳本標記。

一旦您可以訪問您的套件代碼,複製它,然後打開我們剛剛在您的 IDE 中創建的操縱桿項目。從那裡,我們要打開 /index.html 項目根目錄下的文件。

/index.html

<!doctype html>
<html class="no-js" lang="en">
  <head>
    <meta charset="utf-8">
    <title>Joystick</title>
    <meta name="description" content="An awesome JavaScript app that's under development.">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#FFCC00">
    <link rel="apple-touch-icon" href="/apple-touch-icon-152x152.png">
    <link rel="stylesheet" href="/_joystick/index.css">
    <link rel="manifest" href="/manifest.json">
    <script src="https://kit.fontawesome.com/8c0c20c9e4.js" crossorigin="anonymous"></script>
    ${css}
  </head>
  <body>
    <div id="app"></div>
    ${scripts}
    <script>
      if ("serviceWorker" in navigator) {
        navigator.serviceWorker.register("/service-worker.js");
      }
    </script>
  </body>
</html>

在該文件中,就在 ${css} 上方 標籤,我們要粘貼在 <script></script> 我們剛剛從 Font Awesome 複製的標籤。完成後,保存文件,現在 Font Awesome 將在整個應用程序中全局加載。

實現加載器按鈕

本教程的其餘工作將集中在構建一個具有內部加載狀態的可重用按鈕組件。我們的目標是:

  1. 有一個具有兩種狀態的按鈕:加載和未加載。
  2. 一種調用函數的方法,該函數將完成與我們的按鈕相關的一些工作。
  3. 我們可以調用的回調告訴按鈕我們的工作已經完成。

首先,讓我們在 /ui/components/loaderButton/index.js 中創建一個新的骨架組件 :

/ui/components/loaderButton/index.js

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

const LoaderButton = ui.component({
  render: () => {
    return `
      <button>
      </button>
    `;
  },
});

export default LoaderButton;

在這裡,我們使用 @joystick.js/ui 創建一個操縱桿組件 具有單個選項 render 的庫 它返回一個 <button></button> 標記它的標記。

/ui/components/loaderButton/index.js

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

const LoaderButton = ui.component({
  defaultProps: {
    label: 'Button',
    loadingLabel: 'Loading...',
  },
  state: {
    loading: false,
  },
  render: () => {
    return `
      <button>
      </button>
    `;
  },
});

export default LoaderButton;

接下來,我們要添加兩個小細節:一個 defaultProps 選項和 state 選項。對於 defaultProps ,我們預計會出現 label prop 被傳遞給我們的組件。在這裡,我們說“如果沒有 labelloadingLabel prop 已通過,將它們替換為此處提供的默認值。” 同樣,對於 state ,我們設置默認值 loading 在組件內的狀態。正如我們接下來將看到的,當我們更新下面的標記以更改基於我們的 state 呈現的內容時,這將發揮作用 和 props .

/ui/components/loaderButton/index.js

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

const LoaderButton = ui.component({
  defaultProps: {
    label: 'Button',
    loadingLabel: 'Loading...',
  },
  state: {
    loading: false,
  },
  render: ({ state, when, props }) => {
    return `
      <button ${state.loading ? 'disabled' : ''} class="button ${state.loading ? 'is-loading' : ''}">
        ${when(state.loading, `<i class="fas fa-circle-notch fa-spin"></i>`)} ${state.loading ? props.loadingLabel : props.label}
      </button>
    `;
  },
});

export default LoaderButton;

現在是重要的部分。在這裡,我們擴展了 render() 返回的標記 函數包含必要的條件邏輯來改變我們的按鈕相對於 props 的狀態 和 state .

因為 render() 函數返回一個 HTML 字符串,在這裡,我們利用 JavaScript 字符串插值(一種評估變量並在字符串中返回其結果的方法)來動態構建表示按鈕當前狀態的 HTML。

從開頭 <button 標籤,我們看到的第一條語句是${state.loading ? 'disabled' : ''} .這就是說“如果 state.loading 的當前值 是 true , 返回一個帶有 disabled 的字符串 在其中,否則,返回一個空字符串。” 訪問 state ,我們從傳遞給我們的 render() 的組件實例中提取它 功能。在這裡,我們使用 JavaScript 解構來“分離”該值,將其上定義的屬性作為變量直接暴露在我們的渲染函數內部。

什麼而言 我們在這裡做,如果我們的按鈕處於加載狀態,我們希望禁用它以防止在我們分配給該按鈕的工作完成時額外點擊。在這裡,我們動態添加 disabled 屬性到我們的 <button></button> 基於 state.loading 值的標記 .因此,如果我們正在加載,請禁用該按鈕,如果沒有,請使其處於活動/可點擊狀態。

在此右側,使用與 ${state.loading ? 'is-loading' : ''} 相同的概念 ,說“如果 state.loading 是的,我們想動態添加一個 CSS 類到我們的 <button></button> 稱為is-loading ." 這將允許我們稍後根據按鈕的加載狀態添加一些 CSS 樣式。

在下一行(現在在我們的 <button></button> 標記),我們使用一個特殊的函數(在操縱桿中稱為“渲染函數”),稱為 when() 有條件地渲染加載圖標(我們從 Font Awesome 中選擇了 Circle Notch 圖標,其中包括一個內置的動畫類 fa-spin ) 如果 state.loading 的值是我們的按鈕 是 true .第一個參數傳遞給 when() 是我們想要“測試”真實性的值,第二個值是一個 HTML 字符串,如果第一個值為真,則要呈現。

最後,我們使用與第一個相同的插值語法為我們的 <button></button> 有條件地渲染標籤 ,就在我們圖標的右側。在這裡,我們說如果 state.loadingtrue ,我們要渲染 loadingLabel 來自 props 的值,否則,我們只想渲染常規的 label 道具。

/ui/components/loaderButton/index.js

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

const LoaderButton = ui.component({
  defaultProps: {
    label: 'Button',
    loadingLabel: 'Loading...',
  },
  state: {
    loading: false,
  },
  css: `
    .button {
      padding: 20px;
      border: none;
      background: #333;
      color: #fff;
      border-radius: 3px;
      font-size: 15px;
      cursor: pointer;
    }

    .button:active {
      position: relative;
      top: 1px;
    }

    .button i {
      margin-right: 5px;
    }

    .button.is-loading,
    .button:disabled {
      opacity: 0.9;
      pointer-events: none;
    }
  `,
  render: ({ state, when, props }) => {
    return `
      <button ${state.loading ? 'disabled' : ''} class="button ${state.loading ? 'is-loading' : ''}">
        ${when(state.loading, `<i class="fas fa-circle-notch fa-spin"></i>`)} ${state.loading ? props.loadingLabel : props.label}
      </button>
    `;
  },
});

export default LoaderButton;

進入最後的細節。在這裡,我們為按鈕添加了必要的 CSS 樣式。在這裡,我們為一個簡單的黑色按鈕定義了樣式,該按鈕在單擊時會“彈回”(模擬物理按鈕的深度),並且在加載或禁用時其不透明度更改為 90%,沒有懸停/單擊交互狀態。

/ui/components/loaderButton/index.js

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

const LoaderButton = ui.component({
  defaultProps: {
    label: 'Button',
    loadingLabel: 'Loading...',
  },
  state: {
    loading: false,
  },
  css: `...`,
  events: {
    'click button': (event, component) => {
      if (component.props.onClick) {
        component.setState({ loading: true }, () => {
          component.props.onClick(event, () => {
            component.setState({ loading: false });
          });
        });
      }
    }
  },
  render: ({ state, when, props }) => {
    return `
      <button ${state.loading ? 'disabled' : ''} class="button ${state.loading ? 'is-loading' : ''}">
        ${when(state.loading, `<i class="fas fa-circle-notch fa-spin"></i>`)} ${state.loading ? props.loadingLabel : props.label}
      </button>
    `;
  },
});

export default LoaderButton;

現在是重要的部分。我們組件的最後一點工作:處理點擊事件。在這裡,我們添加了 events 我們組件的選項,它幫助我們定義 JavaScript 事件監聽器。在傳遞給 events 的對像上 ,我們通過首先以 <event> <selector> 的形式指定屬性名稱來定義事件監聽器 <event> 的模式 是類型 我們要監聽的 DOM 事件和 <selector> 是我們要監聽事件 on 的元素 .

我們將在指定選擇器上檢測到指定事件時調用的函數分配給該屬性。對於該函數,我們接收兩個參數:原始 DOM event 那發生了,我們的 component 實例。

在這裡的函數內部,我們首先檢查我們是否被傳遞了一個 onClick 函數通過 props .這個很重要。這是我們要調用的函數來完成將確定按鈕加載狀態的工作(例如,上傳文件、保存更改等)。如果該函數存在,首先,我們確保設置 state.loadingtrue 使用 .setState() 組件實例上的方法(我們向該函數傳遞一個對象,其中包含我們想要更新的狀態屬性以及它們的新值)。

作為第二個參數,我們傳遞一個回調來觸發 after state.loading 設置為 true .在裡面 我們調用 onClick 通過 props 傳遞的函數,將觸發的 DOM 事件傳遞給它,並作為第二個參數,在任何工作“完成”後調用的函數。

在該函數內部,請注意​​我們還原了 state.loading 返回 false .這個想法是,一旦工作被指示為“完成”,我們不想再將按鈕顯示在加載狀態(即,我們想讓它可點擊)。

現在來看看有趣的部分,讓我們使用我們的組件並使用它。

使用加載器按鈕

為了測試我們的加載器按鈕,我們將修改位於 /ui/pages/index/index.js 的組件 因為它已經連接到我們應用的根路由了。

/ui/pages/index/index.js

import ui from '@joystick.js/ui';
import LoaderButton from '../../components/loaderButton';

const Index = ui.component({
  render: ({ component }) => {
    return `
      <div>
        ${component(LoaderButton, {
          label: 'Start Machine',
          loadingLabel: 'Starting machine...',
          onClick: (_event, callback) => {
            setTimeout(() => {
              if (callback) callback();
            }, 3000);
          },
        })}
      </div>
    `;
  },
});

export default Index;

在這裡,我們完全覆蓋了這個文件的現有內容。在頂部,我們已經導入了 LoaderButton 零件。在render()Index 的函數 組件,我們已經“拔掉”了 component() render 函數來幫助我們渲染我們的 LoaderButton Index 上的組件 頁面。

對於該函數,我們傳遞 LoaderButton 組件,因為我們在文件頂部導入它。作為第二個參數,我們傳遞一個 props 的對象 我們想要傳遞給我們的組件。如果我們看這裡,我們可以看到我們期望的三個道具:label , loadingLabel , 和 onClick .

對於 onClick ,我們接受了我們期望的 DOM 事件(這裡,我們在參數名稱前加上 _ 下劃線表示我們不會在代碼中使用該變量。在此之後,我們接受我們的“完成”回調。在這裡,為了模擬做一些工作,我們添加了一個 setTimeout() 3 秒(3000 是 3 秒(以毫秒為單位),在裡面,如果我們傳遞了一個 callback ,我們稱之為。

就那麼簡單!現在,如果我們加載 http://localhost:2600 在我們的瀏覽器中,我們應該會看到我們的按鈕,如果我們點擊它,我們應該會看到它轉換到加載狀態。

總結

在本教程中,我們學習瞭如何使用操縱桿創建加載按鈕。我們學習瞭如何使用來自 Font Awesome 的 CDN 鏈接添加圖標,然後,如何連接一個自定義組件,該組件可以在用於更改標籤、加載文本和單擊按鈕時接收道具時接收道具。最後,我們學習瞭如何使用按鈕,使用 setTimeout() 演示一些長時間運行的工作,並在加載完成後將我們的按鈕切換回默認狀態。


Tutorial JavaScript 教程
  1. React v18:useTransition 鉤子——為什麼???

  2. 帶有 React 的 GraphQL - Apollo 與 Relay 概述

  3. ReferenceError – d3 未定義

  4. 使用 flask-praetorian 為 ReactJS 前端構建 JWT 登錄和註冊後端

  5. React Hooks 重溫:useCallback

  6. 根據月份過濾對象列表?

  7. SolidJS - React 的替代品?

  1. 如何使用 Redux Toolkit 在 React 中實現狀態(簡單方法🔥)

  2. 舊的var

  3. Number parseInt() 方法

  4. 用示例反應 Hooks(useState、useEffect、useContext)。

  5. 我可以使用內容腳本 js 文件以編程方式註入 CSS 文件嗎?

  6. 使用 GOOGLE BOOK API 構建圖書查找器應用程序

  7. 如何在 JavaScript 中匹配整個單詞?

  1. 全棧 Twitter 克隆

  2. 使用 React Native 的聊天應用程序(第 4 部分):使用 react-native-gifted-chat 創建聊天 UI 屏幕的指南

  3. 6 個 jQuery 表單嚮導插件

  4. JavaScript 在 | 之後插入附加元素示例