1.模板綁定
- 直接返回模板綁定(非響應(yīng)式)
<template>{{data}}</template>
<script lang="ts">
export default {
name: 'App',
setup(){
return {
data:"數(shù)據(jù)元"
}
}
}
</script>
- 響應(yīng)式
<template>
<div>{{state.count}}</div>
<div>{{count1}}</div>
<div>{{name}}</div>
</template>
<script lang="ts">
interface state {
count:number
}
interface Person{
name:string
}
import { reactive, ref, toRefs } from '@vue/reactivity'
import { defineComponent } from '@vue/runtime-core'
export default defineComponent({
name: 'App',
setup(){
const state = reactive<state>({
count:0
})
const person = reactive<Person>({
name:"小王"
})
//setup返回的 ref 在模板中訪問時是被自動淺解包的
//因此不應(yīng)在模板中使用.value
const count1 = ref<number>(1)
return{
state,
count1,
//將響應(yīng)式的對象變?yōu)槠胀▽ο?再解構(gòu)蜻底,在模板中就可以直接使用屬性,不用person.name
...toRefs<Person>(person)
}
}
})
</script>
2.參數(shù)
setup(props:,context:){
}
2.1 props
- 是由父組件傳遞下來的響應(yīng)式數(shù)據(jù)和reactive包裝的類型向相同聘鳞,均是proxy類型薄辅,因此不用再次對其進行響應(yīng)式包裝
- 不能使用 ES6 解構(gòu)props,它會消除 prop 的響應(yīng)性抠璃,若想結(jié)構(gòu)props站楚,可以用
toRefs
,因為上面說了props是proxy式的響應(yīng)式數(shù)據(jù)搏嗡,所以用toRefs
將其轉(zhuǎn)換為Ref響應(yīng)數(shù)據(jù)窿春,還能讓模板綁定更簡單
//Test.vue
<template>
<h1>{{title}}</h1>
</template>
<script lang="ts">
import { defineComponent, watch, watchEffect } from "@vue/runtime-core";
export default defineComponent({
name:"Test",
props:{
title:String
},
setup(props,context){
console.log(props);
//最初的時候執(zhí)行一次
//變化的時候再次執(zhí)行
watchEffect(()=>{
console.log(props);
})
//僅變化的時候執(zhí)行
watch(()=> props.title,newValue =>{
console.log(newValue);
})
}
})
</script>
//App.vue
<template>
<Test :title="title"></Test>
</template>
<script lang="ts">
import { reactive, ref, toRefs } from '@vue/reactivity'
import { defineComponent } from '@vue/runtime-core'
import Test from './components/Test.vue'
export default defineComponent({
name: 'App',
components:{
Test
},
setup(){
const title = ref<string>("我是vue")
console.log(title);
setTimeout(() => {
title.value = "我是vue3.0"
console.log(title)
}, 2000);
return {
title
}
}
})
</script>
- 如果 title 是可選的 prop,則傳入的 props 中可能沒有 title 采盒。在這種情況下旧乞,toRefs 將不會為 title 創(chuàng)建一個 ref 。你需要使用 toRef 替代它:
<template>
<h1>{{title}}</h1>
</template>
<script lang="ts">
import { defineComponent, toRef, toRefs, watch, watchEffect } from "@vue/runtime-core";
export default defineComponent({
name:"Test",
props:{
title:String
},
setup(props,context){
console.log(props);
const title = toRef(props,'title')
//最初的時候執(zhí)行一次
//變化的時候再次執(zhí)行
watchEffect(()=>{
console.log(title.value);
})
//僅變化的時候執(zhí)行
watch(()=> title,newValue =>{
console.log(newValue);
})
}
})
</script>
2.2context
-
context
包含三個屬性:attrs
纽甘、slots
、emit
- 由于
context
是非響應(yīng)式的决瞳,因此可以在setup
中對其進行解構(gòu)
export default {
setup(props, { attrs, slots, emit }) {
...
}
}
-
attrs
和slots
是有狀態(tài)的對象左权,它們總是會隨組件本身的更新而更新赏迟。這意味著你應(yīng)該避免對它們進行解構(gòu),并始終以attrs.x
或slots.x
的方式引用property
甩栈。與props
不同量没,attrs
和slots
是非響應(yīng)式的。如果你打算根據(jù)attrs
或slots
更改對應(yīng)業(yè)務(wù)邏輯究抓,那么應(yīng)該在onUpdated
生命周期鉤子中執(zhí)行此操作刺下。
- attrs與props的不同:
- props 要先聲明才能取值稽荧,attrs 不用先聲明
- props 聲明過的屬性蛤克,attrs 里不會再出現(xiàn)
- props 不包含事件,attrs 包含
- props 支持 string 以外的類型髓介,attrs 只有 string 類型
<template>
<h1>{{title}}</h1>
</template>
<script lang="ts">
import { defineComponent, toRef, toRefs, watch, watchEffect } from "@vue/runtime-core";
export default defineComponent({
name:"Test",
setup(props,context){
console.log(context.attrs);
return {
...toRefs(context.attrs)
}
}
})
</script>
<template>
<h1>{{title}}</h1>
</template>
<script lang="ts">
import { defineComponent, toRef, toRefs, watch, watchEffect } from "@vue/runtime-core";
export default defineComponent({
name:"Test",
setup(props,context){
console.log(context.attrs);
return {
//失去響應(yīng)性
...context.attrs
}
}
})
</script>
<template>
<h1>{{attrs.title}}</h1>
</template>
<script lang="ts">
import { defineComponent, toRef, toRefs, watch, watchEffect } from "@vue/runtime-core";
export default defineComponent({
name:"Test",
setup(props,context){
console.log(context.attrs);
return {
attrs:context.attrs
}
}
})
</script>
- emit:用于父子通信
<template>
<h1>{{count}}</h1>
<button @click="plus(3)">增加</button>
</template>
<script lang="ts">
import { defineComponent, SetupContext, toRef, toRefs, watch, watchEffect } from "@vue/runtime-core";
export default defineComponent({
name:"Test",
props:{
count:Number
},
emits:['plus'],
setup(props,context:SetupContext){
const plus:(num: number) => void = (num:number)=>{
context.emit('plus',num)
}
return {
plus
}
}
})
</script>
<template>
<Test :count="count" @plus="plus"></Test>
</template>
<script lang="ts">
import { reactive, ref, toRefs } from '@vue/reactivity'
import { defineComponent } from '@vue/runtime-core'
import Test from './components/Test.vue'
export default defineComponent({
name: 'App',
components:{
Test
},
setup(){
const count = ref<number>(1)
const plus:(num: number) => void = (num:number):void=>{
count.value += num
}
return {
count,
plus
}
}
})
</script>
3.this
VUE2 | VUE3 |
---|---|
beforeCreate | setup |
created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
errorCaptured | onErrorCaptured |
setup
中的this
是undefined