下拉更新

下拉更新是一個特殊元件,可用於啟動頁面內容的更新。

下拉更新版面

讓我們看看如何將下拉更新整合到頁面中

<div class="page">
  <!-- Page content must have additional "ptr-content" class -->
  <div class="page-content ptr-content" data-ptr-distance="55" data-ptr-mousewheel="true">
    <!-- Default pull to refresh preloader-->
    <div class="ptr-preloader">
      <div class="preloader"></div>
      <div class="ptr-arrow"></div>
    </div>

    <!-- usual content below -->
    <div class="list">
      ...
    </div>

    <!-- nested scrollable element -->
    <div class="my-scolling-content ptr-watch-scrollable">
      ...
    </div>

    <!-- another nested scrollable element -->
    <div class="another-scolling-content ptr-ignore">
      ...
    </div>
  </div>
</div>

在何處

從底部下拉更新

也可以讓它像從底部下拉一樣運作。在這種情況下,我們需要將 ptr-preloader 元素移到頁面內容的底部,並在下拉更新內容中新增額外的 ptr-bottom 類別

<div class="page">
  <!-- ptr-content must have additional "ptr-bottom" class -->
  <div class="page-content ptr-content ptr-bottom">
    <div class="list">
      ...
    </div>

    <!-- Pull to refresh preloader moves to bottom -->
    <div class="ptr-preloader">
      <div class="preloader"></div>
      <div class="ptr-arrow"></div>
    </div>
  </div>
</div>

下拉更新順序

當使用者開始向下拉動 ptr-content 時,ptr-preloader 將接收額外的 ptr-pull-down 類別。

當使用者將 ptr-content 向下拉動超過 44px 的距離 (當 ptr-preloader 完全可見時),ptr-preloader 將接收額外的 ptr-pull-up 類別,這會改變箭頭旋轉,以通知使用者在釋放時進行更新動作。

當使用者在「ptr-pull-up」狀態時釋放下拉更新內容,則ptr-preloader將會收到額外的ptr-refreshing類別。在「更新」狀態下,箭頭將會隱藏,使用者將會看到預載指示器。在這個階段,您可能需要執行 Ajax 請求並更新頁面內容。

下拉更新應用程式方法

有幾個應用程式的程式碼可以用於下拉更新容器

app.ptr.create(el)- 在指定的 HTML 元素容器上初始化 PTR。

  • el - HTMLElementstring(使用 CSS 選擇器)- PTR 元素(ptr-content)。必填。

方法傳回建立的 PTR 執行個體

僅在您在頁面初始化後新增 ptr 內容,或是在稍後想要啟用它的情況下,才使用這個方法。否則,如果在頁面初始化時有「ptr-content」元素,它將會自動建立

app.ptr.destroy(el)- 從指定的 HTML 元素移除 PTR 事件監聽器

  • el - HTMLElementstring(使用 CSS 選擇器)- PTR 元素(ptr-content)。必填。

app.ptr.get(el)- 透過 HTML 元素取得 PTR 執行個體

  • el - HTMLElementstring(使用 CSS 選擇器)。PTR 元素(ptr-content)。

方法傳回 PTR 執行個體

app.ptr.done(el)- 重設指定的 PTR 內容元素上的 PTR 狀態

  • el - HTMLElementstring(使用 CSS 選擇器)。PTR 元素(ptr-content)。必填。

app.ptr.refresh(el)- 觸發指定的 PTR 內容元素上的 PTR

  • el - HTMLElementstring(使用 CSS 選擇器)。PTR 元素(ptr-content)。必填。

下拉更新方法和屬性

如果我們手動建立 PTR 或使用 app.ptr.get 方法,我們將會初始化 PTR 執行個體,其中包含有用的方法和屬性

// init ptr manually
var ptr = app.ptr.create('.ptr-content');

