Vue3使用Composition API實現響應式

来源:https://www.cnblogs.com/Amd794/p/18220995
-Advertisement-
Play Games

title: Vue3使用Composition API實現響應式 date: 2024/5/29 下午8:10:24 updated: 2024/5/29 下午8:10:24 categories: 前端開發 tags: Vue3 Composition Refs Reactive Watch L ...



title: Vue3使用Composition API實現響應式
date: 2024/5/29 下午8:10:24
updated: 2024/5/29 下午8:10:24
categories:

  • 前端開發

tags:

  • Vue3
  • Composition
  • Refs
  • Reactive
  • Watch
  • Lifecycle
  • Debugging

image

1. 介紹

Composition API是Vue.js 3中新增的一組API,用於在組件中組合邏輯和功能。它可以讓你更好地組織和重用代碼,使組件更易於理解和維護。在使用Composition
API時,你可以使用<script setup>語法或setup()函數,兩種方式都可以使用Composition API中的響應式API、生命周期鉤子、模板引用和自定義渲染函數等特性。

2. 基本響應式

在Vue.js 3中,Composition API提供了幾種創建響應式數據的方法,包括refreactivereadonlyshallowReactive
shallowReadonly

2.1 ref

ref函數用於創建一個響應式的ref對象,其值可以通過.value
屬性獲取或設置。當ref對象的值發生變化時,Vue.js會自動更新視圖。AD:首頁 | 一個覆蓋廣泛主題工具的高效線上平臺

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const count = ref(0);

function increment() {
  count.value++;
}
</script>

2.2 reactive

reactive函數用於創建一個響應式的對象,其所有屬性都是響應式的。當對象的屬性發生變化時,Vue.js會自動更新視圖。

<template>
  <div>
    <p>name: {{ user.name }}</p>
    <p>age: {{ user.age }}</p>
    <button @click="incrementAge">+1</button>
  </div>
</template>

<script setup>
import { reactive } from 'vue';

const user = reactive({
  name: 'Alice',
  age: 20
});

function incrementAge() {
  user.age++;
}
</script>

2.3 readonly

readonly函數用於創建一個只讀的響應式對象,其所有屬性都是只讀的。當試圖修改只讀對象的屬性時,會拋出一個錯誤。

<template>
  <div>
    <p>name: {{ user.name }}</p>
    <p>age: {{ user.age }}</p>
  </div>
</template>

<script setup>
import { reactive, readonly } from 'vue';

const user = reactive({
  name: 'Alice',
  age: 20
});

const readonlyUser = readonly(user);

// 會拋出一個錯誤
readonlyUser.age = 21;
</script>

2.4 shallowReactive

shallowReactive函數用於創建一個淺響應式的對象,其所有屬性都是響應式的,但其子對象的屬性不是響應式的。
AD:專業搜索引擎

<template>
  <div>
    <p>name: {{ user.name }}</p>
    <p>age: {{ user.age }}</p>
    <p>address: {{ user.address }}</p>
    <button @click="incrementAge">+1</button>
    <button @click="changeAddress">改變地址</button>
  </div>
</template>

<script setup>
import { shallowReactive } from 'vue';

const user = shallowReactive({
  name: 'Alice',
  age: 20,
  address: {
    province: 'Beijing',
    city: 'Beijing'
  }
});

function incrementAge() {
  user.age++;
}

function changeAddress() {
  user.address = {
    province: 'Shanghai',
    city: 'Shanghai'
  };
}
</script>

2.5 shallowReadonly

shallowReadonly函數用於創建一個淺只讀的響應式對象,其所有屬性都是只讀的,但其子對象的屬性不是只讀的。

<template>
  <div>
    <p>name: {{ user.name }}</p>
    <p>age: {{ user.age }}</p>
    <p>address: {{ user.address }}</p>
    <!-- 會拋出一個錯誤 -->
    <button @click="changeAddress">改變地址</button>
  </div>
</template>

<script setup>
import { shallowReactive, shallowReadonly } from 'vue';

const user = shallowReactive({
  name: 'Alice',
  age: 20,
  address: {
    province: 'Beijing',
    city: 'Beijing'
  }
});

const readonlyUser = shallowReadonly(user);

// 會拋出一個錯誤
readonlyUser.age = 21;
</script>

3. 響應式API

Composition API提供了幾種響應式API,包括watchEffectwatchcomputedprovide/inject

