vue3與ts組件封裝提高代碼復(fù)用性
引言
對(duì)于一名前端程序員來說封裝組件是一個(gè)必備技能。當(dāng)我們?cè)谌粘5墓ぷ髦锌傆兴玫慕M件庫滿足不了需求的情況,這就需要我們有封裝組件的基本功了。 封裝組件,可以提高我們代碼的復(fù)用性,提高工作效率,提高代碼的可閱讀性。
組件我自己的理解的話,分為兩種吧,一種是工具類的組件,一種是頁面級(jí)別的組件,工具類的組件就是說封裝后,在以后的項(xiàng)目中如果用相同的應(yīng)用場(chǎng)景時(shí),可復(fù)用。頁面類組件的話就是將一個(gè)大的頁面分成很多的小組件,然后進(jìn)行拼接,組成大頁面,讓頁面看起來不臃腫,美觀,提高代碼的閱讀性。方便后期的維護(hù)管理。
輪播圖組件的封裝
在父組件中留出位置放子組件(子組件為全局組件。)在pinia中發(fā)送請(qǐng)求拿數(shù)據(jù) 在拿到數(shù)據(jù)后cope value 去拿泛型。父?jìng)髯拥姆绞饺ピ谧咏M件中接收數(shù)據(jù),在子組件中去做相應(yīng)的業(yè)務(wù)邏輯,自動(dòng)播放,按鈕,前進(jìn)后退等功能。
在pinia中發(fā)請(qǐng)求拿到數(shù)據(jù)
import request from '@/utils/request' import { defineStore } from 'pinia' import {IApiRes, banneritem } from '@/types/data' export default defineStore('home',{ state:()=>{ return{ bannerlist: [] as banneritem[] } }, actions:{ // 獲取輪播圖數(shù)據(jù) async getBannerList(){ const res = await request.get<IApiRes<banneritem[]>>('/home/banner') console.log(res,'2222222'); this.bannerlist = res.data.result },
types/data中進(jìn)行泛型補(bǔ)充:
// 所有的接口的通用類型 export interface IApiRes<T> { code: string msg: string result: T } // banner輪播圖類型 export type banneritem={ id: string; imgUrl: string; hrefUrl: string; type: string; }
父組件中
<script lang="ts" setup> import useStore from '@/store'; //子組件引入 import Carousel from '@/components/Carousel/index.vue'; const { home} = useStore() home.getBannerList() </script> <template> <div class="home-banner"> <!-- 輪播圖 --> <!-- <carousel :slides="home.Bannerlist" :autoPlay="true" :duration="2000"></carousel> --> <Carousel :slides="home.bannerlist" :autoplay="true" :duration="2000" ></Carousel> </div> </template>
在父組件中使用傳入相應(yīng)的參數(shù)即可。
在子組件中
相應(yīng)的樣式及業(yè)務(wù)邏輯,都有注釋,我就不一一寫了。
<script lang="ts" setup name="Carousel"> import { banneritem } from '@/types/data'; import { onBeforeMount, onMounted, ref } from 'vue'; // 接收父組件傳過來的數(shù)據(jù) const {slides, autoplay=true, duration=3000} = defineProps<{ slides:banneritem[], autoplay:boolean, duration:number }>() // 當(dāng)前選擇的是那一張圖片。 let active = ref(0) // 左側(cè)箭頭 const hleft = ()=>{ active.value-- if(active.value < 0){ active.value = slides.length-1 } } // 右側(cè)箭頭 const hright = ()=>{ active.value++ if(active.value > slides.length - 1){ active.value = 0 } } let timer = -1 // 鼠標(biāo)離開開啟自動(dòng)播放 const start = ()=>{ if(autoplay){ // 在ts中,使用定時(shí)器,注意:window.setInterval timer =window.setInterval(()=>{ hright() },duration) } } // 鼠標(biāo)進(jìn)入停止自動(dòng)播放 const stop = ()=>{ clearInterval(timer) } // 點(diǎn)擊小圓點(diǎn)跳轉(zhuǎn) const ind= (id:number)=>{ active.value = id } //在頁面加載時(shí) 自動(dòng)播放 onMounted(()=>{ start() }) // 在頁面關(guān)閉時(shí),銷毀組件 停止播放 onBeforeMount(()=>{ stop() }) </script> <template> <!-- fade類表示當(dāng)前圖片可見 --> <div class="xtx-carousel" @mouseleave="start" @mouseenter="stop" > <ul class="carousel-body"> <li class="carousel-item " :class="{fade :index === active}" v-for="(item,index ) in slides" :key="item.id"> <RouterLink to="/"> <img :src="item.imgUrl" alt="" /> </RouterLink> </li> </ul> <!-- 左邊箭頭 --> <a href="javascript:;" rel="external nofollow" rel="external nofollow" class="carousel-btn prev" @click="hleft" ><i class="iconfont icon-angle-left"></i ></a> <!-- 右邊箭頭 --> <a href="javascript:;" rel="external nofollow" rel="external nofollow" class="carousel-btn next" @click="hright" ><i class="iconfont icon-angle-right"></i ></a> <!-- 小圓點(diǎn) --> <div class="carousel-indicator"> <span v-for="(item,index) in slides" :key="item.id" :class="{active:active === index}" @mouseenter="ind(index)" ></span> </div> </div> </template> <style scoped lang="less"> .xtx-carousel { width: 100%; height: 100%; min-width: 300px; min-height: 150px; position: relative; .carousel { &-body { width: 100%; height: 100%; } &-item { width: 100%; height: 100%; position: absolute; left: 0; top: 0; opacity: 0; transition: opacity 0.5s linear; &.fade { opacity: 1; z-index: 1; } img { width: 100%; height: 100%; } } &-indicator { position: absolute; left: 0; bottom: 20px; z-index: 2; width: 100%; text-align: center; span { display: inline-block; width: 12px; height: 12px; background: rgba(0, 0, 0, 0.2); border-radius: 50%; cursor: pointer; ~ span { margin-left: 12px; } &.active { background: #fff; } } } &-btn { width: 44px; height: 44px; background: rgba(0, 0, 0, 0.2); color: #fff; border-radius: 50%; position: absolute; top: 228px; z-index: 2; text-align: center; line-height: 44px; opacity: 0; transition: all 0.5s; &.prev { left: 20px; } &.next { right: 20px; } } } &:hover { .carousel-btn { opacity: 1; } } } </style>
以上就是vue3與ts組件封裝提高代碼復(fù)用性的詳細(xì)內(nèi)容,更多關(guān)于vue3與ts組件封裝的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue中element 的upload組件發(fā)送請(qǐng)求給后端操作
這篇文章主要介紹了vue中element 的upload組件發(fā)送請(qǐng)求給后端操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09基于vue+echarts數(shù)據(jù)可視化大屏展示的實(shí)現(xiàn)
這篇文章主要介紹了基于vue+echarts數(shù)據(jù)可視化大屏展示的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12vue3.0使用taro-ui-vue3引入組件不生效的問題及解決
這篇文章主要介紹了vue3.0使用taro-ui-vue3引入組件不生效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03v-for循環(huán)中使用require/import關(guān)鍵字引入本地圖片的幾種方式
在做項(xiàng)目的過程中,模版相同,可是不標(biāo)題和圖片不同,循環(huán)標(biāo)題我們知道可以用v-for循環(huán),可是該怎么引入本地圖片呢?下面這篇文章主要給大家介紹了v-for循環(huán)中使用require/import關(guān)鍵字引入本地圖片的幾種方式,需要的朋友可以參考下2021-09-09vue.js評(píng)論發(fā)布信息可插入QQ表情功能
這篇文章主要為大家詳細(xì)介紹了vue.js評(píng)論發(fā)布信息可插入QQ表情功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08vue實(shí)現(xiàn)裁切圖片同時(shí)實(shí)現(xiàn)放大、縮小、旋轉(zhuǎn)功能
這篇文章主要介紹了vue實(shí)現(xiàn)裁切圖片同時(shí)實(shí)現(xiàn)放大、縮小、旋轉(zhuǎn)功能,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03vue實(shí)現(xiàn)購物車拋物線小球動(dòng)畫效果的方法詳解
這篇文章主要介紹了vue實(shí)現(xiàn)購物車拋物線小球動(dòng)畫效果的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了vue.js實(shí)現(xiàn)拋物線動(dòng)畫效果購物車功能相關(guān)原理與操作注意事項(xiàng),需要的朋友可以參考下2019-02-02