Vue 实验性语法 script setup

3,683 阅读1分钟

说明

这篇文章或许某些地方有问题,这篇文章只是在我看过别人写的 vite2的介绍文章 后,自己在看了下声明文件后写,根据自己的想法写的,并没有看过vue的代码,所以有些地方的原理我也不知道。

  • 创建项目: npm init @vitejs/app 或者 yarn create @vitejs/app
  • 推荐环境: vscode + Volar (工作区禁用Vetur)

一、 组件使用

import导入组件后,模板中就可以直接使用,无需在components中注册组件。

<template>
  <HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
</template>

<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
</script>

二、 Data Property 和方法

script中的顶级变量与方法可以直接在模板使用,无需手动导出。

<template>
  <HelloWorld :msg="msg" />
</template>

<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
const msg="Hello Vue 3 + TypeScript + Vite"
function handleClick(s: string){
  console.log(s)
}
</script>

三、Props

使用 defineProps 定义组件Props,用法与以前的props定义一致。

<template>
  <div>{{ msg }}</div>
</template>

<script setup lang="ts">
import { defineProps, PropType } from "vue";
defineProps({
  msg: String,
  propA: [String, Number],
  propB: {
    type: Boolean,
    required: true,
  },
  propC: {
    type: Object as PropType<{ a: string; b?: number }>,
    default: () => {},
  },
});
</script>

四、自定义事件

使用 defineEmit 定义组件自定义事件。

第一种传参方式字符串数组,数组中每个字符串元素为定义的自定义事件名。
<!-- HelloWorld.vue -->
<template>
  <div @click="$emit('myClick','test')">{{ msg }}</div>
</template>

<script setup lang="ts">
import { defineEmit, defineProps } from "vue";
defineProps({
  msg: String,
});
defineEmit(['myClick'])
</script>
<!-- App.vue -->
<template>
  <HelloWorld :msg="msg" @myClick="handleClick"/>
</template>

<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
const msg="Hello Vue 3 + TypeScript + Vite"
function handleClick(...args: any[]){
  console.log(args)
}
</script>

第一种方式传参使用简单,但是有一个问题,就是自定义事件方法的类型默认设置成 (...payload: unknown[]) => unknown 。导致在设置响应事件的方法也要定义成这个类型,不然ts就会提示类型不匹。

第二种传参方式对象,对象下的键名为自定义事件名,键值为一个函数。

defineEmit定义的对象键值会作为对于键名自定义事件的函数类型,有意识的时这个对象键值函数在自定义事件触发的时候也会执行。如果不需要自定义事件触发时子组件操作什么,直接定义一个空函数就行。

<!-- HelloWorld.vue -->
<template>
  <div @click="$emit('myClick', 'test')">{{ msg }}</div>
</template>

<script setup lang="ts">
import { defineEmit, defineProps } from "vue";
defineProps({
  msg: String,
});
defineEmit({
  myClick(s: string) {
    // 自定义事件触发的时候也执行这个函数
    console.log(123456);
  },
});
</script>
<!-- App.vue -->
<template>
  <HelloWorld :msg="msg" @myClick="handleClick"/>
</template>

<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
const msg="Hello Vue 3 + TypeScript + Vite"
function handleClick(s: string){
  console.log(s)
}
</script>

获取上下文

使用 useContext 获取当前组件上下文

<template>
  <div @click="$emit('myClick', 'test')">{{ msg }}</div>
</template>

<script setup lang="ts">
import { defineEmit, defineProps} from "vue";
import {useContext} from 'vue'
defineProps({
  msg: String,
});
defineEmit({
  myClick(s: string) {
    console.log();
  },
});
console.log(useContext());
</script>

这里有一个地方需要注意的是defineProps与useContext不能在同一个import句法导入,不然vite就会报错,我只是发现不知道为什么。