一點 Vue.observable 想法

admin發表於2020-06-15

Vue 2.6.0 新增了 Vue.observable api,但最近才去嘗試使用它。

這東西說新也不新,因為他就是 vue 本身的功能,只是暴露出來,成為新 api 了。

在老版本中,直接用 new Vue({ data: {} }) 也一樣。

API 本身

官方文件原文描述是: 讓一個物件可響應。Vue 內部會用它來處理 data 函式返回的物件。

然後百度一下這個,幾乎全是 使用Vue.observable()進行狀態管理 這種文章。

谷歌一下也一樣,然後你會發現,國內的文章都是翻譯過來的。


所以我想試試能不能做點其他東西。


嘗試

我建立了一個可響應物件,const state = Vue.observable({ count: 1 });,然後嘗試掛載到 data 和 computed 下,發現都可以用,然後我在 state 上加了個方法。

[JavaScript] 純文字檢視 複製程式碼
const state = Vue.observable({ count: 1 });
state.add = () => state.count++;
const app = new Vue({
  data: {
    state,
  },
});

當掛載到 data 下,我發現 add 沒被代理,所以推測 vue 直接掛載 Vue.observable 建立的物件。


嘗試分頁封裝

我之前做分頁,都需要 data 下掛個物件,然後需要計算屬性計算當前顯示列表。

現在我們可以嘗試使用 Vue.observable 封裝一個分頁方法。

[JavaScript] 純文字檢視 複製程式碼
/**
 * 生成分頁
 * @param {any[]} list 資料列表
 * @param {number} size 每頁條數
 */
const pagination = (list, size = 10) => {
  const res = Vue.observable({
    /** 當前頁碼 */
    page: 1,
    /** 每頁條數 */
    size,
    /** 總頁數 */
    total: Math.ceil(list.length / size),
    /** 當前頁顯示資料 */
    list: [],
  });

  /** 原陣列 */
  res.orgList = list;

  /** 分頁方法 */
  res.setPage = (num) => {
    res.page += num
    const { page, size } = res;
    const pos = (page - 1) * size;
    res.list = res.orgList.slice(pos, pos + size);
  }

  // 初始化
  res.setPage(0);
  return res;
};

程式碼比較簡化,沒寫 ajax 分頁支援,就用最簡單的例子來演示,以便於理解。

[HTML] 純文字檢視 複製程式碼
<template>
  <div id="app">
    <ul>
      <li v-for="(it, idx) of usersList.list" :key="idx">{{ it.name }}</li>
    </ul>
    <div class="pagination">
      <span
        class="btn"
        :class="{ 'is-disabled': usersList.page === 1 }"
        @click="usersList.setPage(-1)"
      >上一頁</span>
      <span>{{usersList.page}}/{{usersList.total}}</span>
      <span
        class="btn"
        :class="{ 'is-disabled': usersList.page === usersList.total }"
        @click="usersList.setPage(1)"
      >下一頁</span>
    </div>
  </div>
</template>

<script>
import pagination from "./pagination";

const list = Array(33)
  .fill(0)
  .map((_, i) => ({ name: "name" + i }));

export default {
  name: "App",
  data() {
    return {
      usersList: pagination(list)
    };
  }
};
</script>

<style>
.btn {
  display: inline-block;
  background-color: #369;
  border-radius: 4px;
  padding: 0.2em 0.5em;
  color: #fff;
  user-select: none;
  margin: 0 0.5em;
}
.btn.is-disabled {
  background-color: #aaa;
  pointer-events: none;
}
</style>

小總

這個例子中 Vue.observable 將分頁功能封裝到一個函式中確實簡化了不少。

也許還有更多場景可以使用它來優化,那就等待大家去挖掘吧,別再一味翻譯國外的文章。

相關文章