// or using get to retrieve already created instance
var ptr = app.ptr.get('.ptr-content');
屬性
ptr.app連結到全域應用程式執行個體
ptr.elPTR HTML 元素(ptr-content
ptr.$el包含 PTR HTML 元素(ptr-content)的 Dom7 執行個體
方法
ptr.done()重設 PTR 狀態
ptr.refresh()觸發 PTR
ptr.destroy()銷毀 PTR 實例並從指定的 HTML 元素中移除 PTR 事件聆聽器

下拉更新事件

PTR 會在彈出元素上觸發下列 DOM 事件,以及在應用程式和彈出實例上觸發事件

DOM 事件

事件目標說明
ptr:pullstart下拉更新內容<div class="ptr-content">當您開始移動下拉更新內容時,將觸發事件
ptr:pullmove下拉更新內容<div class="ptr-content">在您移動下拉更新內容期間,將觸發事件
ptr:pullend下拉更新內容<div class="ptr-content">當您釋放下拉更新內容時,將觸發事件
ptr:refresh下拉更新內容<div class="ptr-content">當下拉更新進入「更新中」狀態時,將觸發事件。event.detail 包含 ptr.done 方法,可在載入完成後重設其狀態
ptr:done下拉更新內容<div class="ptr-content">在下拉更新完成並回到初始狀態(呼叫 ptr.done 方法後)後,將觸發事件
ptr:beforedestroy下拉更新內容<div class="ptr-content">在 PTR 實例即將被銷毀之前,將觸發事件

應用程式和下拉更新實例事件

PTR 實例會在自身實例和應用程式實例上發出事件。應用程式實例事件具有相同的名稱,並以 ptr 為字首。

事件目標引數說明
pullStartptr(el)當您開始移動下拉更新內容時,將觸發事件。事件處理常式會接收到 ptr 元素作為引數
ptrPullStartapp(el)
pullMoveptr(el, data)在您移動下拉更新內容期間,將觸發事件。事件處理常式會接收到 ptr 元素和包含下列屬性的 ptr 資料作為引數
  • event - touchmove 事件
  • scrollTop - 目前的捲軸頂端位置
  • translate - 目前的 translateY 位移
  • touchesDiff - 觸控點差異(以像素為單位)
ptrPullMoveapp(el, data)
pullEndptr(el, data)當您釋放下拉更新內容時,將觸發事件。事件處理常式會接收到 ptr 元素作為引數
ptrPullEndapp(el, data)
refreshptr(el, done)當下拉更新進入「更新中」狀態時,將觸發事件。事件處理常式會接收到 ptr 元素和 done 函式,以重設 PTR 狀態
ptrRefreshapp(el, done)
完成ptr(el)拉動更新完成並返回初始狀態後(呼叫 ptr.done 方法後)將觸發事件。事件處理常式會收到 ptr 元素作為參數
ptrDoneapp(el)
beforeDestroyptr(ptr)PTR 執行個體即將被銷毀前將觸發事件。事件處理常式會收到 PTR 執行個體作為參數
ptrBeforeDestroyapp(ptr)

CSS 變數

以下是相關的 CSS 變數(CSS 自訂屬性)清單。

.ios {
  --f7-ptr-preloader-size: 28px;
  --f7-ptr-size: 44px;
}
.md {
  --f7-ptr-preloader-size: 22px;
  --f7-ptr-size: 40px;
}
.md,
.md .dark,
.md [class*='color-'] {
  --f7-ptr-preloader-bg-color: var(--f7-md-surface-1);
  --f7-ptr-preloader-color: var(--f7-md-primary);
}

範例

從上方拉動

pull-to-refresh.f7.html
<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner">
        <div class="title">Pull To Refresh</div>
      </div>
    </div>
    <div class="page-content ptr-content" @ptr:refresh=${loadMore}>
      <div class="ptr-preloader">
        <div class="preloader"></div>
        <div class="ptr-arrow"></div>
      </div>
      <div class="list media-list">
        <ul>
          ${items.map((item) => $h`
          <li class="item-content">
            <div class="item-media"><img src=${item.picURL} width="44" /></div>
            <div class="item-inner">
              <div class="item-title-row">
                <div class="item-title">${item.song}</div>
              </div>
              <div class="item-subtitle">${item.author}</div>
            </div>
          </li>
          `)}
        </ul>
      </div>
    </div>
  </div>
</template>
<script>
  export default (props, { $update }) => {
    // Dummy Content
    const songs = ['Yellow Submarine', 'Don\'t Stop Me Now', 'Billie Jean', 'Californication'];
    const authors = ['Beatles', 'Queen', 'Michael Jackson', 'Red Hot Chili Peppers'];
    let items = [
      {
        picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-1.jpg',
        song: 'Yellow Submarine',
        author: 'Beatles',
      },
      {
        picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-2.jpg',
        song: 'Don\'t Stop Me Now',
        author: 'Queen',
      },
      {
        picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-3.jpg',
        song: 'Billie Jean',
        author: 'Michael Jackson',
      },
    ]

    const loadMore = (e, done) => {
      // Emulate 2s loading
      setTimeout(() => {
        const picURL = 'https://cdn.framework7.io/placeholder/abstract-88x88-' + (Math.floor(Math.random() * 10) + 1) + '.jpg';
        const song = songs[Math.floor(Math.random() * songs.length)];
        const author = authors[Math.floor(Math.random() * authors.length)];
        // Add new item
        items.push({
          picURL,
          song,
          author,
        });

        // Update state to rerender
        $update();

        // When loading done, we need to reset it
        done();
      }, 2000);
    }

    return $render;
  }
</script>

從下方拉動

pull-to-refresh-bottom.f7.html
<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner">
        <div class="title">Pull To Refresh Bottom</div>
      </div>
    </div>
    <div class="page-content ptr-content ptr-bottom" @ptr:refresh=${loadMore}>
      <div class="ptr-preloader">
        <div class="preloader"></div>
        <div class="ptr-arrow"></div>
      </div>
      <div class="list media-list">
        <ul>
          ${items.map((item) => $h`
          <li class="item-content">
            <div class="item-media"><img src=${item.picURL} width="44" /></div>
            <div class="item-inner">
              <div class="item-title-row">
                <div class="item-title">${item.song}</div>
              </div>
              <div class="item-subtitle">${item.author}</div>
            </div>
          </li>
          `)}
        </ul>
      </div>
    </div>
  </div>
</template>
<script>
  export default (props, { $update }) => {
    // Dummy Content
    const songs = ['Yellow Submarine', 'Don\'t Stop Me Now', 'Billie Jean', 'Californication'];
    const authors = ['Beatles', 'Queen', 'Michael Jackson', 'Red Hot Chili Peppers'];
    let items = [
      {
        picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-1.jpg',
        song: 'Yellow Submarine',
        author: 'Beatles',
      },
      {
        picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-2.jpg',
        song: 'Don\'t Stop Me Now',
        author: 'Queen',
      },
      {
        picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-3.jpg',
        song: 'Billie Jean',
        author: 'Michael Jackson',
      },
    ]

    const loadMore = (e, done) => {
      // Emulate 2s loading
      setTimeout(() => {
        const picURL = 'https://cdn.framework7.io/placeholder/abstract-88x88-' + (Math.floor(Math.random() * 10) + 1) + '.jpg';
        const song = songs[Math.floor(Math.random() * songs.length)];
        const author = authors[Math.floor(Math.random() * authors.length)];
        // Add new item
        items.push({
          picURL,
          song,
          author,
        });

        // Update state to rerender
        $update();

        // When loading done, we need to reset it
        done();
      }, 2000);
    }

    return $render;
  }
</script>