Vue 3.x 的 script setup 语法糖用法详解
由于原来vue3中的setup Composition API 语法太过于冗长麻烦,官方又出了这么个语法糖,非常的好用了。
这里介绍一些常用的语法:
一、如何开始使用?
1、需要关闭vetur
插件,安装Volar
插件
2、tsconfig.json / jsconfig.json
文件 ,在compilerOptions
里面加上 "strict": true,和 "moduleResolution": "node"
3、直接在script标签加入setup 或者 setup lang="ts"
<script setup>
</script>
或者使用TypeScript
<script setup lang="ts">
</script>
script setup
里面的代码会被编译成组件setup()
函数的内容。这意味着与普通的 script
只在组件被首次引入的时候执行一次不同,script setup
中的代码会在每次组件实例被创建的时候执行。
当使用 script setup 的时候,任何在script setup声明的顶层的绑定 (包括变量,函数声明,以及 import 引入的组件、方法等内容) 都能在模板中直接使用
import 导入的内容也会以同样的方式暴露。意味着可以在模板表达式中直接使用导入的函数,并不需要通过 methodsscript-setup
无法指定当前组件的名字,所以使用的时候以文件名为主
<template> <div @click="test">{{ name}}</div> <div>{{dateFomat('2022-02-18')}}</div> <HomeComponent /> </template> <script setup> import { dateFomat} from './utils' import HomeComponent from './MyComponent.vue' import { ref , reactive } from 'vue' // 简单变量 const name= ref('Lilei!') //复杂变量 const user =reacrive({ name:"韩梅梅", age:18 }) // 函数 const test =() => { console.log('hello') } </script>
二、prop父组件给子组件传值
在 <script setup>
中必须使用 defineProps API 来声明 props ,它们具备完整的类型推断并且在 <script setup>
中是直接可用的:
父组件中给子组件传值
<template>
<myson info="子组件prop接收" ></myson>
</template>
<script setup lang="ts">
import myson from './myson.vue'
</script>
子组件获取prop
第一种方式:使用 JavaScript 原生构造函数进行类型规定。
<template> <p>{{ info }}</p> </template> <script setup lang="ts"> import { defineProps } from 'vue' // 子组件使用defineProps接收父组件prop参数,类型是大写开头 defineProps({ info: { type: String, required: false, default: '我是prop传值' } }) <script>
第二种方式:使用 TypeScript 的类型注解。
defineProps 也是可以使用尖括号 <> 来包裹类型定义,紧跟在 API 后面,另外,由于 defineProps 返回的是一个对象(因为 props 本身是一个对象),所以尖括号里面的类型还要用大括号包裹,通过 key: value 的键值对形式表示
defineProps<{ name: string }>();//这里是类型string是小写的,而第一中方式是大写的,注意一下 如果有多个 prop ,就跟写 接口 interface 一样,注意类型都是小写开头 defineProps<{ name: string; phoneNumber: number; userInfo: object; tags?: string[]; //?号表示这个是可选的 }>(); 注意这里的userInfo 类型也可以写一个接口 interface UserInfo { id: number; age: number; } defineProps<{ name: string; userInfo: UserInfo; }>();
attrs 的接收父组件的传值
attrs 和 props 很相似,也是基于父子通信的数据,如果父组件绑定下来的数据没有被指定为 props ,那么就会被挂到 attrs 这边来。
setup script 中使用 useAttrs 来获取attrs
父组件中
<template>
<myson msg="hello world" ></myson>
</template>
<script setup lang="ts">
import myson from './myson.vue'
</script>
子组件没有使用prop接收,就会到attr中
// 导入 useAttrs 组件 import { useAttrs } from 'vue' // 获取 attrs const attrs = useAttrs() // attrs是个对象,和 props 一样,需要通过 key 来得到对应的单个 attr console.log(attrs.msg);
三、子组件使用emits触发父组件的方法
setup script
api中使用 defineEmits 来定义emit触发父组件事件,用法如下:
子组件中
<template> <button @click="triggerFatherAdd">点击触发父组件add</button> </template> <script setup lang="ts"> import { defineEmits } from 'vue' // 子组件使用defineEmits向父组件抛出事件 const emits = defineEmits(['add', 'update'])//事件数组 // 触发调用子组件时的自定义事件add const triggerFatherAdd = () => { emits('add', '新增数据')//后面是参数 } </script>
父组件中使用子组件自定义事件@add=“父组件中的事件处理”
<template> <myson @add="add" ></myson> </template> <script setup lang="ts"> import myson from './myson.vue' const add = (msg:string) => { console.log('add', msg) } </script>
四、ref获取这个子组件对象
在之前的语法中,通过ref获取子组件的数据都是默认隐式暴露给父组件的,而script setup
默认是不暴露子组件数据的,暴露数据需要 defineExpose api的支持
基本用法也很简单,它本身是一个函数,可以接受一个对象参数。
在子组件里,把需要暴露出去的数据通过 key: value 的形式作为入参
子组件中的写法:
<script setup lang="ts"> import { defineExpose } from 'vue' // 定义一个想提供给父组件拿到的数据 const msg: string = 'Hello World!'; // 显示暴露的数据,才可以在父组件拿到 defineExpose({ msg }); </script>
父组件通过绑定ref拿到数据
<template> <myson ref="son" ></myson> </template> <script setup lang="ts"> import { ref , onMounted } from 'vue' //1、定义一个变量,变量的名字需要和上面ref的一致 const son=ref() //2、通过 .value 获取数据,但是需要页面挂载后才能拿到ref数据,在此之前都是 undefined console.log(son.value) //undefined onMounted(() => { const getsonMsg = son.value.msg console.log(getsonMsg) //Hello World! }) </script>
五、使用 provide 给子孙组件传值和 inject 接收父组件的值
父组件中使用provide
<script setup lang="ts"> import { provide } from "vue"; const curUserId = 168 //可以是简单类型,也可以是复杂类型 provide('curUserId', curUserId) </script>
子孙组件中获取
<script setup lang="ts"> import { inject } from "vue"; const curUserId= inject('curUserId') </script>
六、style中使用v-bind
直接上代码:
<template> <span> 有开始循环了-开端 </span> </template> <script setup> import { reactive } from 'vue' const state = reactive({ color: 'red' }) </script> <style scoped> span { /* 使用v-bind绑定state中的变量 */ color: v-bind('state.color'); } </style>