3.1 watchEffect

watchEffect函數用於創建一個響應式的副作用函數,當響應式數據發生變化時,副作用函數會自動重新執行。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script setup>
import { ref, watchEffect } from 'vue';

const count = ref(0);

watchEffect(() => {
  console.log(`count is ${count.value}`);
});

function increment() {
  count.value++;
}
</script>

3.2 watch

watch函數用於創建一個響應式的監聽器,當響應式數據發生變化時,監聽器會自動執行。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';

const count = ref(0);

watch(count, (newValue, oldValue) => {
  console.log(`count changed from ${oldValue} to ${newValue}`);
});

function increment() {
  count.value++;
}
</script>

3.3 computed

computed函數用於創建一個響應式的計算屬性,其值是根據響應式數據計算得出的。當響應式數據發生變化時,計算屬性會自動重新計算。
AD:漫畫首頁

<template>
  <div>
    <p>count: {{ count }}</p>
    <p>doubleCount: {{ doubleCount }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

const count = ref(0);

const doubleCount = computed(() => {
  return count.value * 2;
});

function increment() {
  count.value++;
}
</script>

3.4 provide/inject

provideinject函數用於在組件樹中傳遞數據。provide函數用於在父組件中提供數據,inject函數用於在子組件中註入數據。

<template>
  <div>
    <ChildComponent />
  </div>
</template>

<script setup>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue';

provide('message', 'Hello, world!');
</script>
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script setup>
import { inject } from 'vue';

const message = inject('message');
</script>

4. 生命周期鉤子

Composition
API提供了幾種生命周期鉤子,包括setup()onBeforeMount()onMounted()onBeforeUpdate()onUpdated()onBeforeUnmount()onUnmounted()onErrorCaptured()onRenderTracked()
onRenderTriggered()

4.1 setup()

setup()函數是Composition API的入口點,用於在組件創建之前執行一些初始化操作。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    return {
      count,
      increment
    };
  }
};
</script>

4.2 onBeforeMount()

onBeforeMount()函數在組件掛載之前執行。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    onBeforeMount(() => {
      console.log('before mount');
    });

    return {
      count,
      increment
    };
  }
};
</script>

4.3 onMounted()

onMounted()函數在組件掛載之後執行。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    onMounted(() => {
      console.log('mounted');
    });

    return {
      count,
      increment
    };
  }
};
</script>

4.4 onBeforeUpdate()

onBeforeUpdate()函數在組件更新之前執行。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    onBeforeUpdate(() => {
      console.log('before update');
    });

    return {
      count,
      increment
    };
  }
};
</script>

4.5 onUpdated()

onUpdated()函數在組件更新之後執行。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    onUpdated(() => {
      console.log('updated');
    });

    return {
      count,
      increment
    };
  }
};
</script>

4.6 onBeforeUnmount()

onBeforeUnmount()函數在組件卸載之前執行。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    onBeforeUnmount(() => {
      console.log('before unmount');
    });

    return {
      count,
      increment
    };
  }
};
</script>

4.7 onUnmounted()

onUnmounted()函數在組件卸載之後執行。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    onUnmounted(() => {
      console.log('unmounted');
    });

    return {
      count,
      increment
    };
  }
};
</script>

4.8 onErrorCaptured()

onErrorCaptured()函數在組件捕獲到錯誤時執行。

<template>
  <div>
    <p>count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const count = ref(0);

    function increment() {
      count.value++;
    }

    onErrorCaptured((error, instance, info) => {
      console.error(error);
      return false;
    });

    return {
      count,
      increment
    };
  }
};
</script>

4.9 onRenderTracked 和 onRenderTriggered

onRenderTrackedonRenderTriggered是兩個生命周期鉤子,它們與Vue的響應式系統和編譯器有關。這兩個鉤子是在Vue
3.x版本中引入的,主要用於調試目的,幫助開發者瞭解組件渲染過程中的跟蹤和觸發情況。

  1. onRenderTracked鉤子:

    • 當組件的響應式依賴項被追蹤時,即響應式系統開始跟蹤一個依賴項時,這個鉤子會被調用。
    • 它主要用於調試,可以幫助開發者瞭解何時響應式系統開始關註某個依賴項。
    • onRenderTracked鉤子接收兩個參數:depcontextdep是依賴項對象,context是當前組件的上下文對象。
  2. onRenderTriggered鉤子:

    • 當組件的響應式依賴項被觸發時,即響應式系統因為某個依賴項的變化而觸發了重新渲染時,這個鉤子會被調用。
    • 它主要用於調試,可以幫助開發者瞭解何時響應式系統因為某個依賴項的變化而重新渲染組件。
    • onRenderTriggered鉤子也接收兩個參數:depcontext,含義與onRenderTracked相同。

