vue3.2已经发了一段时间了,也用了一段时间,特别setup语法用起来特顺手,有种回不去的感觉,下面就分享我这一段时间的感受以及体验的效果,总结学习,共同进步。
下来说下好处:此处偷个懒,直接复制官网的
- 更少的样板内容,更简洁的代码。
- 能够使用纯 Typescript 声明 props 和抛出事件。
- 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
- 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)。
我们首先看下setup语法:
1. props
先来看下3.2之前的声明props写法
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
props: {
name: {
type: String,
default: '',
},
},
setup(props, context) {
console.log(props, context);
},
});
</script>
3.2 <script setup>语法
defineProps和defineEmits都是只在<script setup>中才能使用的编译器宏。
他们不需要导入且会随着<script setup>处理过程一同被编译掉。
在<script setup>中必须使用defineProps和defineEmitsAPI 来声明props和emits
<script setup>
const props = defineProps({
name: {
type: String,
default: '',
},
});
console.log(props);
const testlick = () => {
console.log('test');
};
</script>
这样写是不是简洁很多,使用也更加方便了。我们先看下编译后的文件
里面的代码会被编译成组件
setup()函数的内容。这意味着与普通的<script>只在组件被首次引入的时候执行一次不同,<script setup>中的代码会在每次组件实例被创建的时候执行。
我们看到最后的编译结果和我们之前的Vue3.2之前语法是一样,他会把我们的声明变量,函数,以及 import 引入的内容都会暴露在最顶层,所以任何在 <script setup> 声明的顶层的绑定都能在模板中直接使用。
如果使用eslint报错的话,可以在eslint.js添加
// eslint.js
module.exports = {
globals: {
defineEmits: true,
defineProps: true,
}
}
2. emit
在
<script setup>中必须使用defineProps和defineEmitsAPI 来声明props和emits
我们在使用emit必须声明我们使用的事件名,例如:['change','update:modelValue'],可以多个声明,用都好隔开
我们使用最常用的双向绑定例子,来看下代码以及编译后的代码,看过后你就会更加清晰。
<script setup>
import { computed } from 'vue';
const props = defineProps({
modelValue: {
type: String,
default: '',
},
});
const emit = defineEmits(['update:modelValue']);
const inputValue = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value),
});
</script>
3. 组件
<script setup> 中的组件可以直接使用引入标签名,不用在使用components声明
<template>
<Test />
</template>
<script setup>
import Test from './index.vue';
</script>
<style lang="scss" scoped>
</style>
是不是很方便,不用担心组件没有声明报错了,我们来看下编译的代码
我们来看下createBlock方法,是创建是一个vnode节点,在组件打开的时候把这个vnode添加到父组件中,关闭的时候删除节点,这样就实现了直接可以使用引入的标签名使用组件。有兴趣的可以去研究下源码
4. useSlots 和 useAttrs
如果想要获取slots和attrs,可以使用这两个api,这个不是经常使用
<script setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>
5. defineExpose
使用
<script setup>的组件是默认关闭的,也即通过模板 ref 或者$parent链获取到的组件的公开实例,不会暴露任何在<script setup>中声明的绑定。
vue2我们可以用$ref.获取设置ref组件的方法以及属性,如果使用script setup是获取不到,我们先打印下数据看下效果.
通过getCurrentInstance()获取实例,首先看下没有使用defineExpose之前的打印效果
我们打印下ref,看下vue3的打印结果
看下使用defineExpose后的实例
ref获取的效果
可以看到如果没有导出, $ref方式是获取不到的其方法或者属性的。
6. 和普通的<script>一起使用
我们有时候要用的另外的scritp处理其他的逻辑
例如:
<script>
export default {
name: 'Test',
inheritAttrs: false,
customOptions: {},
...
}
</script>
我们看到使用Object.assign合并的方式,这种方式优先取<scritpt setup>的方法和属性。
<script>
const a = 123;
const confirmHandler = ()=> {
console.log(6666)
}
</script>
<script setup>
import { ref } from 'vue';
const emit = defineEmits(['change', 'confirm']);
const confirmHandler = () => {
emit('confirm', multipleSelection.value);
};
const search = ref('');
const changeHandle = () => {
const list = { page: currentPage.value };
if (search.value) list.search = search.value;
emit('change', list);
};
defineExpose({
changeHandle,
confirmHandler
})
</script>