JavaScript >> Javascript 文檔 >  >> Tags >> DOM

如何使用 JavaScript 在 DOM 中動態定位元素

如何使用 JavaScript 相對於其他 DOM 元素動態操作 DOM 元素。

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

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

為什麼?

乍一看,這似乎有點傻。我們為什麼要這樣做?好吧,當您開始構建更複雜的界面時,儘管最好通過 CSS first 嘗試許多 UI 模式 ,有時,這會使事情變得比必要的複雜。當您自己的應用出現這種情況時,最好知道如何通過 JavaScript 應用樣式來處理 UI 中的更改以避免混亂或脆弱的 CSS。

設置我們的測試用例

在本教程中,我們將使用操縱桿組件。這是我們剛剛設置的 Joystick 框架的 UI 部分。這將允許我們使用純 HTML、CSS 和 JavaScript 快速構建 UI。

首先,在我們運行 joystick create app 時為我們創建的應用程序中 ,打開/ui/pages/index/index.js 文件。獲取後,將內容替換為以下內容:

/ui/pages/index/index.js

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

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

export default Index;

在這裡,我們將替換映射到應用程序 http://localhost:2600/ 中根路由的現有示例組件 (或只是 / ) 帶有一個骨架組件,我們可以使用它來構建我們的測試用例。

接下來,讓我們替換那個 <div></div>render() 返回 方法(這是將在屏幕上呈現或“繪製”的 HTML)以及我們稍後將使用 JavaScript 動態定位的“卡片”列表:

/ui/pages/index/index.js

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

const Index = ui.component({
  render: () => {
    return `
      <div class="index">
        <ul class="cards">
          <li>
            <h2>Aliquam impedit ipsa adipisci et quae repellat sit.</h2>
            <p>Deleniti quibusdam quia assumenda omnis. Rerum cum et error vero enim ex. Sapiente est est ut omnis possimus temporibus in.</p>
          </li>
          <li>
            <h2>Ab recusandae minima commodi sed pariatur.</h2>
            <p>Velit in voluptatum quia consequatur fuga et repellendus ut cupiditate. Repudiandae dignissimos dolores qui. Possimus nihil laboriosam enim dolorem vitae accusantium accusamus dolor. Tenetur fuga omnis et est accusantium dolores. Possimus vitae aliquid. Vitae commodi et autem vitae rerum.</p>
          </li>
          <li>
            <h2>Voluptatem ipsa sed illum numquam aliquam sint.</h2>
            <p>Suscipit quis error dolorum sed recusandae recusandae est. Et tenetur perferendis sequi itaque similique. Porro facere qui saepe alias. Qui itaque corporis explicabo itaque. Quibusdam vel expedita odio quaerat libero veniam praesentium minus.</p>
          </li>
          <li>
            <h2>Aliquam impedit ipsa adipisci et quae repellat sit.</h2>
            <p>Deleniti quibusdam quia assumenda omnis. Rerum cum et error vero enim ex. Sapiente est est ut omnis possimus temporibus in.</p>
          </li>
          <li>
            <h2>Ab recusandae minima commodi sed pariatur.</h2>
            <p>Velit in voluptatum quia consequatur fuga et repellendus ut cupiditate. Repudiandae dignissimos dolores qui. Possimus nihil laboriosam enim dolorem vitae accusantium accusamus dolor. Tenetur fuga omnis et est accusantium dolores. Possimus vitae aliquid. Vitae commodi et autem vitae rerum.</p>
          </li>
          <li>
            <h2>Voluptatem ipsa sed illum numquam aliquam sint.</h2>
            <p>Suscipit quis error dolorum sed recusandae recusandae est. Et tenetur perferendis sequi itaque similique. Porro facere qui saepe alias. Qui itaque corporis explicabo itaque. Quibusdam vel expedita odio quaerat libero veniam praesentium minus.</p>
          </li>
          <li>
            <h2>Aliquam impedit ipsa adipisci et quae repellat sit.</h2>
            <p>Deleniti quibusdam quia assumenda omnis. Rerum cum et error vero enim ex. Sapiente est est ut omnis possimus temporibus in.</p>
          </li>
          <li>
            <h2>Ab recusandae minima commodi sed pariatur.</h2>
            <p>Velit in voluptatum quia consequatur fuga et repellendus ut cupiditate. Repudiandae dignissimos dolores qui. Possimus nihil laboriosam enim dolorem vitae accusantium accusamus dolor. Tenetur fuga omnis et est accusantium dolores. Possimus vitae aliquid. Vitae commodi et autem vitae rerum.</p>
          </li>
          <li>
            <h2>Voluptatem ipsa sed illum numquam aliquam sint.</h2>
            <p>Suscipit quis error dolorum sed recusandae recusandae est. Et tenetur perferendis sequi itaque similique. Porro facere qui saepe alias. Qui itaque corporis explicabo itaque. Quibusdam vel expedita odio quaerat libero veniam praesentium minus.</p>
          </li>
          <li>
            <h2>Aliquam impedit ipsa adipisci et quae repellat sit.</h2>
            <p>Deleniti quibusdam quia assumenda omnis. Rerum cum et error vero enim ex. Sapiente est est ut omnis possimus temporibus in.</p>
          </li>
          <li>
            <h2>Ab recusandae minima commodi sed pariatur.</h2>
            <p>Velit in voluptatum quia consequatur fuga et repellendus ut cupiditate. Repudiandae dignissimos dolores qui. Possimus nihil laboriosam enim dolorem vitae accusantium accusamus dolor. Tenetur fuga omnis et est accusantium dolores. Possimus vitae aliquid. Vitae commodi et autem vitae rerum.</p>
          </li>
          <li>
            <h2>Voluptatem ipsa sed illum numquam aliquam sint.</h2>
            <p>Suscipit quis error dolorum sed recusandae recusandae est. Et tenetur perferendis sequi itaque similique. Porro facere qui saepe alias. Qui itaque corporis explicabo itaque. Quibusdam vel expedita odio quaerat libero veniam praesentium minus.</p>
          </li>
        </ul>
      </div>
    `;
  },
});

