vue3语法糖🍬setup的使用

261 阅读1分钟

背景

vue3更新很久啦,在编码方式上有一个很大的改变,解放我们的双手的亮点不少!下面记录一下其中亮点之一语法糖🍬setup的用法。

语法

<script setup lang="ts">
</script>

优点

  • 更少的样板内容,更简洁的代码。

    无需注册组件

    setup中引入组件

      <script setup lang="ts">
      import Footer from '@/components/Footer.vue';
      </script>
    

    模版中使用

    <template>
       <div class="home">
         <Footer />
       </div>
     </template>
    

    顶层的绑定会被暴露给模板

    变量方法import 导入的内容无需return出去,直接暴露给模版,开箱即用

    模版

     <template>
       <div> {{ msg }}</div>
       <button @click="handClick">ok</button>
       <button @click="showInfo">ok</button>
     </template>
    

    setup

      <script setup lang="ts">
         import { showInfo } from '@/utils/index.js';
         const msg = 'hello world!';
         const handClick = () => {
           console.log('btn');
         };
      </script>
    

    defineProps、defineEmits

    无需引入,更好的支持typescript

    defineEmits两种写法

    <script setup lang="ts">
        const emit = defineEmits(['changeName']);
    </script>
    
    <script setup lang="ts">
        const emit = defineEmits<{
           (e: 'changeName'): void;
         }>();
     </script>
    

    defineProps

    <script setup lang="ts">
        const props = defineProps({
           name: String
         });
    </script> 
    

useAttrs、useSlots

  • useAttrs:用来获取父组件传递过来的所有的参数属性信息
  • useSlots: 获取插槽信息
  • 模板中通过 $attrs、$slots来访问

setup

<script setup lang="ts">
    import { useAttrs } from 'vue';
    const { attrs = { name } } = useAttrs();
    console.log(attrs);
    console.log(name);
</script>

模版

<div> {{ $attrs.name }}</div>

支持顶层await

<script setup lang="ts">
   const getInfos = () => {
     setTimeout(() => {
       console.log(1);
     }, 1000);
   };
   const res = await getInfos();
</script>

注意,这里返回了一个promise,使用该组件的时候需要使用异步组件进行包裹 <Suspense>

自定义指令

通过固定指令的名称格式(vNameOfDirective)自动注册自定义指令

<script setup lang="ts">
    // 自动注册一个指令 指令名称v-MyDirective,模版自动识别格式进行注册
    const vMyDirective = {
      beforeMount: () => {},
      mounted(el: HTMLElement) {
        console.log(el.focus());
      }
    };
</script>
<template>
  <input v-MyDirective />
</template>

别处导入,重命名

<script setup>
import { myDirective as vMyDirective } from './MyDirective.js'
</script>

动态组件

<component :is="flat ? User : ''" :name="name" @changeName="changeName" />

其他

除了vue3默认帮我们帮引入的一些api(defineEmits、defineProps、defineExpose),有一些(比如ref、useAttrs、useSlots)还需要手动导入也是挺麻烦的,我们可以使用unplugin-auto-import把使用频率高的api进行自动导入,这样可以少些很多代码。

安装

npm i -D unplugin-auto-import

安装完成后会自动生成两个文件 auto-imports.d.ts.eslintrc-auto-import.json

Vite配置

// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
plugins: [
  AutoImport({
// resolvers: [ElementPlusResolver()],
imports: [
  'vue',
  'pinia',
  'vue-router',
],
eslintrc: {
  enabled: true, // Default `false`
      filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
      globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
    },
    dts: true //auto generation auto-imports.d.ts file
  }),
]
})

ts配置

如果不配置,ts语法校验会失败

// tsconfig.json
{
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue","auto-imports.d.ts"],

}

使用

无需引入api,默认引入的可以在eslintrc-auto-import.json中查看,这样看代码少了太多了!

// User.vue
<script setup lang="ts">
const emit = defineEmits(['changeName']);
const attrs = useAttrs();
let { name } = attrs;
</script>
<template>
  <div> {{ name }}</div>
  <div> {{ $attrs.name }}</div>
  <div @click="emit('changeName')"> changeName</div>
</template>