JavaScript >> Javascript 文檔 >  >> JavaScript

如何在操縱桿組件中獲取和渲染數據

在 Joystick 組件中添加 data 選項,在服務端獲取數據,並在服務端和客戶端的組件中渲染。

開始使用

在本教程中,我們將使用 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 .在你運行它之前,我們需要安裝一個額外的依賴,node-fetch

終端

cd app && npm i node-fetch

安裝後,從相同的 app 你只是cd的目錄 'd進入,你可以啟動應用程序:

終端

joystick start

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

使用 getter 連接 API 端點

我們需要做的第一件事是訪問我們將在組件中呈現的一些數據。雖然我們可以 只是渲染一些靜態(或硬編碼)數據,最好從第三方 API 中提取一些數據,這樣我們才能看到這種技術的強大和靈活性。

/api/index.js

import fetch from 'node-fetch';
import { URL, URLSearchParams } from 'url';

export default {
  getters: {
    posts: {
      get: (input = {}) => {
        const url = new URL('https://jsonplaceholder.typicode.com/posts');

        if (input?.id) {
          const searchParams = new URLSearchParams(input);
          url.search = searchParams.toString();
        }

        return fetch(url).then((response) => response.json());
      },
    },
  },
  setters: {},
};

在操縱桿應用程序中,“getter”允許我們為“獲取”數據定義 API 端點。在幕後,getter 被轉換為應用程序中的普通 HTTP REST API 端點(例如,http://localhost:2600/api/_getters/posts )。

上面,我們定義了一個名為 posts 的新 getter 它將從 JSON Placeholder API(一個免費的 REST API,為測試和原型設計提供測試數據)獲取帖子列表。

Getter 是 Joystick 應用程序中的兩種 API 端點之一,另一種是 setter(我們的應用程序中的這些“設置”數據——CRUD 的“創建、更新和刪除”部分)。在 Joystick 應用程序中,getter 和 setter 一起定義在從 /api/index.js 導出的單個對像上 我們在上面看到的文件(在操縱桿中稱為您的 API 的“模式”)。

然後將該對象導入到 /index.server.js 並作為選項的一部分傳遞給 node.app() 函數——作為 api ——來自 @joystick.js/node 包裹。這告訴 Joystick 在啟動應用程序的服務器端時自動加載我們在上面看到的文件中定義的所有 getter 和 setter。

在本教程中,我們定義了一個 getter posts 它從 JSON 佔位符 API 返回數據。為了讓它工作,我們添加了一個新屬性 posts 分配給 getters 的對象 它本身被分配了一個對象。

該對象包含一個屬性 get 它被分配給一個函數,該函數負責“獲取”我們的數據並將其返回給調用 getter 的 HTTP 請求。在該函數內部,我們首先通過 new URL() 創建一個 URL 對象的實例 構造函數(注意我們已經從 url 包——這是 Node.js 內置的,我們 需要單獨安裝)。

我們將要為其創建對象的 URL 傳遞給該構造函數。在這種情況下,我們要使用 /posts 來自位於 https://jsonplaceholder.typicode.com/posts 的 JSON 佔位符 API 的端點 .

接下來,我們檢查一下我們的 getter 是否通過了任何 input 調用時的變量(其工作原理稍後會更有意義,但可以將其視為作為 POST 傳遞 正文到 HTTP 請求)。如果我們有一個 id 在我們的輸入中定義的值(JSON 佔位符 API 上的帖子 ID,例如 15 ),我們要創建 URLSearchParams 的新實例 類,傳入我們的輸入對象。在這裡,對像上的每個屬性都會變成一個查詢參數。例如,input 價值……

{ id: 5 }

會變成……

?id=5

為了使該值有用,我們設置了 .search url 的屬性 我們在上面創建的對像到 searchParams 的值 轉換為字符串值(使用 .toString() 函數)。

最後,使用我們完整的 url 對象,我們調用 fetch() 我們從 node-fetch 導入的函數 打包頂部,傳遞 url 對象(fetch 理解如何解釋這個對象)。因為我們期望 fetch() 最後,我們調用 .then() 返回一個 JavaScript Promise 說“在我們收到回復後然後 這樣做。”

我們正在做的“這個”是採用 response 對象並使用 .json() 將其轉換為 JSON 格式 方法。我們期望從這個方法鏈返回的是一個對像數組,這些對象表示來自 JSON 佔位符 API 的帖子。

有了這個,現在我們準備好連接我們的數據了。為此,我們需要一個可以渲染我們要創建的組件的路由。真的很快,讓我們跳到 /index.server.js 文件並設置該路由。

為我們的組件連接路由

如果我們打開 /index.server.js 在我們的應用程序根目錄下的文件,我們會看到 joystick create app 我們之前調用的函數創建了一個自動導入和運行 node.app() 的文件 為我們提供一些示例路線。

/index.server.js

import node from "@joystick.js/node";
import api from "./api";

node.app({
  api,
  routes: {
    "/": (req, res) => {
      res.render("ui/pages/index/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "/posts": (req, res) => {
      res.render("ui/pages/posts/index.js");
    },
    "*": (req, res) => {
      res.render("ui/pages/error/index.js", {
        layout: "ui/layouts/app/index.js",
        props: {
          statusCode: 404,
        },
      });
    },
  },
});

默認情況下,根路由位於 / 和一個包羅萬象的或 404 * 的路線 (意思是,所有與這條路線不匹配的東西)都是為我們預先定義的。在這裡,我們添加了一個額外的路線 /posts .對於該路由,我們已經分配了一個函數來處理接收 req 的入站請求 和 res 對象。雖然看起來不像,但在幕後,Joystick 把它變成了一個普通的 Express.js 路由,類似於我們編寫 app.get('/posts', (req, res) => { ... }) .

在該函數內部,我們調用 Joystick 添加到 res 的特殊函數 名為 .render() 的對象 .顧名思義,此功能旨在渲染 響應請求的操縱桿組件。對於它,我們將路徑傳遞給我們希望它渲染的應用程序中的一個組件,以及一個選項對象(如果需要,它不在這裡,所以我們省略了它)。

當這個路由在瀏覽器中匹配時,Joystick 會去獲取這個組件並在服務器端為我們渲染成 HTML 並將 HTML 發送回瀏覽器。在內部,res.render() 知道 data 操縱桿組件上的選項。如果它在組件上看到這一點,它會“收集”調用並獲取數據作為服務器端渲染過程的一部分。

這就是我們要調用 posts 的方式 我們在上面定義的 getter。我們的目標是,當我們的頁面加載時,我們會返回服務器端渲染的 HTML,而其中沒有加載數據。

接下來,我們需要在傳遞給 res.render() 的路徑上實際創建組件 以上。

使用來自 API 的數據連接操縱桿組件

首先,我們需要添加我們假設存在於 /ui/pages/posts/index.js 的文件 :

/ui/pages/posts/index.js

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

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

export default Posts;

在這裡,我們只是使用 ui.component() 添加一個骨架組件 從 @joystick.js/ui 導入的函數 包(由 joystick create 自動為我們安裝 )。

在我們從 render 返回的 HTML 字符串中 函數,現在我們只是渲染一個空的 <div></div> .如果我們在瀏覽器中訪問我們在服務器上添加的路由 http://localhost:2600/posts ,我們應該會看到一個空白的白頁。

現在我們準備好連接我們的數據了。讓我們添加我們需要的所有內容並遍歷它(我們不需要太多代碼):

/ui/pages/posts/index.js

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

const Posts = ui.component({
  data: async (api = {}, req = {}, input = {}) => {
    return {
      posts: await api.get('posts', {
        input,
      }),
    };
  },
  render: ({ data, each }) => {
    return `
      <div>
        <ul>
          ${each(data?.posts, (post) => {
            return `
              <li>
                <h4>${post.title}</h4>
                <p>${post?.body?.slice(0, 80)}...</p>
              </li>
            `;
          })}
        </ul>
      </div>
    `;
  },
});

export default Posts;

信不信由你,這就是我們獲取數據並在我們的應用程序中呈現服務器端並在瀏覽器中呈現的全部內容。

在組件定義的頂部,我們添加了一個新選項 data 分配給一個功能。這個函數接收三個參數:

  1. api 這是一個包含 get() 的同構(意味著它在瀏覽器和服務器上工作)版本的對象 和 set() @joystick.js/ui 內置的函數 和 @joystick.js/node 調用我們的 getter 和 setter。
  2. req 這是入站 HTTP 請求的瀏覽器安全版本(這使我們可以訪問 req.paramsreq.context.user 因此我們可以在獲取數據時引用它們)。
  3. input 通過 data.refetch() 重新獲取數據時傳遞的任何輸入數據 方法(我們稍後會介紹)。

在該函數內部,我們返回一個我們想要分配的對像作為 data 的值 在我們的組件實例上。在這裡,因為我們想要返回一個帖子列表,我們定義了一個屬性 posts 並將其設置為對 api.get('posts') 的調用 'posts' part 是我們在教程前面定義的 getter 的名稱。

因為我們希望從該 getter 返回一個代表我們帖子的對像數組,所以我們將調用直接分配給該函數,前綴為 await 關鍵字(並添加 async 到我們傳遞給 data 的函數 ) 告訴 JavaScript 在繼續解釋代碼之前等到此調用響應。

這裡的最終結果是在服務器上,我們的數據被自動獲取並設置為 data 我們組件實例的屬性。在render中 函數,我們可以看到我們添加了一個調用來解構或“提取”一個 dataeach 傳遞給渲染函數的參數中的屬性(這是一個表示組件實例的對象)。

在我們的 HTML 中,我們添加了一個 <ul></ul> 無序列表標籤,在其中,我們使用 JavaScript 插值 ${} 語法說“在這些括號中,調用 each() 傳遞 data.posts 值的函數 。”

那個函數,each() 將遍歷我們傳遞給它的帖子數組,並從我們傳遞給它的第二個參數的函數中返回一個 HTML 字符串。該函數接受當前項目,或者在本例中為 post 在返回的 HTML 中循環使用。

在這裡,我們輸出 title 每篇文章和 body 的截斷版本 對於數組中的每個帖子。

如果我們現在加載瀏覽器,我們應該會在瀏覽器中看到一些帖子呈現。

雖然我們在技術上已經完成,但在結束之前,讓我們快速了解如何在初始頁面加載後重新獲取數據。

/ui/pages/posts/index.js

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

const Posts = ui.component({
  data: async (api = {}, req = {}, input = {}) => {
    return {
      posts: await api.get('posts', {
        input,
      }),
    };
  },
  events: {
    'submit form': (event, component) => {
      event.preventDefault();
      const input = component.DOMNode.querySelector('input');

      if (input.value) {
        component.data.refetch({ id: input.value });
      } else {
        component.data.refetch();
      }
    },
  },
  render: ({ data, each }) => {
    return `
      <div>
        <form>
          <input type="text" placeholder="Type a post ID here..." />
          <button type="submit">Get Post</button>
        </form>
        <ul>
          ${each(data?.posts, (post) => {
            return `
              <li>
                <h4>${post.title}</h4>
                <p>${post?.body?.slice(0, 80)}...</p>
              </li>
            `;
          })}
        </ul>
      </div>
    `;
  },
});

export default Posts;

如果我們正在構建一個重要的 UI,很可能在某些時候我們會希望基於某種用戶交互或某個時間間隔(例如,每 5 秒輪詢一次新數據)重新獲取數據。

data 分配給我們組件實例的屬性,Joystick 給我們一個 .refetch() 我們可以調用該方法來按需執行重新獲取。如果我們查看從 render() 返回的 HTML 函數,我們可以看到我們已經添加了幾行,添加了一個簡單的 <form></form> 帶有輸入和按鈕。

回想一下,當我們在服務器上定義 getter 時,我們添加了 id 的可能性 被傳遞,這樣我們就可以獲取特定的帖子。默認情況下,我們不傳遞任何東西,而是為了演示我們對 data.refetch() 的使用 (以及向其傳遞輸入值的能力),在這裡,我們為表單的 submit 添加了一個事件監聽器 事件來做到這一點。

查看events 我們添加到組件定義中的屬性,當我們提交表單時,首先,我們要確保我們調用了 event.preventDefault() event 上的函數 我們傳遞的參數(這是正在發生的瀏覽器 DOM 事件)以防止在瀏覽器中調用標准或內置的表單提交處理程序(這會觸發我們想要跳過的頁面刷新)。

在此之下,我們採用 component 作為第二個屬性自動傳遞給我們在操縱桿中的事件處理程序的實例。在那個對像上,一個 DOMNode 添加了屬性,它使我們能夠在瀏覽器中呈現當前組件時訪問它(我們在這裡編寫的代碼——我們的 Joystick 組件——只是動態生成這些 DOM 節點的抽象)。

在那個 component.DOMNode 我們稱之為 querySelector 的值 方法,傳入我們要訪問的元素的選擇器。在這裡,我們要獲取 <input /> 在我們的組件中呈現的標籤。作為回報,我們期望取回 那個輸入元素的 DOM 節點 (為什麼我們將它存儲在一個名為 input 的變量中 )。

在此之下,我們有條件地調用 component.data.refetch() 基於我們的 input 有一個價值。如果它確實 ,我們想將該值作為 id 傳遞 我們輸入對象的屬性。在這裡,我們傳遞給 component.data.refetch() 的對象 自動分配給 input 當我們調用 api.get('posts') 時我們傳遞給服務器的值 在我們的 data 功能。

如果 input.value 為空 ,我們想跳過任何輸入。

這樣做的最終結果是,如果我們 傳遞一個值(帖子的 ID,例如 15 ),我們將把它傳遞給我們的 getter,並期望從 JSON 佔位符 API 返回一個帖子。如果我們 傳遞一個值,我們將期望我們的完整帖子列表的默認響應。

回到瀏覽器中,如果我們加載它並在輸入中輸入一個數字並點擊“獲取帖子”,我們應該會看到我們的列表自動減少到那個帖子。如果我們刪除該號碼並再次點擊“獲取帖子”,我們應該會看到完整列表已恢復。

總結

在本教程中,我們學習瞭如何使用 Joystick 中的 getters 功能連接 API 端點,我們使用 Joystick data 從組件調用該功能 屬性來自動獲取和服務器端渲染我們的 HTML 和里面的數據。我們還學習瞭如何使用 res.render() 通過路由渲染組件 Joystick 中的方法以及如何在組件內部重新獲取數據以響應用戶的行為。


Tutorial JavaScript 教程
  1. 使用 HTML、CSS 和 Bootstrap 創建個人作品集網站

  2. 什麼是 PWA?

  3. 像老闆一樣的 JavaScript:理解 Fluent API

  4. 沒有 Firebase 的 React Native 中的 Google 身份驗證/登錄。

  5. 使用免費的 JavaScript 庫進行可視化:WebDataRocks 和 ChartJS

  6. Reduxs mapDispatchToProps 是如何工作的

  7. 理解 JavaScript 中的 valueOf()

  1. 算法工具包 #1:取模

  2. 再次刪除帶有文檔和集合的集合(firestore react native)

  3. GraphQL 概述:使用 React 前端構建待辦事項列表 API

  4. 免費書籍:部署 Node.js 🚀

  5. 添加禁用屬性 JavaScript |禁用 HTML 元素示例

  6. 檢測 JavaScript 版本

  7. 10 個 JavaScript 特性將幫助你更快地採用 React

  1. LeetCode - 旋轉圖像

  2. 在 Flutter 中實現人臉識別和身份驗證

  3. 使用 JavaScript 的隨機笑話生成器

  4. 第 3 章:讓我們進入動物群:在創建社交媒體數據庫時了解動物群的指南