vue3.2 最新setup语法糖

546 阅读1分钟

前言

Vue3.0给我们提供了composition API,而实现composition API这种代码风格主要是使用官方提供的setup这个函数。

Vue3.0一个常规的setup写法如下:

<script lang="ts">
import { defineComponent, ref } from 'vue'
import NavMenu from '@/components/nav-menu'
import NavHeader from '@/components/nav-header'

export default defineComponent({
  components: {
    NavMenu,
    NavHeader
  },
  setup(props,context) {
    const isCollapse = ref(false)
    const handleFoldChange = (isFold: boolean) => {
      isCollapse.value = isFold
    }

    return {
      isCollapse,
      handleFoldChange
    }
  }
})

其实在Vue3.0阶段,就已经有了script setup。不过当时这个提案还只是实验阶段,所以之前写Vue3的代码仍然是采用常规setup函数这种,终于我们在2021年6月29日上午迎来了他的Finalization,下面简单介绍下更新的内容。

更新内容

介绍更新内容之前,我们先看看最新的script setup代码写法,让大家有一个基本的了解以及和之前写法做一下对比:

<script setup lang="ts">
import { ref } from 'vue'
import AccountLogin from './account-login.vue'

const isRememberPassword = ref(true)
const accountRef = ref<InstanceType<typeof AccountLogin>>()
const activeName = ref('account')
const login = () => {
  activeName.value === 'account'
    ? accountRef.value?.loginAction(isRememberPassword.value)
    : phoneRef.value?.loginAction(isRememberPassword.value)
}
</script>

1.子组件不需要注册

在 script setup 中,引入的组件可以直接使用,无需再通过components进行注册,并且无法指定当前组件的名字,它会自动以引入文件名为主。示例:

<template>
    <login-account />
</template>

<script setup>
  import LoginAccount from './loginAccount'
</script>

2.变量和方法不需要再被return

示例:

<template>
  <div class="overview">
    {{ message }}
    <button @click="changeMessage/button>
  </div>
</template>

<script lang="tssetup>
import { ref } from 'vue'
const message = ref('hello world')
const changeMessage = () => {
  message = 'hahahah'
}
</script>

3.新增API

defineExpose

传统setup写法里我们可以在父组件中通过子组件的ref实例来访问子组件的数据和方法(childRef.value.someFn()),但是这种写法在script setup却行不通了。

不过最新提供了defineExpose这个API。组件通过defineExpose暴露出自己的属性,在父组件中拿到。

//子组件
import { ref, defineExpose } from 'vue'
const loginAction = (isRememberPassword: boolean) => {
  ......
}
defineExpose({
  loginAction
})
//父组件
<template>
  <div>
    <account-login
      ref="accountRef"
      :rememberPassword="isRememberPassword"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import AccountLogin from './account-login.vue'
const accountRef = ref<InstanceType<typeof AccountLogin>>()
const login = () => {
  accountRef.value?.loginAction()
}
</script>

defineProps

defineProps用于子组件接受父组件传的值.示例:

//父组件
<template>
  <div>
    <account-login :message="message" />
  </div>
</template>
<script lang="ts" setup>
// 组件命名采用的是大驼峰,引入后不需要在注册
import AccountLogin from './account-login.vue'
let message = 'hello world' 
</script>
//子组件
<template>
  <div>
    <h2>{{message}}</h2>
  </div>
</template>
<script lang="ts" setup>
import {defineProps} from 'vue'
defineProps({
    message:{
        type:String,
        default:'hahha'
    }
})
</script>

defineEmits

子组件向父组件传递事件。示例:

//子组件
<template>
  <div>
    <button @click='sendEmit'>给父组件发送事件</button>
  </div>
</template>
<script lang="ts" setup>
import {defineEmits} from 'vue'
//使用defineEmits创建名称,接受一个数组
const emit = defineEmits(['sendEmit'])
const sendEmit = () =>{
  emit('sendEmit','传递的数据')
}
</script>
//父组件
<template>
  <div>
    <account-login @sendEmit="handleEmit">
  </div>
</template>
<script lang="ts" setup>
// 组件命名采用的是大驼峰,引入后不需要在注册
import AccountLogin from './account-login.vue'
const handleEmit = (data) => {
  console.log(`子组件传来的值:${data}`)
}
</script>

4.其它

顶层await

script setup会默认声明async,类似于async setup()的效果,你可以在script setup中直接使用await函数。示例:

<script lang="ts" setup>
  const res = await request('api/getData')
</script>

useSlots 和 useAttrs

之前可以通过useContext从上下文中获取 slots 和 attrs。不过提案在正式通过后,废除了这个语法,被拆分成了useAttrs和useSlots。示例:

// 旧
<script setup>
  import { useContext } from 'vue'
  const { slots, attrs } = useContext()
</script>

// 新
<script lang="ts" setup>
  import { useAttrs, useSlots } from 'vue'
  const attrs = useAttrs()
  const slots = useSlots()
</script>

以上就是这次更新的主要内容。

点个关注,互相监督学习进步!