Vue3的script setup语法糖详解

530 阅读1分钟

【前提】

  • ① 直接使用setup函数代码冗余,需要return数据,所以官方推出了script setup语法糖。
  • ② script setup里面的代码会被编译成组件setup()函数的内容,这意味着与普通的 script 只在组件被首次引入的时候执行一次不同,script setup 中的代码会在每次组件实例被创建的时候执行。
  • ③ 当使用 script setup 的时候,任何在script setup声明的顶层的绑定 (包括变量,函数声明,以及 import 引入的组件、方法等内容) 都能在模板中直接使用

1. 如何使用

  • 1、需要关闭vetur插件,安装Volar插件

  • 2、tsconfig.json / jsconfig.json 文件 ,在compilerOptions里面加上 "strict": true,和 "moduleResolution": "node"

  • 3、直接在script标签加入setup 或者 setup lang="ts"

     // 第1种:直接在script标签上加setup
    <script setup>
    </script>
    
    // 第2种:直接在script标签上加setup lang='ts'
    <script setup lang='ts'>
    </script>
    

2. 组件间的通信

2.1 definProps ---> 父传子(类比vue2中的props)

// 父组件中的代码如下:
<template>
    <Child :childMsg='msg' :childNum='num'></Child>
</template>

<script setup>
    import Child from './Child.vue'
    import {ref} from 'vue'
    let msg = ref('我是父组件的msg数据')
    let num = ref(10)
</script>

// 子组件中的代码如下:
<template>
    <div>{{childMsg}}----{{childNum}}</div>
</template>

<script setup>
    import {defineProps} from 'vue'
    
    // 方式1:用数组接收
    defineProps(['childMsg','childNum'])
    
    // 方式2:用对象接收
    defineProps({
        childMsg:{
            type:String,  //这里的数据类型大写
            required:true,   //必填项
            default:'我是默认数据' //默认值
        },
        childNum:{
            type:number
        }
    })
    
    //方式3:ts---泛型
    defineProps<{
        childMsg:string,
        childNum:number
    }>()
    
    //方式4:ts---接口对象约束
    interface Iinfo{
        childMsg:string,
        childNum:number
    }
    defineProps<Iinfo>()
    
    //方式5:ts---将方式4中的接口抽离到另一个文件中/src/typing/types.ts
       //src/typing/types.ts中代码如下
        export declare interface Iinfo{
            childMsg:string,
            childNum:number
        }
      //使用接口文件
      import {Iinfo} from '@typing/types'
      defineProps<Iinfo>()
</script>

2.2 useAttrs ---> 父传子(类比vue2中的this.$attrs)

  • 接收父组件传递没有被defineProps接收的属性

    // 父组件中的代码如下: 
      <template> 
              <Child :childMsg='msg' :childNum='num'></Child>
      </template>
    
      <script setup>
          import Child from './Child.vue'
          import {ref} from 'vue'
          let msg = ref('我是父组件的msg数据')
          let num = ref(10)
      </script>
    
    // 子组件中的代码如下:
      <template>
          <div>{{childMsg}}---{{childNum}}</div>
      </template>
      
      <script setup>
          import {defineProps,useAttrs} from 'vue'
          defineProps(['childMsg']);
          console.log(useAttrs()); //返回一个Proxy对象
          let {childNum} = useAttrs()
      </script>
    

2.3 defineEmits ---> 子传父 (类似vue2中的this.$emit)

在子组件中通过defineEmits派发子组件的自定义事件去触发父组件中的事件处理

QQ图片20230527100343.png

2.4 ref 和 defineExpose ---> 子传父(类似vue2中的this.$refs)

【vue3与vue2通过ref获取子组件对象的区别】 vue2中通过ref获取子组件的数据默认隐式暴露子组件数据。vue3的script setup语法糖中默认不暴露子组件数据,暴露数据需要在子组件中使用defineExpose

QQ图片20230612000135.png

2.5 provide 和 inject ---> 祖先传后代

QQ图片20230612000715.png

2.6 style中使用v-bind

QQ图片20230612001009.png

2.7 v-model ---> 父传子,子传父(类似vue2中sync修饰符)

QQ图片20230612001504.png