主頁 > 企業開發 > vue3組合式API介紹

vue3組合式API介紹

2023-04-23 07:50:45 企業開發

為什么要使用Composition API?

根據官方的說法,vue3.0的變化包括性能上的改進、更小的 bundle 體積、對 TypeScript 更好的支持、用于處理大規模用例的全新 API,全新的api指的就是本文主要要說的組合式api,

在 vue3 版本之前,我們復用組件(或者提取和重用多個組件之間的邏輯),通常有以下幾種方式:

  • Mixin:命名空間沖突 & 渲染背景關系中暴露的 property 來源不清晰,例如在閱讀一個運用了多個 mixin 的模板時,很難看出某個 property 是從哪一個 mixin 中注入的,
  • Renderless Component:無渲染組件需要額外的有狀態的組件實體,從而使得性能有所損耗
  • Vuex:就會變得更加復雜,需要去定義 Mutations 也需要去定義 Actions

上述提到的幾種方式,也是我們專案中正在使用的方式,對于提取和重用多個組件之間的邏輯似乎并不簡單,我們甚至采用了 extend 來做到最大化利用已有組件邏輯,因此使得代碼邏輯依賴嚴重,難以閱讀和理解,
Vue3 中的 Composition API 便是解決這一問題;且完美支持型別推導,不再是依靠一個簡單的 this 背景關系來暴露 property(比如 methods 選項下的函式的 this 是指向組件實體的,而不是這個 methods 物件),其是一組低侵入式的、函式式的 API,使得我們能夠更靈活地「組合」組件的邏輯,

業務實踐

組合式api的出現就能解決以上兩個問題,此外,它也對TypeScript型別推導更加友好,
在具體使用上,對vue單檔案來說,模板部分和樣式部分基本和以前沒有區別,組合式api主要影響的是邏輯部分,下面是一個經典的vue2的計數器案例.:

vue2 實作

//Counter.vue
export default {
  data: () => ({
    count: 0
  }),
  methods: {
    increment() {
      this.count++;
    }
  },
  computed: {
    double () {
      return this.count * 2;
    }
  }
}

vue3 composition api

當我們在組件間提取并復用邏輯時,組合式API 是十分靈活的,一個組合函式僅依賴它的引數和 Vue 全域匯出的 API,而不是依賴其微妙的 this 背景關系,你可以將組件內的任何一段邏輯匯出為函式以復用它,

  • 基于回應式
  • 提供 vue 的生命周期鉤子
  • 組件銷毀時自動銷毀依賴監聽
  • 可復用的邏輯
// Counter.vue
import { ref, computed } from "vue";

export default {
  setup() {
    const count = ref(0);
    const double = computed(() => count * 2)
    function increment() {
      count.value++;
    }
    return {
      count,
      double,
      increment
    }
  }
}

代碼提取

Composition API的第一個明顯優點是提取邏輯很容易,使用Composition提取上面Counter.vue組件代碼,

//useCounter.js 組合函式
import { ref, computed } from "vue";

export default function () {
  const count = ref(0);
  const double = computed(() => count * 2)
  function increment() {
    count.value++;
  }
  return {
    count,
    double,
    increment
  }
}

代碼重用

要在組件中使用該函式,我們只需將模塊匯入組件檔案并呼叫它(注意匯入是一個函式),這將回傳我們定義的變數,隨后我們可以從 setup 函式中回傳它們,

// MyComponent.js
import useCounter from "./useCounter.js";

export default {
  setup() {
    const { count, double, increment } = useCounter();
    return {
      count,
      double,
      increment
    }
  }
} 

相比而言,組合式 API:

  • 暴露給模板的 property 來源十分清晰,因為它們都是被組合邏輯函式回傳的值
  • 不存在命名空間沖突,可以通過解構任意命名
  • 不再需要僅為邏輯復用而創建新的組件實體


3107124351-5f184be9e39f2_fix732.png

常用api介紹

setup

export default {
  setup(props, context) {
    console.log(context); // { attrs, slots, emit }
    //context.emit('emitFun', {emit: true})
    return { privateMsg: props.msg };
  }
}

