拙见:本人初次接触vue3还是一年多前,当时是通过改造一个旧的小项目来达到熟悉vue3的目的。但一顿代码敲下来,却让我陷入了迷茫,vue3冗长的return以及数据、方法都放在一起,不像vue2有一个明确的模块区分,使我很不适应。后来也是因为没有强制要求,而渐渐放下来vue3的学习。直到今年八月份入职新公司后,由于公司内部整体框架都是用的vite+vue3,所以在进行项目开发时又重新接触了vue3相关的知识,不过这次是带有setup语法糖的vue3。经过两个月的实操下来,不得不说,曾经让我排斥的vue3,现在感觉是那么的香。
因为setup语法糖的实现,最直观的感受就是数据和方法不用再进行冗长的return,在script和template中都可以直接使用。一些代码编写习惯也和vue2比较类似,所以对于vue2转vue3的同学学习起来也更友好。下面简单介绍一些,我接触到的语法糖的用法。
<template>
<div>{{msg}}</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
//变量声明
const msg = ref(666)
//方法声明
const showMsg = () =>{
console.log(msg.value)
}
//方法调用;console.log(666)
showMsg()
</script>
注意事项:在script中,获取数据值需要.value,在template中则不需要。
//因setup本身就是在created生命周期时执行,因此获取不到对应DOM元素,需要在nextTick 或者onMounted中去执行
<template>
<div ref="myRef"></div>
</template>
<script lang="ts" setup>
import { ref, onMounted,nextTick } from 'vue'
//变量声明,这里的声明需要和DOM元素的ref同名
const myRef = ref(null);
//方法一:onMounted
onMounted(() => {
//可以获取到DOM元素
console.log(myRef.value);
});
//方法二:nextTick
nextTick(() => {
//可以获取到DOM元素
console.log(myRef.value);
});
<template>
<div>{{newNum }}</div>
</template>
<script lang="ts" setup>
import { ref ,computed,watch} from 'vue'
//变量声明
const num = ref(1)
//computed使用
const newNum = computed({
return num+=1
})
//watch使用
watch(
() => num.value,
(newV,oldV) =>{
console.log(newV)//变化后值
console.log(oldV)//变化前值
},
{
immediate: true, // 立即执行
deep: true // 深度监听
}
)
</script>
<template>
<div>{{newNum }}</div>
</template>
<script lang="ts" setup>
import Child from '@/components/Child.vue'
</script>
注意事项:在 script setup 中,引入的组件可以直接使用,无需再通过components进行注册,并且无法指定当前组件的名字,它会自动以文件名为主,也就是不用再写name属性了。
<template>
<Child @getChild="getChild" :title="msg" />
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import Child from '@/components/Child.vue'
const msg = ref('parent value')
const getChild = (e) => {
// 接收子组件传递过来的数据
console.log(e); // child value
}
</script>
<template>
<div @click="toEmits">Child Components</div>
</template>
<script lang="ts" setup>
// defineEmits,defineProps无需导入,直接使用
const emits = defineEmits(['getChild']);
//ts中的写法,不带默认值
const props = defineProps<{
title:string
}>();
//ts中的写法,带默认值
const props = withDefaults(
defineProps<{
title:string
}>(),
//默认值
{
title:'child value'
}
)
const toEmits = () => {
emits('getChild', 'child value') // 向父组件传递数据
}
// 获取父组件传递过来的数据,不需要后缀.value
console.log(props.title); // parent value
</script>
<template>
<Child v-model:dataValue = "msg"/>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import Child from '@/components/Child.vue'
const msg = ref('666')
</script>
<template>
<el-select v-model="value">
//省略组件部分详细代码
<el-options.....>
</el-select>
</template>
<script lang="ts" setup>
//update后缀要与父组件v-model后缀名称相同
const emits = defineEmits(['update:dataValue']);
const props = defineProps<{
dataValue:string
}>();
const value = computed({
get:()=>{
//value赋值为接收到的值
return props.dataValue;
},
set:(newV)=>{
//value值改变后传递给父组件
emit('update:dataValue',newV)
}
})
</script>
<template>
<Child ref="child" />
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import Child from '@/components/Child.vue'
const child = ref();
onMounted(() => {
console.log(child.value.msg); // Child Components
console.log(child.value.num); // 123
})
</script>
<template>
{{msg}}
</template>
<script lang="ts" setup>
import { ref } from 'vue'
let msg = ref("Child Components");
let num = ref(123);
// defineExpose无需导入,直接使用
defineExpose({
msg,
num
});
</script>
注意事项:script setup 的组件默认不会对外部暴露任何内部声明的属性。
如果有部分属性要暴露出去,可以使用 defineExpose