iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0
自我挑戰組

不用前端框架 手把手打造基礎SPA網站系列 第 18

[DAY18]進階應用 - SPA簡易生命週期實現

什麼是生命週期

在進入這個主題前,首先需要了解什麼是網頁的生命週期。在以往傳統網頁,每頁都是獨立分開的個體,生命週期的起算,從網頁開始讀取,到DOM(Document Object Model)的產生,至整個頁面加載完畢,及離開網頁的事件。SPA由於是單頁應用,除了一開始加載頁面,內容的切換實際上都在同一頁,所以在切換內容時,不會觸發網頁原本的讀取與離開事件。 為了實現這個方法,前端框架也有所謂的Lifecycle Methods,讓元件可以在發生不同事件當中做要做的事情。

以React為例

在React的世界裡,每個component有屬於自己的生命週期,我們可以看下面這張圖:

React component完整的生命週期過程包含mounting(掛載) -> updating(更新) -> unmounting(卸載)。可以看到熟悉的render發生在mounting至updating階段,另外在mounting階段的下方有個componentDidMount方法,這代表在DOM加載完成時觸發,看看React對這部份的說明:

在一個 component 被 mount(加入 DOM tree 中)後,componentDidMount() 會馬上被呼叫。需要 DOM node 的初始化應該寫在這個方法裡面。如果你需要從遠端終端點(remote endpoint)請求資料的話, 此處非常適合進行實例化網路請求(network request)。

當要透過操作頁面中的DOM元件來達成一些行為,為了避免DOM還沒有加載進來操作會出現錯誤,就使用componentDidMount這個方法來操作。

所以若是我們想要在SPA中操作Component裡的DOM元件,是否代表在render方法後觸發另一個方法就可以了?

加載完畢彈出視窗

我們可以常會看到一些網站在載入完成時跳出友善擾人的廣告視窗,今天來試試看這樣的效果。首先到Bootstrap官網找到Modal彈窗元件,複製代碼後把它加入Home.js,作為在進入畫面時顯示的提示訊息:

src/pages/Home.js

import { App } from './App'
 
export const Home = {
  render: () => {
    const modal = `
      <div class="modal" tabindex="-1" id="modal">
        <div class="modal-dialog">
          <div class="modal-content">
            <div class="modal-header">
              <h5 class="modal-title">重要公告</h5>
              <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                <span aria-hidden="true">×</span>
              </button>
            </div>
            <div class="modal-body">
              <p>假期只剩三天QQ</p>
            </div>
          </div>
        </div>
      </div>
    `
    const content = `
      <div class="container">
        <h1>Home page</h1>
        <div>Welcome to my page!</div>
      </div>
      ${modal}
    `
 
    return App.render(content)
  },
}

我們宣告modal並放在原本宣告的content裡,因為bootstrap預設Modal是隱藏的,只有在呼叫顯示時才會出現,呼叫的方法為$('#modal').modal('show')。如果在render階段裡使用呼叫,可以預期的是因為還沒完成render,頁面中還沒產生DOM,所以什麼事也沒發生。

為元件增加mount屬性

為了可以正常運作,應該要在render階段後才對modal使用呼叫方法,所以我們嘗試在Home Component物件中加入一個新的屬性mount,同樣使用callback的arrow function,然後在裡面放入呼叫的方法如下:

src/pages/Home.js

//引入JQuery
import $ from 'jquery'

export const Home = {
  mount: () => {
    //呼叫modal
    $('#modal').modal('show')
  },
  render: () => {
//...

因為呼叫顯示modal有使用到JQuery,開頭也記得一併引入。

在Router呼叫mount

接著我們到原本的Router模組裡,把元件內的mount方法加入進來:

src/routes/Router.js

export const Router = () => {
  //...
  // 3.將元件內容渲染至畫面
  document.querySelector('#wrapper').innerHTML = component.render()
  // 4.元件render後呼叫
  component.mount()
}

這樣就算完成了,可以看到在render後增加了呼叫元件mount屬性,如此就可以確保在DOM產生後對modal進行呼叫了。

最後成果

參考資料:
重新認識 JavaScript 番外篇 (6) - 網頁的生命週期


上一篇
[DAY17]進階應用 - 幫你的SPA套上Bootstrap
下一篇
[DAY19]進階應用 - 元件內部State的應用
系列文
不用前端框架 手把手打造基礎SPA網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言