setup函式是組件內使用 component API 的入口,是在組件實體被創建時, 初始化了 props 之后呼叫,處于 created 前,還有以下特點:
1.可以回傳一個物件或函式,物件的屬性會合并到模板渲染的背景關系中;
2.第一個引數是回應式的props物件,注意不能解構 props 物件,會使其失去回應性, **
也不可直接修改 props,會觸發警告
3.第二個引數是一個背景關系物件,暴露了 attrs,slots,emit 物件
4.
this 在 setup 函式中不可用,**因為它不會找到組件實體,setup 的呼叫發生在 data、computed 和 methods 被決議之前,所以它們無法在 setup 中被獲取,

props與背景關系物件attrs的區別:
1、props 要先宣告才能取值,attrs 不用先宣告
2、props 宣告過的屬性,attrs 里不會再出現
3、props 不包含事件,attrs 包含,vue2中的$listeners 被整合到 $attrs

reactive

<template>
  <div>
    <p>{{data.msg}}</p>
    <button @click="updateData">更新資料</button>
  </div>
</template>

<script>
import { reactive } from "vue";

export default {
  name: "ReactiveObject",
  setup() {
    const data = https://www.cnblogs.com/huangchengpei/archive/2023/04/22/reactive({ msg:"hello world" });
    const updateData = https://www.cnblogs.com/huangchengpei/archive/2023/04/22/() => {
      data.msg="hello world " + new Date().getTime();
    };
    return { data, updateData };
  },
};
</script>

reactive函式接收一個普通物件然后回傳物件的回應式代理,同 Vue.observable,
原理:通過proxy對資料進行封裝,當資料變化時,觸發模板等內容的更新,

ref

<template>
  <div>
    <p>{{msg}}</p>
    <button @click="updateMessage">更新資料</button>
  </div>
</template>

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

export default {
  name: "ReactiveSingleValue",
  setup() {
    const msg= ref("hello world");
    const updateMessage = () => {
      msg.value = "https://www.cnblogs.com/huangchengpei/archive/2023/04/22/hello world" + new Date().getTime();
    };
    return { msg, updateMessage };
  },
};
</script>

ref和reactive存在一定的相似性,所以需要完全理解它們才能高效的在各種場景下選擇不同的方式,它們之間最明顯的區別是ref使用的時候需要通過.value來取值,reactive不用,ref是property而reactive是proxy,reactive能夠深度監聽各種型別物件的變化,ref是處理諸如number,string之類的基本資料型別,
它們的區別也可以這么理解,ref是使某一個資料提供回應能力,而reactive是為包含該資料的一整個物件提供回應能力,
在模板里使用ref和嵌套在回應式物件里時不需要通過.value,會自己解開:

除了回應式ref還有一個參考DOM元素的ref,2.x里面是通過this.$refs.xxx來參考,但是在setup里面沒有this,所以也是通過創建一個ref來使用:

<template>
    <div ref="node"></div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
    setup() {
        const node = ref(null)
        onMounted(() => {
            console.log(node.value)  // 此處就是dom元素 <div ref="node"></div>
        })
        return {
            node
        }
    }
}
</script>

computed

傳入一個 getter 函式,回傳一個默認不可修改的 ref 物件,同 vue 2.x 中的計算屬性 computed

const count = ref(0)
const sum = computed(() => count.value + 1)
console.log(sum.value) // 1
sum.value = https://www.cnblogs.com/huangchengpei/archive/2023/04/22/3 // 錯誤

也可傳入一個 get 和 set 函式物件,創建一個可修改的計算狀態

const count = ref(0)

const sum = computed({
  get: () => count.value + 1,
  set: (value) => {
    count.value = https://www.cnblogs.com/huangchengpei/archive/2023/04/22/value - 1
  }
})

sum.value = 55
console.log(sum, count) // 1, 54

watchEffect

import { reactive, watchEffect } from "vue";
export default {
  name: "WatchEffect",
  setup() {
    const data = https://www.cnblogs.com/huangchengpei/archive/2023/04/22/reactive({ count: 1 });
    watchEffect(() => console.log(`偵聽器:${data.count}`));
    setInterval(() => {
      data.count++;
    }, 1000);
    return { data };
  },
};

watchEffect用來監聽資料的變化,它會立即執行一次,之后會追蹤函式里面用到的所有回應式狀態,當變化后會重新執行該回呼函式,

watch

