Hook:是一個函數、把setup函數中的組合api進行了封裝,類似於vue2中的mixin,
Src目錄下新建hooks資料夾 裡面寫各種邏輯的hook
在使用 reactive 建立物件後, 在模板中使用物件中的屬性, 會多次書寫 物件的名稱。可以使用這兩個api 來把要使用的 單獨定義出來
const hero = reactive({
name: 'zhangsan',
age: 23,
family: {
mather: 'dd'
}
})
const name = toRef(hero, 'name')
const namgChange = () => {
hero.name = 'lisi'
}
<h1>{{hero.name}}</h1>
<h1>{{name}}</h1>
<button @click="namgChange">
變化
</button>
上面列子中對hero.name 修改和對 name修改時同等效果的
上面toRef 一次只能處理一個屬性
toRefs 一次能處理多個屬性
import { toRefs } from "vue";
setup() {
return {
...toRefs(Hero)
}
}
操作場景 用於讀取響應式資料,後續操作不會引起頁面資料變化
將一個由reactive生成的響應式物件轉為普通物件(ref生成的不行)
標記一個物件永遠不作為響應式物件
用法 markRaw(需要標記的物件)
建立一個自定義的ref,並對其依賴項跟蹤和更新觸發進行顯式控制,customRef裡面需要寫一個函數,函數接收兩個引數,並且應該返回一個帶有 get 和 set 的物件
track () 在get中通知vue追蹤return出去的資料變化
tigger() 在set中改完資料後 通知vue重新解析模板
<template>
<input v-model="keyword" />
<h3>{{keyword}}</h3>
</template>
<script>
import { customRef } from "vue";
export default {
name: 'Testvue',
setup() {
function myref(value,time = 1000) {
let timer;
return customRef((track, tigger) => {
return {
get() {
track() // 通知vue追蹤value的變化
return value
},
set(newValue) {
clearTimeout(timer)
timer = setTimeout(() =>{
value = newValue
tigger() // 改完資料後 通知vue重新解析模板
}, time)
}
}
})
}
let keyword = myref('hello', 500)
return {
keyword
}
}
};
</script>
父元件用provide提供資料 後代元件用inject使用資料
父元件
<template>
<input v-model="keyword" />
<h3>{{keyword}}</h3>
<hellochild></hellochild>
</template>
<script>
import { customRef, provide } from "vue";
import hellochild from './hellochild.vue'
export default {
name: 'Testvue',
components: {
hellochild
},
setup() {
function myref(value,time = 1000) {
let timer;
return customRef((track, tigger) => {
return {
get() {
track() // 通知vue追蹤value的變化
return value
},
set(newValue) {
clearTimeout(timer)
timer = setTimeout(() =>{
value = newValue
tigger() // 改完資料後 通知vue重新解析模板
}, time)
}
}
})
}
let keyword = myref('hello', 500)
provide('keyword', keyword)
return {
keyword
}
}
};
</script>
子元件
<template>
<div>
我是元件件, 看下 父元件的 keyword {{keyword}}
</div>
</template>
<script setup>
import {inject} from 'vue'
let keyword = inject('keyword')
</script>
有簡寫和完整寫法之分,完整寫法考慮讀寫
// 計算屬性 簡寫 -- 單純的讀取
person.fullName = computed(() => {
return person.firstName + person.lastName
})
// 計算屬性完整寫法 --- 考慮修改
person.fullName = computed({
get() {
return person.firstName + person.lastName
},
set(value) {
const nameArr = value.split('-')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
}
})
不用指明監聽那個屬性的變化,回撥函數中用到哪個屬性,就監聽那個屬性變化
<template>
<h3>當前數值:{{ sum }}</h3>
<button @click="sum++">增加</button>
</template>
<script>
import { ref, watch } from "@vue/runtime-core";
export default {
setup() {
let sum = ref(0);
watch(
sum,
(newValue, oldValue) => {
console.log(newValue, oldValue);
},
{
immediate: true, // 立即監聽
deep: true, // 深度監聽
}
);
return {
sum,
};
},
};
</script>
當監聽多個響應式資料時,將多個資料放在一個陣列裡面,這樣監聽的newValue和oldValue都也都是也陣列的形式呈現
<template>
<h3>當前數值:{{ sum }}</h3>
<button @click="sum++">增加</button>
<h3>標題:{{ title }}</h3>
<button @click="title+='~'">增加</button>
</template>
<script>
import { ref, watch } from "@vue/runtime-core";
export default {
setup() {
let sum = ref(0);
let title = ref("hi~");
// 監聽多個
watch(
[sum,title],
(newValue, oldValue) => {
console.log(newValue, oldValue);
},
{
immediate: true, // 立即監聽
deep: true, // 深度監聽
}
)
return {
sum,
title,
};
},
};
</script>
無法正確獲取oldValue,並且強制開啟了深度監聽。
第一個引數要以回撥函數返回寫法
<template>
<h3>姓名:{{Hero.username}}</h3>
<h3>年齡:{{Hero.age}}</h3>
<button @click="Hero.age++">改變年齡</button>
<button @click="Hero.username += '~'">改變姓名</button>
</template>
<script>
import { reactive, watch } from "@vue/runtime-core";
export default {
setup() {
let Hero = reactive({
username: '李四',
age: 18,
job: {
j1: {
speak: '你好'
}
}
})
// reactive所定義的響應式資料的某個屬性
watch(
()=>Hero.age, // 以回撥形式拿到監聽的屬性
(newValue, oldValue) => {
console.log(newValue, oldValue);
},
{
immediate: true, // 立即監聽
deep: true, // 深度監聽
})
return {
Hero
};
},
};
</script>
如果監聽的屬性巢狀層次比較深 則需要開啟深度監聽
watch(
[()=>Hero.username, ()=>Hero.age, () =>Hero.job], // 以回撥形式拿到監聽的屬性
(newValue, oldValue) => {
console.log(newValue, oldValue);
},
{
immediate: true, // 立即監聽
deep: true, // 深度監聽
})