setup

1.模板绑定

  • 直接返回模板绑定(非响应式)
<template>{{data}}</template>
<script lang="ts">
export default {
  name: 'App',
  setup(){
      return {
        data:"数据元"
      }
  }
}
</script>
  • 响应式
<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 在模板中访问时是被自动浅解包的
     //因此不应在模板中使用.value
     const count1 = ref<number>(1)
     return{
       state,
       count1,
       //将响应式的对象变为普通对象 再解构,在模板中就可以直接使用属性,不用person.name
      ...toRefs<Person>(person) 
     }
  }
})
</script>

2.参数

setup(props:,context:){

}

2.1 props

  • 是由父组件传递下来的响应式数据和reactive包装的类型向相同,均是proxy类型,因此不用再次对其进行响应式包装
  • 不能使用 ES6 解构props,它会消除 prop 的响应性,若想结构props,可以用toRefs,因为上面说了props是proxy式的响应式数据,所以用toRefs将其转换为Ref响应数据,还能让模板绑定更简单
//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);
        //最初的时候执行一次
        //变化的时候再次执行
        watchEffect(()=>{
            console.log(props);
        })
        //仅变化的时候执行
        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 创建一个 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')
        //最初的时候执行一次
        //变化的时候再次执行
        watchEffect(()=>{
            console.log(title.value);
        })
        //仅变化的时候执行
        watch(()=> title,newValue =>{
            console.log(newValue);
        })
    }
})
</script>

2.2context

  • context包含三个属性:attrsslotsemit
  • 由于context是非响应式的,因此可以在setup中对其进行解构
export default {
  setup(props, { attrs, slots, emit }) {
    ...
  }
}
  • attrsslots 是有状态的对象,它们总是会随组件本身的更新而更新。这意味着你应该避免对它们进行解构,并始终以 attrs.xslots.x 的方式引用 property。与 props 不同,attrsslots是非响应式的。如果你打算根据 attrsslots 更改对应业务逻辑,那么应该在 onUpdated 生命周期钩子中执行此操作。

  • attrs与props的不同
    • props 要先声明才能取值,attrs 不用先声明
    • props 声明过的属性,attrs 里不会再出现
    • 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 {
          //失去响应性
          ...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中的thisundefined

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354

推荐阅读更多精彩内容