完全等效于 2.x 中 watch 選項,對比 watchEffect,watch 允許我們:

  • 懶執行副作用;
  • 更明確哪些狀態的改變會觸發偵聽器重新運行副作用;
  • 訪問偵聽狀態變化前后的值,
// 監聽一個 getter
const state = reactive({ count: 0 })
watch(
  () => state.count,
  (count, prevCount) => {
    console.log(count, prevCount)
  }
)

// 直接監聽一個 ref
const count = ref(0)
watch(count, (count, prevCount) => {
  console.log(count, prevCount)
}, {
  deep: true, // 深度監聽
  immediate: true // 初始化執行一次
})

// 監聽多個資料
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
  console.log([foo, bar], [prevFoo, prevBar])
})

toRefs

把一個回應式物件轉換成普通物件,該普通物件的每個 property 都是一個 ref,和回應式物件 property 一一對應,可以被解構且保持回應性

<template>
  <div>
    <h1>解構回應式物件資料</h1>
    <p>Username: {{username}}</p>
    <p>Age: {{age}}</p>
  </div>
</template>

<script>
import { reactive, toRefs } from "vue";
export default {
  name: "DestructReactiveObject",
  setup() {
    const user = reactive({
      username: "haihong",
      age: 10000,
    });
    return { ...toRefs(user) };
  },
};
</script>

toRef

toRef 可以用來為一個 reactive 物件的屬性創建一個 ref,這個 ref 可以被傳遞并且能夠保持回應性,

setup() {
  const user = reactive({ age: 1 });
  const age = toRef(user, "age");

  age.value++;
  console.log(user.age); // 2

  user.age++;
  console.log(age.value); // 3
}

Provide/Inject

為了增加 provide 值和 inject 值之間的回應性,我們可以在 provide 值時使用 ref 或 reactive,
當使用回應式 provide / inject 值時,建議盡可能將對回應式 property 的所有修改限制在定義 provide 的組件內部,然而,有時我們需要在注入資料的組件內部更新 inject 的資料,在這種情況下,我們建議 provide 一個方法來負責改變回應式 property,
最后,如果要確保通過 provide 傳遞的資料不會被 inject 的組件更改,我們建議對提供者的 property 使用 readonly,

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, readonly, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'https://www.cnblogs.com/huangchengpei/archive/2023/04/22/South Pole'
    }

    provide('location', readonly(location))
    provide('geolocation', readonly(geolocation))
    provide('updateLocation', updateLocation)
  }
}
</script>
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')
    const updateUserLocation = inject('updateLocation')

    return {
      userLocation,
      userGeolocation,
      updateUserLocation
    }
  }
}
</script>

生命周期函式

與 2.x 版本生命周期相對應的組合式 API
~~beforeCreate~~ -> 使用 setup()
~~created~~ -> 使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> one rrorCaptured

只需要將之前的生命周期改成onXXX的形式即可,需要注意的是created、beforeCreate兩個鉤子被洗掉了,生命周期函式只能在setup函式里使用,

總結

使用組合式api還是需要一點時間來適應的,首先需要能區分ref和reactive,不要在基本型別和參考型別、回應式和非回應式物件之間搞混,其次就是如何拆分好每一個use函式,組合式api帶來了更好的代碼組織方式,但也更容易把代碼寫的更難以維護,比如setup函式巨長,

簡單總結一下升級思路,data選項里的資料通過reactive進行宣告,通過...toRefs()回傳;computed、mounted等選項通過對應的computed、onMounted等函式來進行替換;methods里的函式隨便在哪宣告,只要在setup函式里回傳即可,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/550895.html

標籤:其他

上一篇:線上多域名實戰

下一篇:返回列表