export default Index;

很簡單。在這裡,我們添加了一個類 index 到現有的 <div></div> 在裡面,我們添加了一個 <ul></ul> (無序列表)類 cards .在裡面,我們添加了 12 個 <li></li> 標籤,每個代表一張“卡片”,上面有一些 lorem ipsum 內容。儘管長度在技術上是任意的,但為了理解我們將在下面實現的內容,有幾個項目而不是 1-2 是有意義的(儘管可以隨意調整長度,因為我們的代碼仍然可以工作)。

/ui/pages/index/index.js

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

const Index = ui.component({
  css: `
    .cards {
      opacity: 0;
      border-top: 1px solid #eee;
      border-bottom: 1px solid #eee;
      padding: 40px;
      overflow-x: scroll;
      display: flex;
    }

    .cards li {
      background: #fff;
      border: 1px solid #eee;
      box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
      padding: 30px;
      border-radius: 3px;
      list-style: none;
      width: 300px;
      min-width: 300px;
    }

    .cards li h2 {
      font-size: 28px;
      line-height: 36px;
      margin: 0;
    }

    .cards li p {
      font-size: 16px;
      line-height: 24px;
      color: #888;
    }

    .cards li:not(:last-child) {
      margin-right: 30px;
    }
  `,
  render: () => {
    return `
      <div class="index">
        <ul class="cards">
          <li>
            <h2>Aliquam impedit ipsa adipisci et quae repellat sit.</h2>
            <p>Deleniti quibusdam quia assumenda omnis. Rerum cum et error vero enim ex. Sapiente est est ut omnis possimus temporibus in.</p>
          </li>
          ...
        </ul>
      </div>
    `;
  },
});

export default Index;

就在我們的render之上 方法,我們已經向我們的組件 css 添加了一個屬性 正如您所期望的那樣,它允許我們向我們的組件添加一些 CSS 樣式。這些樣式的目的是為我們提供一個水平滾動的“卡片”列表,這些“卡片”延伸到瀏覽器的邊緣,如下所示:

現在我們在瀏覽器中有了基本樣式和標記,接下來,我們要添加必要的 JavaScript 以動態地將列表中的第一張卡片移動到頁面中間。我們的目標是模仿當前 Apple Store 設計中的“新功能”列表這樣的設計:

為此,接下來,我們將連接必要的 JavaScript 作為 Joystick 組件上的方法。

在頁面加載時動態設置填充

在我們在這里處理“頁面加載”部分之前,首先,我們需要編寫 JavaScript 在 DOM 中選擇我們的列表,計算窗口的當前中心點,然後設置列表的左側填充。我們是這樣做的:

/ui/pages/index/index.js

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

const Index = ui.component({
  state: {
    defaultListPadding: '20px',
  },
  methods: {
    handleSetListPadding: (component = {}) => {
      const list = component.DOMNode.querySelector('ul.cards');
      const windowCenterPoint = window.innerWidth / 2;
      
      if (list) {
        list.style.paddingLeft = windowCenterPoint >= 400 ? `${windowCenterPoint}px` : component.state.defaultListPadding;
        list.style.opacity = 1;
      }
    },
  },
  css: `...`,
  render: () => {
    return `
      <div class="index">
        <ul class="cards">
          <li>
            <h2>Aliquam impedit ipsa adipisci et quae repellat sit.</h2>
            <p>Deleniti quibusdam quia assumenda omnis. Rerum cum et error vero enim ex. Sapiente est est ut omnis possimus temporibus in.</p>
          </li>
          ...
        </ul>
      </div>
    `;
  },
});

export default Index;

在操縱桿組件上,“方法”(定義為 methods 上的方法函數 我們組件選項的屬性)是我們組件上的一個雜項函數,可以從組件中的任何位置調用。在這裡,我們定義了 handleSetListPadding 作為一種方法,以便我們可以在我們的組件安裝在屏幕上時調用它(稍後會詳細介紹)。

首先,我們添加一個參數為 component 它由 Joystick 自動傳遞給我們(框架自動將函數上最後一個可能的參數分配為組件實例——因為我們沒有任何參數,所以它默認為第一個插槽)。在那個 component 實例對象,我們得到一個 DOMNode 代表我們組件渲染的 DOM 節點的屬性(在本例中為 Index 我們正在創作的組件)在瀏覽器中。

由此,我們可以使用原生 JavaScript DOM 選擇,在這裡,我們使用 .querySelector() 該 DOM 節點上的方法來定位我們的 ul.cards 列表,將其存儲在變量 list 中 .

接下來,因為我們想將該列表的左側填充設置為窗口的中心,所以我們需要計算該中心點的像素值是多少。為此,我們可以採用 window.innerWidth 值並除以 2 (例如,如果我們的窗口當前是 1000 像素寬,windowCenterPoint 將變為 500 )。

使用我們的 listwindowCenterPoint 假設我們做了 找到一個 list 頁面中的元素,我們要修改list.style.paddingLeft value,設置它等於一個字符串值,連接 windowCenterPoint 的值 使用 px (我們這樣做是因為我們得到的值是一個整數,但我們需要將填充設置為像素值)。

請注意,在這裡,我們將這個 paddingLeft 基於 windowCenterPoint 的值的條件值 .如果值大於400 ,我們要將其設置為 paddingLeft .如果是不是 ,我們想要回退到默認的填充值(這可以確保我們不會意外地將卡片完全推離屏幕以獲得較小的視口)。為了存儲這個默認值,我們添加了 state 組件選項的屬性,它是一個包含組件狀態默認值的對象。在這裡,我們分配了 defaultListPadding 到字符串 '20px' 我們在 windowCenterPoint >= 400 中將其用作“else” 三元。

接下來,就在我們調用設置 list.style.paddingLeft 的下方 我們還確保設置 list.style.opacity 1. 為什麼?好吧,在我們的 css 我們之前設置的,我們將列表設置為 opacity: 0; 默認。這是一個“技巧”,可防止我們的列表在頁面加載緩慢(命中或未命中取決於連接速度)期間在頁面上視覺跳轉。這消除了任何可能對用戶造成影響的視覺故障。

雖然我們已經編寫了代碼,但目前這不會做任何事情。為了讓它工作,我們需要實際調用我們的方法。

