Vue 入門到實戰 八

8章 組合API與響應性

目錄

8.1 響應性

8.1.1 什么是響應性

8.1.2 響應性原理

8.2 為什么使用組合API

8.3 setup組件選項

8.3.1 setup函數的參數

8.3.2 setup函數的返回值

8.3.3 使用ref創建響應式引用

8.3.4 setup內部調用生命周期鉤子函數

8.4 提供/注入

8.4.1 provide方法

8.4.2 inject方法

8.5 模板引用

8.6 響應式計算與偵聽

8.6.1 響應式計算

8.6.2 響應式偵聽


8.1 響應性

8.1.1 什么是響應性

響應性是一種允許我們以聲明式的方式去適應變化的一種編程范例。Vue.js如何追蹤數據的變化呢?在生成Vue.js實例時,使用帶有gettersetter的處理程序遍歷傳入的data,將其所有property轉換為Proxy對象。Proxy代理對象,顧名思義,在訪問對象前增加一個中間層,通過中間層做一個中轉,通過操作代理對象,實現目標對象的修改。Proxy對象對于用戶來說是不可見的,但在內部,它使Vue.js能夠在property值被訪問或修改的情況下進行依賴跟蹤和變更通知。

8-1】property轉換為Proxy對象。

<script>const data = {uname: 'chenheng',age: 90}const handler = {get(target, name, receiver) {alert('執行get方法')//Reflect.get 方法查找并返回 target 對象的 name 屬性,如果沒有該屬性,則返回 undefinedreturn Reflect.get(...arguments)},set(target, name, value, receiver) {alert('執行set方法')//Reflect.set 方法設置 target 對象的 name 屬性等于 value。return Reflect.set(...arguments)}}const proxy = new Proxy(data, handler)alert(proxy.uname)    //執行get方法proxy.uname = 'hhhhh' //執行set方法alert(proxy.uname)    //執行get方法
</script>

target

要包裝的目標對象Proxy。它可以是任何類型的對象,包括本機數組,函數甚至其他代理

handler

一個對象,其屬性是定義對代理p執行操作時的行為的函數

proxy監聽數組

?proxy可以監聽屬性的新增刪除操作

proxy監聽深層次嵌套對象

8.1.2 響應性原理

reactive()方法和watchEffect()方法是Vue3中響應式的兩個核心方法,reactive()方法負責將數據變成響應式代理對象,watchEffect()方法的作用是監聽數據變化去更新視圖或調用函數。

8-2】reactive()方法和watchEffect()方法的應用。

8.2 為什么使用組合API

通過創建Vue.js組件,可以將接口的可重復部分及其功能提取到可重用的代碼段中,從而使應用程序可維護且靈活。然而,當應用程序非常復雜(成百上千組件)時,再使用組件的選項(datacomputedmethodswatch)組織邏輯,可能導致組件難以閱讀和理解。如果能夠將與同一個邏輯相關的代碼配置在一起將有效解決邏輯復雜、可讀性差等問題。這正是使用組合API的目的。

8.3 setup組件選項

Vue組件提供setup選項,供開發者使用組合APIsetup選項在創建組件前執行,一旦props被解析,便充當組合式API的入口點。由于在執行setup時尚未創建組件實例,因此在setup選項中沒有this。這意味著,除了props之外,無法訪問組件中聲明的任何屬性,包括本地狀態、計算屬性或方法。

setup選項是一個接受propscontext參數的函數。此外,從setup返回的所有內容都將暴露給組件的其余部分(計算屬性、方法、生命周期鉤子、模板等等)。

8.3.1 setup函數的參數

1setup函數中的第一個參數(props

setup函數中的props是響應式的,當傳入新的屬性時,它將被更新。

8-3】setup函數中,參數props是響應式的。

但是,因為props是響應式的,不能使用ES6解構,將會消除props的響應性。如果需要解構props,可以在setup函數中使用toRefs函數來完成此操作。

8-4】setup函數中,使用toRefs函數創建props屬性的響應式引用。

toRef是把對象的某個屬性改成響應式的數據,toRefs是把整個對象改成響應式數據

2setup函數中的第二個參數(context

context上下文是一個普通的JavaScript對象,它暴露組件的4個屬性:attrsslotsemit以及expose

setup(props, context) {

??? // Attribute (非響應式對象,等同于 $attrs)

??? console.log(context.attrs)可以獲取父組件的傳遞歸來的參數hobby,但是一定需要注釋props

??? // 插槽 (非響應式對象,等同于 $slots)

??? console.log(context.slots)

??? // 觸發事件 (方法,等同于 $emit)

?

?home.vue

<template><Demo @zemit="showemit"></Demo>
</template><script>
import Demo from "@/components/demo.vue";
export default {components: {Demo,},setup() {function showemit(val) {alert(`觸發context.emit事件,收到參數是:${val}`);}return {showemit,};},
};
</script>

?demo.vue

<template><p>個人信息</p><p>姓名:{{ person.name }}</p><p>年齡:{{ person.age }}</p><button @click="zevent">zemit事件</button>
</template><script>
import { reactive } from "vue";
export default {name: "Home12",emits: ["zemit"],setup(props, context) {console.log("1", props);// console.log("context.attrs", context.attrs);console.log("context.attrs", context.emit);const person = reactive({name: "劉巍",age: 18,});function zevent() {context.emit("zemit", '南昌大學');}return {  person,zevent,};},
};
</script>

?

8.3.2 setup函數的返回值

1)對象

如果setup返回一個對象,則可以在組件的模板中訪問該對象的屬性。

8-5】在該實例中,setup函數返回一個對象。

<template><h1>一個人的信息</h1><h3>職業:{{ job.type }}</h3><h3>薪水:{{ job.salary }}</h3><h3>愛好:{{ hobby }}</h3><h3>測試數據的值:{{ job.a.b.c }}</h3><button @click="changeInfo">修改人的信息</button>
</template><script>
import {reactive} from 'vue'export default {name: 'App',setup() {//數據let job = reactive({type: 'SAP工程師',salary: '60k',a: {b: {c: 666}}})let hobby = reactive(['籃球', '說泡', '旅游'])//counts changeInfo = ()=>{...}function changeInfo() {job.type = "管理咨詢顧問"job.salary = "100k"job.a.b.c = 999hobby[0] = '學習'}return {job,hobby,changeInfo}}
}
</script>

2)渲染函數

setup還可以返回一個渲染函數,該函數可以直接使用在同一作用域中聲明的響應式狀態。

8-6】實現8-5】的功能,要求setup返回渲染函數。

8.3.3 使用ref創建響應式引用

1.聲明響應式狀態

要為JavaScript對象創建響應式狀態,可以使用reactive()方法。reactive()方法接收一個普通對象然后返回該對象的響應式代理。示例代碼如下:

const book = Vue.reactive({ title: '好書' })

reactive()方法響應式轉換是“深層的”即影響對象內部所有嵌套的屬性。基于ESProxy實現,返回的代理對象不等于原始對象。建議使用代理對象,避免依賴原始對象。

2.使用ref創建獨立的響應式值對象

ref接受一個參數值并返回一個響應式且可改變的ref對象。ref對象擁有一個指向內部值的單一屬性.value。示例代碼如下:

const readersNumber = Vue.ref(1000)

console.log(readersNumber.value) //1000

readersNumber.value++

console.log(readersNumber.value) // 1001

ref作為渲染上下文的屬性返回(即在setup()返回的對象中)并在模板中使用時,它會自動開箱,無需在模板內額外書寫.value

8.3.4 setup內部調用生命周期鉤子函數

setup內部,可通過在生命周期鉤子函數前面加上“on來訪問組件的生命周期鉤子函數。因為setup是圍繞beforeCreatecreated生命周期鉤子函數運行的,所以不需要顯式地定義它們。換句話說,在這些鉤子函數中編寫的任何代碼都應該直接在setup函數中編寫。這些on函數接受一個回調函數,當鉤子函數被組件調用時將會被執行。示例代碼如下:

setup() {

?// mounted時執行

?onMounted(() => {

? console.log('Component is mounted!')

? })

}

8.4 提供/注入

通過4.3.4節可知,使用provideinject可實現組件鏈傳值。也就是說,父組件可以作為其所有子組件的依賴項提供程序,而不管組件層次結構有多深,父組件有一個provide選項來提供數據,子組件有一個inject選項來使用這個數據。(跨組件的數據傳遞)

現在,在組合API中,也可以使用provide方法和inject方法實現傳值,但兩者都只能在當前活動實例的setup()期間調用。

8.4.1 provide方法

首先,從vue顯式導入provide方法;然后,在setup()中使用provide方法定義每個property

provide方法有兩個參數:

l? name:代表字符串類型的屬性名稱;

l? value:代表任意類型的屬性值。

8.4.2 inject方法

首先,從vue顯式導入inject方法;然后,在setup()中使用inject方法注入每個property值。

inject方法有兩個參數:

l? name:被注入的屬性名稱(字符串類型);

l? defaultValue:默認值(可選)。

假設我們有一個祖先組件?app,一個中間組件?one,以及一個后代組件?two。我們希望從?app傳遞一個數據到?two

app.vue

<template><one></one>
</template><script setup>
// import HelloWorld from './components/HelloWorld.vue'
// import setup from './components/setup.vue'
// import setup1 from './components/setup1.vue'
import one from './components/one.vue'
import { provide } from 'vue';
const hcm = 'payroll';
provide('sap', hcm)
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
</style>

?one.vue

<template><two/>
</template><script setup>
import two from '../components/two.vue';
</script>

two.vue

<template><div :class="theme">我是SAP {{ theme }} 顧問.</div>
</template><script setup>
import { inject } from 'vue';const theme = inject('sap', 'time'); // 'time' 是默認值,如果 provide 沒有提供 'theme'
</script><style scoped>
.dark {background-color: black;color: white;
}.light {background-color: white;color: black;
}
</style>

8.5 模板引用

在使用組合API時,響應式引用和模板引用的概念是統一的。為了獲得對模板內元素或組件實例的引用,可以聲明一個ref并從setup()返回。

8-8】在模板中使用ref引用響應式對象。

8.6 響應式計算與偵聽

8.6.1 響應式計算

使用響應式計算方法computed有兩種方式:傳入一個getter函數,返回一個默認不可手動修改的ref對象;傳入一個擁有getset函數的對象,創建一個可手動修改的計算狀態。

8-9】返回一個默認不可手動修改的ref對象。

<template><div>{{count}}</div>
</template><script>
import{ref,computed} from 'vue';export default {setup() {const count = ref(1)const account = computed(()=> count.value + 1)console.log(account.value)account.value++// 返回值會暴露給模板和其他的選項式 API 鉤子return {count}}
}
</script>

8-10】返回一個可手動修改的ref對象。

<template><div>{{count}}</div>
</template><script>
import{ref,computed} from 'vue';export default {setup() {const count = ref(1)const account = computed({get:()=> count.value + 1,set:(val)=> {count.value = val - 1},} )account.value = 1console.log(count.value)return {count}}
}
</script>

8.6.2 響應式偵聽

可使用響應性偵聽watchEffect方法,對響應性進行偵聽。該方法立即執行傳入的一個函數,同時響應式追蹤其依賴,并在其依賴變更時重新運行該函數。(監聽所有屬性)

8-11】響應性偵聽watchEffect方法的使用。

監聽屬性變化

<template><div><input type="text" v-model="obj.name"> </div>
</template><script>
import{reactive,watchEffect} from 'vue';export default {setup() {let obj = reactive({name:'vivi'});watchEffect(()=>{console.log('name:',obj.name)})return {obj}}
}
</script>

停止監聽

<template><div><input type="text" v-model="obj.name"> <button @click="stopWatchEffect">停止監聽</button></div>
</template><script>
import{reactive,watchEffect} from 'vue';export default {setup() {let obj = reactive({name:'vivi'});const stop1 =  watchEffect(()=>{console.log('name',obj.name)})const stopWatchEffect = ()=>{console.log('停止監聽')stop1(); // ...當該偵聽器不再需要時}return {obj,stopWatchEffect,}}
}
</script>

副作用

使用 onInvalidate 清理計時器,每次 count 變化時,watchEffect 會重新執行,在此之前?onInvalidate 會先清理掉之前的計時器,避免重復創建計時器導致內存泄漏。

注意:如果在?watchEffect 沒有直接使用?count.value ,那么它的變化就不會觸發副作用函數重新執行,從而不會調用?onInvalidate 清理之前的計時器

<template><div><p>當前計數: {{ count }}</p><button @click="count++">增加計數</button></div>
</template>
<script>
import { ref, watchEffect } from 'vue';
export default {setup() {const count = ref(0);watchEffect((onInvalidate) => {// 在函數內直接讀取 count.value,確保它被追蹤,這一步很重要!!!console.log(`副作用函數執行,count 值為: ${count.value}`);const timer = setInterval(() => {console.log(`計時器中 count 的值: ${count.value}`);}, 1000);onInvalidate(() => {console.log('清除計時器 timer');clearInterval(timer);});});return {count,};},
};
</script>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/69229.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/69229.shtml
英文地址,請注明出處:http://en.pswp.cn/web/69229.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java使用aspose實現pdf轉word

Java使用aspose實現pdf轉word 一、下載aspose-pdf-21.6.jar包【下載地址】&#xff0c;存放目錄結構如圖&#xff1b;配置pom.xml。 <!--pdf to word--> <dependency><groupId>com.aspose</groupId><artifactId>aspose-pdf</artifactId>…

使用Node.js搭配express框架快速構建后端業務接口模塊Demo

使用Node.js搭配express框架快速構建后端業務接口模塊Demo&#xff01;實際開發中&#xff0c;有很多項目&#xff0c;其實都是可以使用node.js來完成對接mysql數據庫的&#xff0c;express確實使用起來非常簡單&#xff0c;入手快&#xff0c;效率非常高。下面是一個簡單的案例…

Python----Python高級(并發編程:協程Coroutines,事件循環,Task對象,協程間通信,協程同步,將協程分布到線程池/進程池中)

一、協程 1.1、協程 協程&#xff0c;Coroutines&#xff0c;也叫作纖程(Fiber) 協程&#xff0c;全稱是“協同程序”&#xff0c;用來實現任務協作。是一種在線程中&#xff0c;比線程更加輕量級的存在&#xff0c;由程序員自己寫程序來管理。 當出現IO阻塞時&#xff0c;…

Unity 加載OSGB(webgl直接加載,無需轉換格式!)

Unity webgl加載傾斜攝影數據 前言效果圖后續不足 前言 Unity加載傾斜攝影數據&#xff0c;有很多的插件方便好用&#xff0c;但是發布到網頁端均失敗&#xff0c;因為webgl 的限制&#xff0c;IO讀取失效。 前不久發現一個開源項目: UnityOSGB-main 通過兩種方式在 Unity 中…

【Block總結】PSA,金字塔擠壓注意力,解決傳統注意力機制在捕獲多尺度特征時的局限性

論文信息 標題: EPSANet: An Efficient Pyramid Squeeze Attention Block on Convolutional Neural Network論文鏈接: arXivGitHub鏈接: https://github.com/murufeng/EPSANet 創新點 EPSANet提出了一種新穎的金字塔擠壓注意力&#xff08;PSA&#xff09;模塊&#xff0c;旨…

【重新認識C語言----結構體篇】

目錄 -----------------------------------------begin------------------------------------- 引言 1. 結構體的基本概念 1.1 為什么需要結構體&#xff1f; 1.2 結構體的定義 2. 結構體變量的聲明與初始化 2.1 聲明結構體變量 2.2 初始化結構體變量 3. 結構體成員的訪…

如何在Vscode中接入Deepseek

一、獲取Deepseek APIKEY 首先&#xff0c;登錄Deepseek官網的開放平臺&#xff1a;DeepSeek 選擇API開放平臺&#xff0c;然后登錄Deepseek后臺。 點擊左側菜單欄“API keys”&#xff0c;并創建API key。 需要注意的是&#xff0c;生成API key復制保存到本地&#xff0c;丟失…

電腦開機提示按f1原因分析及終極解決方法來了

經常有網友問到一個問題&#xff0c;我電腦開機后提示按f1怎么解決&#xff1f;不管理是臺式電腦&#xff0c;還是筆記本&#xff0c;都有可能會遇到開機需要按F1&#xff0c;才能進入系統的問題&#xff0c;引起這個問題的原因比較多&#xff0c;今天小編在這里給大家列舉了比…

AI協助探索AI新構型自動化創新的技術實現

一、AI自進化架構的核心范式 1. 元代碼生成與模塊化重構 - 代碼級自編程&#xff1a;基于神經架構搜索的強化學習框架&#xff0c;AI可通過生成元代碼模板&#xff08;框架的抽象層定義、神經元結點-網絡拓撲態的編碼抽象定義&#xff09;自動組合功能模塊。例如&#xff0…

RAID獨立硬盤冗余陣列

目錄 一、RAID基本功能 二、RAID常見級別 三、實現方式 1、軟件磁盤陣列 2、硬件磁盤陣列 四、熱備盤 RAID&#xff08;Redundant Array of Independent Disks&#xff09;是一種通過將多個硬盤組合成一個邏輯單元來提升存儲性能、冗余性或兩者兼具的技術。 一、RAID基本…

【高級篇 / IPv6】(7.2) ? 04. 在60E上配置ADSL撥號寬帶上網(IPv4) ? FortiGate 防火墻

【簡介】除了單位用戶以外&#xff0c;大部分個人用戶目前使用的仍然是30E、50E、60E系列防火墻&#xff0c;固件無法達到目前最高版本7.6&#xff0c;這里以最常用的60E為例&#xff0c;演示固件版本7.2下實現ADSL撥號寬帶的IPv6上網。由于內容比較多&#xff0c;文章分上、下…

Qt之設置QToolBar上的按鈕樣式

通常給QAction設置icon后,菜單欄的菜單項和工具欄(QToolBar)上對應的按鈕會同時顯示該icon。工具欄還可以使用setToolButtonStyle函數設置按鈕樣式,其參數為枚舉值: enum ToolButtonStyle {ToolButtonIconOnly,ToolButtonTextOnly,ToolButtonTextBesideIcon,ToolButtonTe…

【從零開始系列】DeepSeek-R1:(本地部署使用)思維鏈推理大模型,開源的神!——Windows/Linux本地環境測試 + vLLM遠程部署服務

目錄 一、環境配置 1.硬件設備評估 2.基礎環境安裝 3.模型參數下載 (1) huggingface鏡像源下載 (2) modelscope魔搭社區下載 &#xff08;推薦&#xff09; 二、基礎使用&#xff08;Linux、Window兼容&#xff09; 1.Transformers庫自編代碼 三、進階使用&#xff08;僅Lin…

DeepSeek 開源模型全解析(2024.1.1–2025.2.6)

目錄 一、通用大語言模型&#xff1a;DeepSeek-V3 系列 137 二、推理優化模型&#xff1a;DeepSeek-R1 系列 811 三、多模態模型&#xff1a;Janus 系列 10 四、生態整合與部署建議 五、總結與展望 以下為 DeepSeek 在 2024 年 1 月至 2025 年 2 月期間發布的開源模型及其…

Mac: docker安裝以后報錯Command not found: docker

文章目錄 前言解決辦法&#xff08;新的&#xff09;解決步驟&#xff08;原來的&#xff09;不推薦總結 前言 ?本操作參考 http://blog.csdn.net/enhenglhm/article/details/137955756 原作者&#xff0c;更詳細請&#xff0c;查看詳細內容請關注原作者。 一般&#xff0c;…

《手札·開源篇》數字化轉型助力永磁電機企業降本增效:快速設計軟件如何讓研發效率提升40%?

數字化轉型助力永磁電機企業降本增效&#xff1a;快速設計軟件如何讓研發效率提升40%&#xff1f; 一、痛點&#xff1a;傳統研發模式正在吃掉企業的利潤 永磁電機行業面臨兩大挑戰&#xff1a; 研發周期長&#xff1a;一款新電機從設計到量產需6-12個月&#xff0c;電磁計算…

0207作業

思維導圖 服務器 enum Type{TYPE_REGIST,TYPE_LOGIN };typedef struct Pack{int size;enum Type type;char buf[2048];}pack_t;typedef struct list{union Data{struct List* tail;char str[64];}data;struct List* next;struct List* prev; }List;List* create_node(){List* …

深入淺出 DeepSeek V2 高效的MoE語言模型

今天&#xff0c;我們來聊聊 DeepSeek V2 高效的 MoE 語言模型&#xff0c;帶大家一起深入理解這篇論文的精髓&#xff0c;同時&#xff0c;告訴大家如何將這些概念應用到實際中。 &#x1f31f; 什么是 MoE&#xff1f;——Mixture of Experts&#xff08;專家混合模型&#x…

RabbitMQ 從入門到精通:從工作模式到集群部署實戰(五)

#作者&#xff1a;閆乾苓 系列前幾篇&#xff1a; 《RabbitMQ 從入門到精通&#xff1a;從工作模式到集群部署實戰&#xff08;一&#xff09;》&#xff1a;link 《RabbitMQ 從入門到精通&#xff1a;從工作模式到集群部署實戰&#xff08;二&#xff09;》&#xff1a; lin…

nodejs:express + js-mdict 網頁查詢英漢詞典,能播放.spx 聲音

向 DeepSeek R1 提問&#xff1a; 我想寫一個Web 前端網頁&#xff0c;后臺用 nodejs js-mdict , 實現在線查詢英語單詞&#xff0c;并能播放.spx 聲音文件 1. 項目結構 首先&#xff0c;創建一個項目目錄&#xff0c;結構如下&#xff1a; mydict-app/ ├── public/ │ …