標籤雲
其他(157886) Python(38092) JavaScript(25383) Java(17985) C(15215) 區塊鏈(8258) C#(7972) AI(7469) 爪哇(7425) MySQL(7137) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4557) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2430) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1959) Web開發(1951) HtmlCss(1921) python-3.x(1918) 弹簧靴(1913) C++(1910) xml(1889) PostgreSQL(1872) .NETCore(1854) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • vue3組合式API介紹

    為什么要使用Composition API? 根據官方的說法,vue3.0的變化包括性能上的改進、更小的 bundle 體積、對 TypeScript 更好的支持、用于處理大規模用例的全新 API,全新的api指的就是本文主要要說的組合式api。 在 vue3 版本之前,我們復用組件(或者提取和重用 ......

    uj5u.com 2023-04-23 07:50:45 more
  • 線上多域名實戰

    本文博主給大家分享線上多域名實戰,當線上主域名不可用的情況下,啟用備用域名完成網站高可用保障。 網站的高可用性一直是網站運維的重中之重。一旦網站宕機,不僅會造成巨大的經濟損失,也會嚴重影響用戶體驗。備份域名就是一種實作網站高可用的重要手段。通過備份域名,可以在主域名不可訪問時快速切換域名,保證網站正 ......

    uj5u.com 2023-04-23 07:50:00 more
  • Vue基礎知識

    模板語法 文本插值(text interpolation) 最基本的資料系結形式,使用“Mustache”語法即{{...}} <span>Message:{{msg}}</span> {{}}中的值會被替換為相應組件實體中msg屬性的值,且會同步地更新 原始HTML <p>Message:<spa ......

    uj5u.com 2023-04-23 07:49:54 more
  • react18中antd的Upload組件上傳頭像,并且拿到服務器回傳的頭像的u

    業務需求:上傳頭像,上傳完畢后拿到頭像的url,把頭像展示在頁面中,最終把頭像url和其他用戶資訊一起發送給服務器 上傳頭像流程 匯入 Upload 組件和圖示(一個加號,一個加載中) import { Upload } from 'antd'; import { PlusOutlined, Loa ......

    uj5u.com 2023-04-23 07:49:45 more
  • 博客園頁面展示--前端及樣式代碼

    這是一個博客園的首頁面的展示前端代碼和樣式代碼 樣式代碼CSS采用外部鏈接,建好檔案直接復制運行vscode即可,話不多說,直接上代碼 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Mickey - 博客園</title> < ......

    uj5u.com 2023-04-23 07:49:36 more
  • 仿chatGPT或chatPDF的前端界面布局,css實作對話聊天布局代碼,回應

    chatPDF或者chatGPT的界面挺簡潔的,就是一個左側的串列以及右側的對話串列,現在使用css實作這樣的布局 充分運用了flex布局方式實作,左右分欄,以及對話形式展示效果 下面是效果圖: 在手機設備看就隱藏左側,右側100%適應 下面就是html和css的布局代碼 <style> .chat ......

    uj5u.com 2023-04-23 07:49:27 more
  • TypeScript中的實用工具型別(Utility Types)

    TypeScript中的實用工具型別是一些預定義的泛型型別,可用于操作或創建其它新型別。這些實用工具型別在所有TypeScript專案中都是全域可用的,因此無需添加任務依賴項即可使用它們。 1.Partial<Type> 將Type的所有屬性都設定為可選的型別。 1 interface Person ......

    uj5u.com 2023-04-23 07:49:13 more
  • 線上多域名實戰

    本文博主給大家分享線上多域名實戰,當線上主域名不可用的情況下,啟用備用域名完成網站高可用保障。 網站的高可用性一直是網站運維的重中之重。一旦網站宕機,不僅會造成巨大的經濟損失,也會嚴重影響用戶體驗。備份域名就是一種實作網站高可用的重要手段。通過備份域名,可以在主域名不可訪問時快速切換域名,保證網站正 ......

    uj5u.com 2023-04-23 07:48:23 more
  • 博客園頁面展示--前端及樣式代碼

    這是一個博客園的首頁面的展示前端代碼和樣式代碼 樣式代碼CSS采用外部鏈接,建好檔案直接復制運行vscode即可,話不多說,直接上代碼 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Mickey - 博客園</title> < ......

    uj5u.com 2023-04-23 07:48:00 more
  • 仿chatGPT或chatPDF的前端界面布局,css實作對話聊天布局代碼,回應

    chatPDF或者chatGPT的界面挺簡潔的,就是一個左側的串列以及右側的對話串列,現在使用css實作這樣的布局 充分運用了flex布局方式實作,左右分欄,以及對話形式展示效果 下面是效果圖: 在手機設備看就隱藏左側,右側100%適應 下面就是html和css的布局代碼 <style> .chat ......

    uj5u.com 2023-04-23 07:47:51 more