在掛載和窗口調整大小時調用 handleSetListPadding

這部分很簡單,下面是完成它的代碼:

/ui/pages/index/index.js

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

const Index = ui.component({
  state: {
    defaultListPadding: '20px',
  },
  lifecycle: {
    onMount: (component = {}) => {
      component.methods.handleSetListPadding();

      window.addEventListener('resize', () => {
        component.methods.handleSetListPadding();
      });
    },
  },
  methods: {
    handleSetListPadding: (component = {}) => {
      const list = component.DOMNode.querySelector('ul.cards');
      const windowCenterPoint = window.innerWidth / 2;
      
      if (list) {
        list.style.paddingLeft = windowCenterPoint >= 400 ? `${windowCenterPoint}px` : component.state.defaultListPadding;
        list.style.opacity = 1;
      }
    },
  },
  css: `...`,
  render: () => {
    return `
      <div class="index">
        <ul class="cards">
          <li>
            <h2>Aliquam impedit ipsa adipisci et quae repellat sit.</h2>
            <p>Deleniti quibusdam quia assumenda omnis. Rerum cum et error vero enim ex. Sapiente est est ut omnis possimus temporibus in.</p>
          </li>
          ...
        </ul>
      </div>
    `;
  },
});

export default Index;

為我們的組件 lifecycle 添加更多選項 , 在傳遞給它的對像上,我們分配一個屬性 onMount 它設置為一個函數,一旦我們的組件的 HTML 呈現給瀏覽器,Joystick 就會調用該函數。就像我們的 handleSetListPadding 方法,Joystick 自動傳遞 component 實例到所有可用的生命週期方法。

在這裡,我們使用那個 component 實例來訪問我們的 handleSetListPadding 方法,使用 component.methods.handleSetListPadding() 調用它 .除此之外,我們還需要考慮用戶調整瀏覽器的大小以及這將如何影響窗口的中心點。我們需要做的就是在 window 上添加一個事件監聽器 對於 resize 事件並在檢測到該事件時調用的回調中,再次調用 component.methods.handleSetListPadding() .

這是有效的,因為我們正在檢索 window.innerWidth 的值 在調用 handleSetListPadding 時 功能。那麼,在這裡,因為我們在 之後獲得了該值 調整大小已經發生,我們可以相信 window.innerWidth 將包含當前寬度,而不是我們在頁面加載時的寬度。

而已!現在,如果我們在瀏覽器中加載我們的頁面,我們應該能夠調整大小並看到我們的第一張卡片將其左邊緣移動到與窗口中心對齊。

總結

在本教程中,我們學習瞭如何使用 JavaScript 動態操作 DOM。我們學習瞭如何使用 DOM style 通過 CSS 動態定位元素 列表元素的屬性。我們還學習瞭如何依賴 window 每當瀏覽器寬度發生變化時,resize 事件都會重新計算瀏覽器的中心點。


Tutorial JavaScript 教程
  1. 狀態管理器與 Vanilla JS 庫的干淨集成

  2. 客戶端渲染與服務器端渲染

  3. 如何使用 JQuery 將 HTML 標籤更改為另一個標籤?

  4. NGRX 研討會筆記 - 操作

  5. 我是如何自願重新設計 Internet 電子郵件的

  6. 通過 Omnibar 搜索您的網站 - 甚至是靜態網站

  7. 如何使用 Fincra 接受在線支付

  1. 在堆棧中查找最大值

  2. 為什麼我喜歡模式匹配

  3. React 16+ 單張和多張圖片上傳預覽

  4. 反應自定義工具提示

  5. 使用 Meteor 構建多人井字遊戲

  6. JavaScript 中的嚴格模式

  7. 避免在 React 中記憶你的處理程序(並防止無限重新渲染)

  1. 學習 Svelte - 項目 1:依賴解決工具

  2. 為什麼 javascript 使用 ajax 創建虛假圖像?

  3. 如何使用 HTML、CSS、JavaScript 和 Firebase 構建活動預訂應用程序

  4. 對帶有流式 API 端點的 websocket 使用 actioncable