示例代碼:

export default {
    setup() {
        // 定義一個響應式數據
        const count = ref(0);

        // 監聽 count 的變化
        watch(count, (newValue, oldValue) => {
            console.log(`count changed from ${oldValue} to ${newValue}`);
        });

        // 使用 onRenderTracked 和 onRenderTriggered 進行調試
        onRenderTracked((dep, context) => {
            console.log(`onRenderTracked: ${dep}`);
        });

        onRenderTriggered((dep, context) => {
            console.log(`onRenderTriggered: ${dep}`);
        });

        return {
            count
        };
    }
};

在這個示例中,我們定義了一個響應式數據count,並使用了watch來監聽它的變化。同時,我們使用了onRenderTracked
onRenderTriggered來列印調試信息。當響應式系統開始跟蹤或觸發重新渲染時,我們會得到相應的提示。這些鉤子可以幫助開發者更好地理解Vue組件的渲染過程和響應式系統的運作。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MySQL語句優化包括創建合適的索引、使用覆蓋索引、避免不必要的子查詢、通過 EXPLAIN 分析查詢計劃、進行批量操作、減少鎖定範圍、使用預編譯語句和查詢緩存,以顯著提高查詢性能和資料庫運行效率。 ...
  • 恭喜Apache SeaTunnel社區又迎來一位PMC Member@liugddx!在社區持續活躍的兩年間,大家經常看到這位開源愛好者出現在社區的各種活動中,為項目和社區發展添磚加瓦。如今成為項目PMC Member,意味著在社區中的責任更重了,他有什麼感想呢?對於社區未來的發展,他希望從哪些角 ...
  • 轉載自劉茫茫看山 問題背景 某天我們的租戶反饋資料庫連接缺少必要的驅動,我們通過日誌查看確實是缺少部分資料庫的驅動,因為DolphinScheduler預設只帶了Oracle和MySQL的驅動,並且需要將pom文件中的test模式去掉才可以在打包的時候引入。我們的任務量比較大,在3.0存在容錯機制的 ...
  • 參數介紹: MySQL社區版MySQL 5.7.8開始,新增了MAX_EXECUTION_TIME這個系統變數,它用來限制SQL語句的執行時間,確切來說是限制只讀SELECT語句。如果查詢語句的執行時長超過這個閾值,MySQL將自動停止該SQL語句的執行。如果其值為 0,表示不啟用該超時限制功能。該 ...
  • 前言 前端函數和應用側函數相互調用是指前端頁面中的JavaScript函數和應用程式側的函數之間進行相互調用。 在前端開發中,常常會使用JavaScript函數來處理用戶的交互事件和操作。這些函數可以在前端頁面中定義,例如通過事件監聽器或者按鈕點擊事件來觸發函數的執行。這些前端函數可以使用DOM ...
  • 前言 Web是一種基於互聯網的技術和資源的網路服務系統。它是指由許多互連的電腦組成的全球性電腦網路,使用戶能夠通過瀏覽器訪問和互動式使用各種信息和資源,如網頁、文檔、圖片、視頻、音頻等。通過Web,用戶可以瀏覽網頁、發送電子郵件、參與線上社交網路、進行線上購物等各種活動。Web的核心技術包括 ...
  • 在 recyclerview 中,想要無論滑動到哪,每次按遙控器落焦,需要落焦在左側第一個 item 上面,如果不能觸屏還好,觸屏會導致焦點丟失 根據系統的反饋,如果你滑動了列表,剛好列表的 item 卡在一半的位置,此時系統的落焦規則,不一定會到第一個 之前試過一個效果一般的方案,就是通過 fin ...
  • 在上一篇電腦啟動過程文章中介紹了電腦啟動的基本流程,本篇文章主要介紹Linux內核Kernel的啟動過程。 一、內核啟動的基本流程 sequenceDiagram participant Bootloader participant Kernel participant InitProcess ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...