1. 安装Vue3.0
npm init vue@latest,选择所需配置- 根据安装成功后的指令提示
- cd vue3setup 进入项目
- npm install 安装依赖
- npm run dev 启动项目
2. setup语法糖
script setup 是在单文件组件(SFC)中使用组合式API的编译时语法糖。当同时使用SFC与组合式API时该语法是默认推荐。相比于普通的<script>语法,它具有更多优势:
- 更少的样板内容,更简洁的代码
- 能够使用纯TypeScript声明props和自定义事件
- 更好的运行时性能(其模板会被编译成统一作用域内的渲染函数,避免了渲染上下文代理对象)
- 更好的IDE类型推导性能(减少了语言服务器从代码中抽取类型的工作)
2.1 setup语法糖基本用法
- 若要启用该语法糖,需要在
<script>标签上添加setup属性,里面的代码会被编译成组件setup()函数的内容。这意味着与普通的<script>只在组件被首次引入的时候执行一次不同,<script setup>中的代码会在每次组件实例被创建的时候执行。
2.1.1 顶层绑定暴露给模板
- 当使用
<script setup>时,任何在<script setup>声明的顶层的绑定(包含变量、函数声明,以及import导入的内容)都能在模板中直接使用 - 变量、函数以及import内容,直接可在
<template />中进行使用 - 引入组件自动注册
- 引入工具函数,即刻使用
<template>
<div class="about">
<button @click="logCurName">{{myPageName}}</button>
<div>
初始值为 {{calcdouble(initHalf)}}
</div>
<ActivityTip />
</div>
</template>
<script setup>
// 顶层引入工具函数
import calcdouble from "../utils/calcdouble.js";
// 顶层引入组件
import ActivityTip from '../components/ActivityTip.vue'
// 顶层定义变量
const myPageName = 'this is an about page'
const initHalf = 3
// 顶层定义方法
function logCurName() {
console.log(myPageName)
}
</script>
2.1.2 响应式
想要将某个值定义为响应式,可以使用composition Api中的ref,覆盖范围较广。
<template>
<button @click="times++">Add res {{times}}</button>
</template>
<script setup>
const times = ref(0)
</script>
2.1.3 使用组件
- 动态组件: 可以通过当前的某种状态判断要加载哪种具体的组件,也可引用多个组件,通过is属性引入对应的组件,引入进来的组件AComponent、BComponent可以看做变量来进行使用
<template>
<div>
<component :is="AComponent" />
<component :is="showAStatus ? AComponent: BComponent"/>
</div>
</template>
<script setup>
import AComponent from "../components/AComponent.vue";
import BComponent from "../components/BComponent.vue";
const showAStatus = ref(false);
</script>
2.1.4 使用自定义指令
除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外,Vue 还允许你注册自定义的指令 (Custom Directives)。自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。
- 全局自定义指令在script setup中正常工作
- 本地自定义指令在script setup中无需显示注册,但命名必须遵守
vNameOfDirective
<template>
<div>自动聚焦当前输入框: <input v-input-focus type="text" /></div>
</template>
<script setup>
const vInputFocus = {
mounted: (el) => {
el.focus();
},
};
</script>
- 若从外部环境导入某个具体的指令,可以通过重命名来使其符合命名规范
autoFocus.js
const autoFocus = {
mounted: (el) => {
el.focus();
},
};
export {
autoFocus
}
页面中使用autoFocus,不符合指令规范,在引入中将其修改
<template>
<div>自动聚焦当前输入框: <input v-auto-focus type="text" /></div>
</template>
<script setup>
import { autoFocus as vAutoFocus } from '../utils/autoFocus.js'
</script>
2.1.5 defineProps()和defineEmits()
父子组件通信时大多数情况下会遇到props将参数从父组件传入子组件,使用emit将子组件某些值回传给父组件。与之前的原理相同,只是写法上略有些变化。
- defineProps 和 defineEmits 都是只能在
<script setup>中使用的编译器宏。他们不需要导入,且会随着<script setup>的处理过程一同被编译掉。 - defineProps 接收与 props 选项相同的值,defineEmits 接收与 emits 选项相同的值。
- defineProps 和 defineEmits 在选项传入后,会提供恰当的类型推导。
传入到 defineProps 和 defineEmits 的选项会从 setup 中提升到模块的作用域。因此,传入的选项不能引用在 setup 作用域中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块作用域内。
父组件: 引入子组件,定义传入子组件初始props值,定义子组件传出的方法并接收传出值
<template>
<div>
<AComponent :curCount="curCount" @addCurCount="addCurCount"/>
</div>
</template>
<script setup>
import AComponent from "../components/AComponent.vue";
const curCount = ref(4)
function addCurCount(val) {
curCount.value += val
}
</script>
子组件: 接收props值,定义传出方法
<template>
<div>
<button @click="addCurCount">当前值{{ curCount }},点我加3</button>
</div>
</template>
<script setup>
const emits = defineEmits(["addCurCount"]);
const props = defineProps({
curCount: {
type: Number,
},
});
const addCurCount = function () {
emits("addCurCount", 3);
};
</script>
2.1.6 defineExpose
我们可以在父组件通过ref获取子组件实例
父组件:
<template>
<AComponent ref="Acom" :curCount="curCount" @addCurCount="addCurCount"/>
</template>
<script setup>
import AComponent from "../components/AComponent.vue";
import { onMounted, ref } from "vue";
const Acom = ref(null)
onMounted(() => {
console.log(Acom.value, '获取子组件信息')
})
</script>
但子组件中定义的一些变量和方法我们是无法获取到的,此时在子组件中通过defineExpose将想要被父组件访问到的内容暴露出来,我们就可以在Acom.value中获取到啦
子组件:
<script setup>
import { onMounted, ref } from "vue";
const paramsA = ref(12)
const paramsB = '这是一段固定的字符串'
defineExpose({
paramsA,
paramsB,
addCurCount
})
</script>
2.2 setup语法糖结合组件库的使用
结合普通script形式及setup script,对比一下增加setup语法糖后我们的代码会发生哪些不同的地方
- 引入ant-design-vue组件库 main.js
import { Form, Input, Checkbox, Button } from "ant-design-vue";
import 'ant-design-vue/dist/antd.css';
app.use(Form);
app.use(Input);
app.use(Checkbox);
app.use(Button);
- 相同的html结构
<template>
<a-form
:model="formState"
name="basic"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 16 }"
autocomplete="off"
@finish="onFinish"
@finishFailed="onFinishFailed"
>
<a-form-item
label="Username"
name="username"
:rules="[{ required: true, message: 'Please input your username!' }]"
>
<a-input v-model:value="formState.username" />
</a-form-item>
<a-form-item
label="Password"
name="password"
:rules="[{ required: true, message: 'Please input your password!' }]"
>
<a-input-password v-model:value="formState.password" />
</a-form-item>
<a-form-item name="remember" :wrapper-col="{ offset: 8, span: 16 }">
<a-checkbox v-model:checked="formState.remember">Remember me</a-checkbox>
</a-form-item>
<a-form-item :wrapper-col="{ offset: 8, span: 16 }">
<a-button type="primary" html-type="submit">Submit</a-button>
</a-form-item>
</a-form>
</template>
- 在页面中的使用 setup方式
<script setup>
import { reactive } from "vue";
const formState = reactive({
username: "",
password: "",
remember: true,
});
const onFinish = (values) => {
console.log("Success", values);
};
const onFinishFailed = (errorInfo) => {
console.log("Failed:", errorInfo);
};
</script>
- script方式JS内容
<script>
import { defineComponent, reactive } from 'vue';
export default defineComponent({
setup() {
const formState = reactive({
username: '',
password: '',
remember: true,
});
const onFinish = values => {
console.log('Success:', values);
};
const onFinishFailed = errorInfo => {
console.log('Failed:', errorInfo);
};
return {
formState,
onFinish,
onFinishFailed,
};
},
});
</script>
对比后即可发现,setup语法糖形式代码行数明显减少,更加清晰明了,易于阅读
2.3 setup语法糖中使用TypeScript
- 在使用ts时,在script setup标签中增加
lang="ts" - 内容中ts与正常使用情况下一致
- 将上述js改为ts形式如下
<script setup lang="ts">
import { reactive } from "vue";
interface FormState {
username: string;
password: string;
remember: boolean;
}
const formState = reactive<FormState>({
username: "",
password: "",
remember: true,
});
const onFinish = (values: any) => {
console.log("Success", values);
};
const onFinishFailed = (errorInfo: any) => {
console.log("Failed:", errorInfo);
};
</script>
3. setup与普通的script同时使用
<script setup>可以和普通的<script>一起使用。普通的<script>在有这些需要的情况下会被使用到:
- 声明无法在
<script setup>中声明的选项。例如inheritAttrs或插件的自定义选项 - 声明模块的具名导出
- 运行系需要在模块作用域执行一次的副作用,或是创建单例对象
<script>
// 普通 <script>, 在模块作用域下执行 (仅一次)
runSideEffectOnce()
// 声明额外的选项
export default {
inheritAttrs: false,
customOptions: {}
}
</script>
<script setup>
// 在 setup() 作用域中执行 (对每个实例皆如此)
</script>
4. 限制
由于模块执行语义的差异,<script setup>中的代码依赖单文件组件的上下文。当将其移动到外部的.js 或者 .ts文件中的时候,对于开发者和工具来说都会感到混乱。因此<script setup>不能和src属性一起使用。
如果有用,点个赞呗~
总结用法,希望可以帮助到你,
我是Ably,你无须超越谁,只要超越昨天的自己就好~
本文详细介绍了Vue3.0中的setup语法糖,包括安装Vue3.0,setup的基本用法,如响应式、组件、自定义指令、props与emits的定义,以及与typescript的结合使用。通过示例展示了setup如何简化代码,提高性能,并提到了与普通<script>标签的配合使用场景。最后,强调了setup在TypeScript环境下的应用。

被折叠的 条评论
为什么被折叠?



