前言#
很早之前就看见尤大在说 <script setup> + TS + Volar = 真香,但一直都没有去主动尝试过
前段时间恰好在网上看见了相关的项目,好奇心又被调动了,想着也没什么事,也便在这个暑假跟着视频去尝试做了一下,在使用<script setup>语法糖和 ts 的时候,遇见了不少的问题,也在这个项目完成的过程中感受到了<script setup> +ts的酸爽感,不得不说,确实很舒服哈哈哈🤣
话不多说了,直接来说开发项目时感受到的优点和自己在开发过程中遇见的一些问题
優點:#
更簡潔的代碼#
在 vue3.2 中,正式支持了<script setup>語法糖,減少了大量的重複模板代碼,引入的組件無需再註冊後才能使用,只要引入後即可在 sfc 中使用,直接用代碼來展示可能效果更好:
<template>
<Header />
</template>
<script setup>
//引入後可直接使用,無需註冊
import Header from './header.vue'
</script>
不僅僅是組件的引入無需單獨註冊,包括函數與變量的聲明也大大減少了代碼量。使用<script setup>無需再return變量的值,對於函數,也無需再通過methods選項來將其暴露,可直接在 setup 中寫出函數,官方文檔的代碼實例如下:
<script setup>
// 變量
const msg = 'Hello!'
// 函數
function log() {
console.log(msg)
}
</script>
<template>
<button @click="log">{{ msg }}</button>
</template>
項目接口更加詳細#
在該項目中,我所使用的是 mock.js 來寫接口,通過import '@/mock/index'讓接口跑起來。在實際項目中,我需要調用接口時,需要先用 typescript 進行接口定義,雖然這會在一定程度上增加代碼量,但對於中大型項目來說會更便於維護,在調用接口的時候也會有代碼提示,這也是 ts 的優勢了。
代碼示例如下:
<script setup lang="ts">
import { ref } from 'vue'
import axios from 'axios'
// ts定義接口
interface Iswiper {
imgSrc: string
link: string
}
const list = ref<Iswiper[]>([])
axios({
url: '/swiperList',
method: 'get'
}).then((res) => {
console.log(res.data.result)
list.value = res.data.result
})
</script>
當我們將鼠標放上去時,便會出現提示:
,這極大的方便了我們對接口的調用和後期的維護,對 ts 中的詳細教程可以看這篇文章,可以更深入的了解interface
項目開發過程遇見的問題#
路由無法跳轉#
這裡犯的錯誤其實還是因為自己對<script setup>掌握的不夠好。當我想要點擊搜索按鈕進行跳轉的時候,出現了報錯 ———— 無論怎麼點擊都沒有反應。本想在<script setup>中直接使用this.$router.push來進行跳轉,但此刻 setup 還未執行,並沒有 vue 實例,更別提this了
翻看vue-router官方文檔,其實可以很清楚的看見官方對此的解釋:
由於 setup 執行時機在 beforeCreate 之前,故在 setup 中是不能使用 data 和 methods (因為還沒初始化好)。由於不能再 setup 函數中使用 data 和 methods, 所以 Vue 為了避免我們錯誤的使用,它直接將 setup 函數中的 this 修改成 undefined.
但由於本項目中的搜索圖標是標籤,所以也就沒必要使用useRouter函數了,直接在<a>標籤上進行添加即可:

注意,由於我們是默認路由hash, 故此處不可以直接添加為/search,否則不會進行頁面的跳轉,應在前面再添加一個#
無法修改組件樣式#
無法修改組件樣式的情況在之前的項目中也遇見過,element plus組件默認的樣式無法修改,在vant3中也遇見了同樣的問題,我們自己寫的樣式被覆蓋,這裡就直接進行樣式穿透即可,使用方法: ::deep 想要修改類名 { 修改樣式 }:
CSS module#
在我對登錄界面進行樣式修改的時候出現了問題,我無法將整體的頁面背景修改成灰色,我通過對body的樣式修改,發現不起作用,如果直接刪除vue單文件組件的<style scoped>中的scoped便可以樣式生效了,但這樣帶來的副作用就是無法再對樣式私有化,會污染全局
這時候便有兩個解決方法:
單獨再開一個 style#
通過再開一個<style>的方式,單獨對 body 進行一個渲染
使用全局作用域#
CSS Modules 允許使用:global(.className)的語法,聲明一個全局規則
關於 CSS Moudles 的詳細情況可以參考阮一峰老師的這篇文章:CSS Modules 用法教程
defineExpose#
在使用vant3組件的時候,由於他的文檔實例並未像element plus一樣直接用的
結果我登錄界面的輸入框全都不見了.... 一想便知道,估計又是setup語法糖沒把握好的鍋,連忙去翻看 vue 官方文檔,不出意外的找到了問題的原因:事實上,獲取到組件的公開實例的,需要用到definExpose
使用
<script setup>的組件是默認關閉的 —— 即通過模板 ref 或者$parent鏈獲取到的組件的公開實例,不會暴露任何在<script setup>中聲明的綁定。通過
defineExpose編譯器宏來顯式指定在<script setup>組件中要暴露出去的 property
注意,definExpose是需要手動導入的
總結#
<script setup> + TS + Volar 是真的太爽了,雖然我對<script setup>語法糖的掌握還是不夠,導致開發過程中出現了一系列的問題,不過還是能感受到語法糖的魅力的,最後淺淺的附上項目及源碼地址