Vue3当中的<setup script>

303 阅读2分钟

尤大在 Vue 3.2 发布的时候就给出了项目最佳实践的解决方案:

<script setup> + TS =+ Volar

如此可见<setup script>的地位举足轻重,是我们写Vue3绕不过的话题;

在Vue3当中,引入了Composition API,我们可以通过编写setup函数来作为API的入口来使用,它也是Vue3一大特性函数,对于之前Options API分散的写法,我们可以把控制代码统统放在setup函数当中,实现数据的展示和功能的实现

而对于<setup script>,简单来讲,它是vue3新出的一个语法糖,里面的代码会被编译成组件 setup()函数的内容,会极大地方便日常代码的书写。

官方文档指路:v3.cn.vuejs.org/api/sfc-scr…

它的优势说明:

  • 更少的样板内容,更简洁的代码。
  • 能够使用纯 TypeScript 声明 props 和抛出事件。
  • 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
  • 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)

具体代码编写姿势:

1. 自动注册子组件

直接import所需要的组件之后就可以直接使用,会自动完成组件的注册;

在传统script代码中,子组件在import之后需要通过components进行注册才能使用,而在setup语法糖当中会帮助我们自动完成组件的注册;

传统script写法:

<template>
  <div>
    <MyComponent />
  </div>
</template>
<script>
import { defineComponent, ref } from 'vue';
// 组件
import MyComponent from './MyComponent.vue'export default defineComponent({
  components: {
      MyComponent
  },
  setup() {}
});
</script>

setup script写法:

<script setup>
import MyComponent from './MyComponent.vue'</script><template>
  <MyComponent />
</template>

2. 简化返回

setup函数中,需要返回定义的变量和方法名才能在模板当中使用,而语法糖当中顶层定义的属性和方法不需要再手动返回

传统script写法:

<template>
  <div>
    <h2>{{msg}}</h2>
  </div>
</template>
<script>
import { defineComponent, ref } from 'vue';
​
export default defineComponent({
  setup() {
    const msg = ref('Hello!')
  
    const showMsg = () => {
      console.log(msg.value)
    }
    
    return {
      msg,
      showMsg
    }
  }
});
</script>

setup script写法

<script setup>
// 变量
const msg = ref('Hello!')
// 函数
const showMsg = () => {
   console.log(msg.value)
}
</script><template>
  <div @click="showMsg">{{msg}}</div>
</template>

3. definePropsdefineEmit 接受propsemit

传统script代码:

<template>
  我是子组件{{title}}
  <div @click="backData"></div>
</template>
<script >
 import { defineComponent } from 'vue'
 export default defineComponent({
   //或者props:['title'],
   props:{
     title:{
       type:String,
      default:''
     }
   },
   emits: ["getData"],
   setup (props,{emit}) {
    const backData = () => {
      emit('getData', 123) //getData为父组件中定义的接收函数
    }
    return {
      backData
    }
  }
})
</script>

setup script写法:

<template>
<div>
  <h2 >父组件</h2>
  <Child msg="hello" @child-click="childCtx" />
  </div>
</template><script setup>
  import Child from './Child.vue';  //point 1:自动注册子组件
  const childCtx = (ctx) => {      //point 2:属性不需返回
    console.log(ctx);
  }
</script>
​
​
//Child.vue
<template>
<span @click="handleClick">子组件 -- msg: {{ props.msg }}</span>
</template><script setup lang=ts>
  import {  defineProps, defineEmit } from 'vue'   
  
  //typescript中props与emit写法
  const props = defineProps<{
    msg: string
  }>()
  
  const emit = defineEmits<{
    (e: 'child-click', value: string): void
  }>()
  //——end
  
  const handleClick = () => {
    emit('child-click', 'xxx')
  }
​
</script>

TS中带有默认值的props写法:

interface Props {
  msg?: string
  labels?: string[]
}
​
const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})

4. defineExpose API

在传统的写法中,可以在父组件中,通过ref实例的方式去访问子组件的内容,但在script setup中,该方法就不能用了,在setup ,除了内部的template模板,谁都不能访问内部的数据和方法。这时候可以将属性和方法通过defineExpose暴露出去

<script setup>
import { ref } from 'vue'const a = 1
const b = ref(2)
​
defineExpose({
  a,
  b
})
</script>

5. components :is动态组件

当我们不确定某个位置具体要用那个组件时,通常会用到<components/>标签,并结合:is属性对组件名进行动态绑定,当多个组件切换时非常方便;Vue3当中的setup script同样支持这种写法,只不过,我们需要注意以下的用法差异:

使用语法糖时,:is的值改为组件,字符串将不生效,通常可以通过一个变量来进行控制

传统script代码写法(和Vue2基本一致):

<template>
  <component :is="currentComp"></component> 
  <el-button @click="compChange">切换组件</el-button>
</template>
<script>
  import { ref } from 'vue'
  import Child1 from './Child1.vue'
  import Child2 from './Child2.vue'
  export default {
    components: {
      Child1,
      Child2
    },
    setup() {
      let currentComp = ref('Child1')
      // 切换组件
      const compChange = () => {
        if(currentComp.value == 'Child1') {
          currentComp.value = 'Child2'
        }else {
          currentComp.value = 'Child1'
        }
      }
      return {
        currentComp,
        compChange
      }
    }
  }
</script>

setup script写法:

<template> 
  <-- 注意这里的Chlid1、Chlid2为组件类型 -->
  <component :is="flag ? Child1 : Child2"></component> 
  <el-button @click="flag = !flag">切换组件</el-button> 
</template>
<script setup lang="ts">
  import { ref } from 'vue'
  import Child1 from './Child1.vue'
  import Child2 from './Child2.vue'
  const flag = ref(true)
</script>

6. 自定义指令

指令和组件一样,导入会自动进行注册,在符合命名规范的前提下可以直接在模板当中使用(必须以 vNameOfDirective的形式来命名本地自定义指令)

<script setup>
const vMyDirective = {  //定义指令
  beforeMount: (el) => {
    // 在元素上做些操作
  }
}
</script>
<template>
  <h1 v-my-directive>This is a Heading</h1>  //在当前文件中直接使用
</template>
​
​
//在另一个文件当中,通过导入使用
<script setup>
  // 也能够通过重命名来使其符合命名规范
  import { myDirective as vMyDirective } from './MyDirective.js'
</script>

7. 兼容使用

在使用<script setup>的同时,是可以和普通的<script>标签一起使用的,只是两者的执行机制是不同的,普通<script>, 只会执行一次,而<script setup>中的代码,相当于写在了setup函数当中,在 setup()作用域中执行,不止一次

当然,对于<setup script>不仅仅只是这六点特性,本文只是列举的日常开发当中比较常见的一些情景,如果你仅仅只是需要立马上手Vue3,了解完这些就可以去写代码啦~ 对于其他的内容官网上面都解释的非常清楚,非常建议大家养成看官网的好习惯👀👀👀