国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

分析 vant4 源碼,學會用 vue3 + ts 開發(fā)毫秒級渲染的倒計時組件,真是妙啊

這篇具有很好參考價值的文章主要介紹了分析 vant4 源碼,學會用 vue3 + ts 開發(fā)毫秒級渲染的倒計時組件,真是妙啊。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

2022年11月23日首發(fā)于掘金,現(xiàn)在同步到公眾號。

11. 前言

大家好,我是若川。推薦點右上方藍字若川視野把我的公眾號設為星標。我傾力持續(xù)組織了一年多源碼共讀,感興趣的可以加我微信 lxchuan12 參與。另外,想學源碼,極力推薦關注我寫的專欄《學習源碼整體架構系列》,目前是掘金關注人數(shù)(4.6k+人)第一的專欄,寫有20余篇源碼文章。


我們開發(fā)業(yè)務時經(jīng)常會使用到組件庫,一般來說,很多時候我們不需要關心內部實現(xiàn)。但是如果希望學習和深究里面的原理,這時我們可以分析自己使用的組件庫實現(xiàn)。有哪些優(yōu)雅實現(xiàn)、最佳實踐、前沿技術等都可以值得我們借鑒。

相比于原生 JS 等源碼。我們或許更應該學習,正在使用的組件庫的源碼,因為有助于幫助我們寫業(yè)務和寫自己的組件。

如果是 Vue 技術棧,開發(fā)移動端的項目,大多會選用 vant 組件庫,目前(2022-11-20)star 多達 20.5k,最新版本是 v4.0.0-rc7。我們可以挑選 vant 組件庫學習,我會寫一個組件庫源碼系列專欄[1],歡迎大家關注。

  • vant 4 即將正式發(fā)布,支持暗黑主題,那么是如何實現(xiàn)的呢

  • 跟著 vant4 源碼學習如何用 vue3+ts 開發(fā)一個 loading 組件,僅88行代碼

  • 分析 vant4 源碼,如何用 vue3 + ts 開發(fā)一個瀑布流滾動加載的列表組件?

這次我們來學習倒計時組件,`countdown`[2]。

學完本文,你將學到:

1.?如何開發(fā)一個更優(yōu)雅的毫秒級渲染的倒計時組件
2.?學會使用?requestAnimationFrame
3.?等等

22. 準備工作

看一個開源項目,我們可以先看 README.md[3] 再看 github/CONTRIBUTING.md[4]

2.1 克隆源碼

You will need Node.js >= 14[5] and pnpm[6].

#?推薦克隆我的項目
git?clone?https://github.com/lxchuan12/vant-analysis
cd?vant-analysis/vant

#?或者克隆官方倉庫
git?clone?git@github.com:vant-ui/vant.git
cd?vant

#?安裝依賴,如果沒安裝?pnpm,可以用?npm?i?pnpm?-g?安裝,或者查看官網(wǎng)通過其他方式安裝
pnpm?i

#?啟動服務
pnpm?dev

執(zhí)行 pnpm dev 后,這時我們打開倒計時組件 http://localhost:5173/#/zh-CN/count-down

33. 倒計時組件可謂是十分常用

在各種電商類或者其他的移動端頁面中,倒計時真的是太常見了。我們自己也基本能夠快速的寫一個倒計時組件。代碼實現(xiàn)參考這里,主要是 JavaScript。碼上掘金倒計時初步代碼@若川[7]

代碼中,我直接使用的 setInterval 和每秒鐘執(zhí)行一次。把倒計時的時候減去1s,當?shù)褂嫊r毫秒數(shù)不足時用 clearInterval 清除停止定時器。

但如果要實現(xiàn)毫秒級的倒計時這種方法行不通。 另外 setInterval 這種做法,并不是最優(yōu)的。 那么,vant 倒計時組件中,是如何處理毫秒級和實現(xiàn)倒計時呢。

帶著問題我們直接找到 countdown demo 文件:vant/packages/vant/src/count-down/demo/index.vue。為什么是這個文件,我在之前文章跟著 vant4 源碼學習如何用 vue3+ts 開發(fā)一個 loading 組件,僅88行代碼分析了其原理,感興趣的小伙伴點擊查看。這里就不贅述了。

44. 利用 demo 調試源碼

組件源碼中的 TS 代碼我不會過多解釋。沒學過 TS 的小伙伴,推薦學這個TypeScript 入門教程[8]。 另外,vant 使用了 @vue/babel-plugin-jsx[9] 插件來支持 JSX、TSX。

分析 vant4 源碼,學會用 vue3 + ts 開發(fā)毫秒級渲染的倒計時組件,真是妙啊
倒計時組件
//?vant/packages/vant/src/count-down/demo/index.vue
<script?setup?lang="ts">
import?VanGrid?from?'../../grid';
import?VanGridItem?from?'../../grid-item';
import?VanCountDown,?{?type?CountDownInstance?}?from?'..';
import?{?ref?}?from?'vue';
import?{?useTranslate?}?from?'../../../docs/site';
import?{?showToast?}?from?'../../toast';

const?t?=?useTranslate({
??'zh-CN':?{
????reset:?'重置',
????pause:?'暫停',
????start:?'開始',
????finished:?'倒計時結束',
????millisecond:?'毫秒級渲染',
????customStyle:?'自定義樣式',
????customFormat:?'自定義格式',
????manualControl:?'手動控制',
????formatWithDay:?'DD?天?HH?時?mm?分?ss?秒',
??},
});

const?time?=?ref(30?*?60?*?60?*?1000);
const?countDown?=?ref<CountDownInstance>();

//?開始
const?start?=?()?=>?{
??countDown.value?.start();
};
//?暫停
const?pause?=?()?=>?{
??countDown.value?.pause();
};
//?重置
const?reset?=?()?=>?{
??countDown.value?.reset();
};
const?onFinish?=?()?=>?showToast(t('finished'));
</script>

<template>

??<!--?基本使用?-->
??<demo-block?:title="t('basicUsage')">
????<van-count-down?:time="time"?/>
??</demo-block>

??<!--?自定義渲染?-->
??<demo-block?:title="t('customFormat')">
????<van-count-down?:time="time"?:format="t('formatWithDay')"?/>
??</demo-block>

??<!--?毫秒級渲染?-->
??<demo-block?:title="t('millisecond')">
????<van-count-down?millisecond?:time="time"?format="HH:mm:ss:SS"?/>
??</demo-block>

??<!--?自定義樣式-->
??<demo-block?:title="t('customStyle')">
????<van-count-down?:time="time">
??????<template?#default="currentTime">
????????<span class="block">{{?currentTime.hours?}}</span>
????????<span?class="colon">:</span>
????????<span?class="block">{{?currentTime.minutes?}}</span>
????????<span?class="colon">:</span>
????????<span?class="block">{{?currentTime.seconds?}}</span>
??????</template>
????</van-count-down>
??</demo-block>

??<!--?手動控制?-->
??<demo-block?:title="t('manualControl')">
????<van-count-down
??????ref="countDown"
??????millisecond
??????:time="3000"
??????:auto-start="false"
??????format="ss:SSS"
??????@finish="onFinish"
????/>
????<van-grid?clickable?:column-num="3">
??????<van-grid-item?icon="play-circle-o"?:text="t('start')"?@click="start"?/>
??????<van-grid-item?icon="pause-circle-o"?:text="t('pause')"?@click="pause"?/>
??????<van-grid-item?icon="replay"?:text="t('reset')"?@click="reset"?/>
????</van-grid>
??</demo-block>
</template>

demo 文件中,我們可以看出 import VanCountDown, { type CountDownInstance } from '..';,引入自 vant/packages/vant/src/count-down/index.ts。我們繼續(xù)來看入口 index.ts。

55. 入口 index.ts

主要就是導出一下類型和變量等。

//?vant/packages/vant/src/count-down/index.ts
import?{?withInstall?}?from?'../utils';
import?_CountDown?from?'./CountDown';

export?const?CountDown?=?withInstall(_CountDown);
//?默認導出
//?import?xxx?from?'vant'
export?default?CountDown;
export?{?countDownProps?}?from?'./CountDown';
export?type?{?CountDownProps?}?from?'./CountDown';
export?type?{
??CountDownInstance,
??CountDownThemeVars,
??CountDownCurrentTime,
}?from?'./types';

declare?module?'vue'?{
??export?interface?GlobalComponents?{
????VanCountDown:?typeof?CountDown;
??}
}

withInstall 函數(shù)在之前文章5.1 withInstall 給組件對象添加 install 方法 也有分析,這里就不贅述了。

我們可以在這些文件,任意位置加上 debugger 調試源碼。

截兩張調試圖。

調試 Countdown setup。

分析 vant4 源碼,學會用 vue3 + ts 開發(fā)毫秒級渲染的倒計時組件,真是妙啊
調試 setup

調試 useCountDown

分析 vant4 源碼,學會用 vue3 + ts 開發(fā)毫秒級渲染的倒計時組件,真是妙啊
調試 useCountDown

我們跟著調試,繼續(xù)分析 Countdown

66. 主文件 Countdown

//?vant/packages/vant/src/count-down/CountDown.tsx
import?{?watch,?computed,?defineComponent,?type?ExtractPropTypes?}?from?'vue';

//?Utils
import?{
??truthProp,
??makeStringProp,
??makeNumericProp,
??createNamespace,
}?from?'../utils';
import?{?parseFormat?}?from?'./utils';

//?Composables
import?{?useCountDown?}?from?'@vant/use';
import?{?useExpose?}?from?'../composables/use-expose';

const?[name,?bem]?=?createNamespace('count-down');

export?const?countDownProps?=?{
??time:?makeNumericProp(0),
??format:?makeStringProp('HH:mm:ss'),
??autoStart:?truthProp,
??millisecond:?Boolean,
};

export?type?CountDownProps?=?ExtractPropTypes<typeof?countDownProps>;

export?default?defineComponent({
??name,

??props:?countDownProps,

??emits:?['change',?'finish'],

??setup(props,?{?emit,?slots?})?{
????//?代碼省略,下文敘述
??},
});

6.1 setup 部分

這一部分主要使用了useCountDown。

setup(props,?{?emit,?slots?})?{
??//?useCountDown?組合式?API
??const?{?start,?pause,?reset,?current?}?=?useCountDown({
????//?傳入的時間毫秒數(shù),+?是字符串轉數(shù)字
????time:?+props.time,
????//?毫秒級渲染
????millisecond:?props.millisecond,
????//?回調事件,onChange,?onFinish
????onChange:?(current)?=>?emit('change',?current),
????onFinish:?()?=>?emit('finish'),
??});

??//?格式化時間
??const?timeText?=?computed(()?=>?parseFormat(props.format,?current.value));

??//?重置,重新開始
??const?resetTime?=?()?=>?{
????reset(+props.time);

????if?(props.autoStart)?{
??????start();
????}
??};

??watch(()?=>?props.time,?resetTime,?{?immediate:?true?});

??//?導出?start、pause、reset
??useExpose({
????start,
????pause,
????reset:?resetTime,
??});

??return?()?=>?(
????//?有傳入插槽,使用插槽,支持自定義樣式,傳入解析后的時間對象
????<div?role="timer"?class={bem()}>
??????{slots.default???slots.default(current.value)?:?timeText.value}
????</div>
??);
},

6.2 useExpose 暴露

import?{?getCurrentInstance?}?from?'vue';
import?{?extend?}?from?'../utils';

//?expose?public?api
export?function?useExpose<T?=?Record<string,?any>>(apis:?T)?{
??const?instance?=?getCurrentInstance();
??//?合并到?getCurrentInstance().proxy?上
??if?(instance)?{
????extend(instance.proxy?as?object,?apis);
??}
}

通過 ref 可以獲取到 Countdown 實例并調用實例方法,詳見組件實例方法[10]

Vant 中的許多組件提供了實例方法,調用實例方法時,我們需要通過 ref 來注冊組件引用信息,引用信息將會注冊在父組件的 $refs 對象上。注冊完成后,我們可以通過 this.$refs.xxx 或者

const?xxxRef?=?ref();
xxxRef.value.xxx();

訪問到對應的組件實例,并調用上面的實例方法。

77. useCountDown 組合式 API

7.1 parseTime 解析時間

//?vant/packages/vant-use/src/useCountDown/index.ts
import?{
??ref,
??computed,
??onActivated,
??onDeactivated,
??onBeforeUnmount,
}?from?'vue';
import?{?raf,?cancelRaf,?inBrowser?}?from?'../utils';

export?type?CurrentTime?=?{
??days:?number;
??hours:?number;
??total:?number;
??minutes:?number;
??seconds:?number;
??milliseconds:?number;
};

export?type?UseCountDownOptions?=?{
??time:?number;
??//?毫秒
??millisecond?:?boolean;
??onChange?:?(current:?CurrentTime)?=>?void;
??onFinish?:?()?=>?void;
};

const?SECOND?=?1000;
const?MINUTE?=?60?*?SECOND;
const?HOUR?=?60?*?MINUTE;
const?DAY?=?24?*?HOUR;

//?解析時間
function?parseTime(time:?number):?CurrentTime?{
??const?days?=?Math.floor(time?/?DAY);
??const?hours?=?Math.floor((time?%?DAY)?/?HOUR);
??const?minutes?=?Math.floor((time?%?HOUR)?/?MINUTE);
??const?seconds?=?Math.floor((time?%?MINUTE)?/?SECOND);
??const?milliseconds?=?Math.floor(time?%?SECOND);

??return?{
????total:?time,
????days,
????hours,
????minutes,
????seconds,
????milliseconds,
??};
}

以上這大段代碼,parseTime 是主要函數(shù),解析時間,生成天數(shù)、小時、分鐘、秒、毫秒的對象。

7.2 useCountDown 真實邏輯

真實邏輯這一段可以不用細看??梢哉{試時再細看。

主要就是利用 Date.now() 會自己走的原理。

初始化開始:結束時間?=?當前時間戳?+?剩余時間
獲?。菏S鄷r間?=?結束時間?-?當前時間戳
加上自己定時器邏輯循環(huán)
剩余時間就是真實流逝的時間
如果是毫秒級渲染,就直接賦值剩余時間
如果不是,那就判斷是同一秒才賦值

設計的十分巧妙,看到這里,我們可能感慨:不得不佩服。

//?簡化版?一
const?useCountDown?=?(options)?=>?{
??let?endTime;
??let?remain?=?options.time;
??const?getCurrentRemain?=?()?=>?Math.max(endTime?-?Date.now(),?0);
??const?start?=?()?=>?{
????endTime?=?Date.now()?+?remain;
??}
??const?setRemain?=?(value)?=>?{
????remain?=?value;
??};
??return?{
????start,
??}
}
const?{?start?}?=?useCountDown({time:?3?*?1000});
start();

碼上掘金倒計時簡化版二

碼上掘金倒計時簡化版二@若川[11]

//?vant/packages/vant-use/src/useCountDown/index.ts
function?isSameSecond(time1:?number,?time2:?number):?boolean?{
??return?Math.floor(time1?/?1000)?===?Math.floor(time2?/?1000);
}

export?function?useCountDown(options:?UseCountDownOptions)?{
??let?rafId:?number;
??let?endTime:?number;
??let?counting:?boolean;
??let?deactivated:?boolean;

??const?remain?=?ref(options.time);
??const?current?=?computed(()?=>?parseTime(remain.value));

??const?pause?=?()?=>?{
????counting?=?false;
????cancelRaf(rafId);
??};

??const?getCurrentRemain?=?()?=>?Math.max(endTime?-?Date.now(),?0);

??const?setRemain?=?(value:?number)?=>?{
????remain.value?=?value;
????options.onChange?.(current.value);

????if?(value?===?0)?{
??????pause();
??????options.onFinish?.();
????}
??};

??const?microTick?=?()?=>?{
????rafId?=?raf(()?=>?{
??????//?in?case?of?call?reset?immediately?after?finish
??????if?(counting)?{
????????setRemain(getCurrentRemain());

????????if?(remain.value?>?0)?{
??????????microTick();
????????}
??????}
????});
??};

??const?macroTick?=?()?=>?{
????rafId?=?raf(()?=>?{
??????//?in?case?of?call?reset?immediately?after?finish
??????if?(counting)?{
????????const?remainRemain?=?getCurrentRemain();

????????if?(!isSameSecond(remainRemain,?remain.value)?||?remainRemain?===?0)?{
??????????setRemain(remainRemain);
????????}

????????if?(remain.value?>?0)?{
??????????macroTick();
????????}
??????}
????});
??};

??const?tick?=?()?=>?{
????//?should?not?start?counting?in?server
????//?see:?https://github.com/vant-ui/vant/issues/7807
????if?(!inBrowser)?{
??????return;
????}

????if?(options.millisecond)?{
??????microTick();
????}?else?{
??????macroTick();
????}
??};

??const?start?=?()?=>?{
????if?(!counting)?{
??????endTime?=?Date.now()?+?remain.value;
??????counting?=?true;
??????tick();
????}
??};

??const?reset?=?(totalTime:?number?=?options.time)?=>?{
????pause();
????remain.value?=?totalTime;
??};

??//?組件被卸載之前被調用
??onBeforeUnmount(pause);

??//?激活
??onActivated(()?=>?{
????if?(deactivated)?{
??????counting?=?true;
??????deactivated?=?false;
??????tick();
????}
??});

??onDeactivated(()?=>?{
????if?(counting)?{
??????pause();
??????deactivated?=?true;
????}
??});

??//?返回方法和當前時間對象
??return?{
????start,
????pause,
????reset,
????current,
??};
}

我們繼續(xù)來看 rafcancelRaf,是如何實現(xiàn)的。

88. raf、cancelRaf、inBrowser 實現(xiàn)

//?判斷是不是瀏覽器環(huán)境,你可能會問,為啥要判斷?因為?SSR?(服務端渲染)不是瀏覽器環(huán)境。
export?const?inBrowser?=?typeof?window?!==?'undefined';

//?Keep?forward?compatible
//?should?be?removed?in?next?major?version
export?const?supportsPassive?=?true;

export?function?raf(fn:?FrameRequestCallback):?number?{
??return?inBrowser???requestAnimationFrame(fn)?:?-1;
}

export?function?cancelRaf(id:?number)?{
??if?(inBrowser)?{
????cancelAnimationFrame(id);
??}
}

//?double?raf?for?animation
export?function?doubleRaf(fn:?FrameRequestCallback):?void?{
??raf(()?=>?raf(fn));
}

上文代碼,主要一個 API,requestAnimationFrame、cancelAnimationFrame。

我們這里簡單理解為 window.requestAnimationFrame() 中的回調函數(shù),每 16.67ms 執(zhí)行一次回調函數(shù)即可。

也就是類似 setTimeout、clearTimeout

const?timeId?=?setTimeout(?()?=>?{
??//?16.67ms?執(zhí)行一次
??console.log('16.67ms?執(zhí)行一次');
},?16.67);

clearTimeout(timeId);

也可以自行搜索這個 API 查閱更多資料。比如 MDN 上的解釋。

mdn window.requestAnimationFrame[12]

window.requestAnimationFrame() 告訴瀏覽器——你希望執(zhí)行一個動畫,并且要求瀏覽器在下次重繪之前調用指定的回調函數(shù)更新動畫。該方法需要傳入一個回調函數(shù)作為參數(shù),該回調函數(shù)會在瀏覽器下一次重繪之前執(zhí)行

回調函數(shù)執(zhí)行次數(shù)通常是每秒 60 次,但在大多數(shù)遵循 W3C 建議的瀏覽器中,回調函數(shù)執(zhí)行次數(shù)通常與瀏覽器屏幕刷新次數(shù)相匹配。

備注: 若你想在瀏覽器下次重繪之前繼續(xù)更新下一幀動畫,那么回調函數(shù)自身必須再次調用 window.requestAnimationFrame()

99. 支持格式化時間,默認 HH:mm:ss

9.1 parseFormat 處理格式化

再來看看,組件中,是如何格式化時間的。這個值得我們參考。我們很多時候可能都是寫死天數(shù)、小時等文案。不支持自定義格式化。

//?vant/packages/vant/src/count-down/utils.ts
import?{?padZero?}?from?'../utils';
import?{?CurrentTime?}?from?'@vant/use';

export?function?parseFormat(format:?string,?currentTime:?CurrentTime):?string?{
??const?{?days?}?=?currentTime;
??let?{?hours,?minutes,?seconds,?milliseconds?}?=?currentTime;

??//?有?DD?參數(shù),補零替換,沒有則小時數(shù)加上天數(shù)
??if?(format.includes('DD'))?{
????format?=?format.replace('DD',?padZero(days));
??}?else?{
????hours?+=?days?*?24;
??}

??//?有?HH?參數(shù),補零替換,沒有則分鐘數(shù)加上小時數(shù)
??if?(format.includes('HH'))?{
????format?=?format.replace('HH',?padZero(hours));
??}?else?{
????minutes?+=?hours?*?60;
??}

??//?有?mm?參數(shù),補零替換,沒有則秒數(shù)加上分鐘數(shù)
??if?(format.includes('mm'))?{
????format?=?format.replace('mm',?padZero(minutes));
??}?else?{
????seconds?+=?minutes?*?60;
??}

??//?有?mm?參數(shù),補零替換,沒有則毫秒數(shù)加上秒數(shù)
??if?(format.includes('ss'))?{
????format?=?format.replace('ss',?padZero(seconds));
??}?else?{
????milliseconds?+=?seconds?*?1000;
??}

??//?毫秒數(shù)?默認補三位數(shù),按照格式最終給出對應的位數(shù)
??if?(format.includes('S'))?{
????const?ms?=?padZero(milliseconds,?3);

????if?(format.includes('SSS'))?{
??????format?=?format.replace('SSS',?ms);
????}?else?if?(format.includes('SS'))?{
??????format?=?format.replace('SS',?ms.slice(0,?2));
????}?else?{
??????format?=?format.replace('S',?ms.charAt(0));
????}
??}

??//?最終返回格式化的數(shù)據(jù)
??return?format;
}

9.2 padZero 補零

//?vant/packages/vant-compat/node_modules/vant/src/utils/format.ts
//?補零操作
export?function?padZero(num:?Numeric,?targetLength?=?2):?string?{
??let?str?=?num?+?'';

??while?(str.length?<?targetLength)?{
????str?=?'0'?+?str;
??}

??return?str;
}

行文自此,我們就分析完了毫秒級渲染的倒計時組件的實現(xiàn)。

1010. 總結

我們來簡單總結下。通過 demo 文件調試,入口文件,主文件,useCountDown 組合式 API,插槽等。 分析了自定義格式、毫秒級渲染、自定義樣式(利用插槽)等功能的實現(xiàn)。

其中毫秒級渲染,主要就是利用 Date.now() 和 (window.requestAnimationFrame)每 16.67ms 執(zhí)行一次回調函數(shù)。

大致流程如下:

初始化開始:結束時間?=?當前時間戳?+?剩余時間
獲?。菏S鄷r間?=?結束時間?-?當前時間戳
加上自己定時器邏輯循環(huán)(`window.requestAnimationFrame`)每?16.67ms?執(zhí)行一次回調函數(shù)
剩余時間就是真實流逝的時間
如果是毫秒級渲染,就直接賦值剩余時間
如果不是,那就判斷是同一秒才賦值

看完這篇源碼文章,再去看 CountDown 組件文檔[13],可能就會有豁然開朗的感覺。再看其他組件,可能就可以猜測出大概實現(xiàn)的代碼了。

如果是使用 reactTaro 技術棧,感興趣也可以看看 taroify CountDown 組件的實現(xiàn) 文檔[14],源碼[15]。

如果看完有收獲,歡迎點贊、評論、分享支持。你的支持和肯定,是我寫作的動力

參考資料

[1]

組件庫源碼系列專欄: https://juejin.cn/column/7140264842954276871

[2]

countdown: https://vant-contrib.gitee.io/vant/v4/#/zh-CN/count-down

[3]

README.md: https://github.com/youzan/vant

[4]

github/CONTRIBUTING.md: https://github.com/youzan/vant/blob/main/.github/CONTRIBUTING.md

[5]

Node.js >= 14: https://nodejs.org

[6]

pnpm: https://pnpm.io

[7]

碼上掘金倒計時初步代碼@若川: https://code.juejin.cn/pen/7167966535649230883

[8]

TypeScript 入門教程: http://ts.xcatliu.com/

[9]

@vue/babel-plugin-jsx: https://www.npmjs.com/package/@vue/babel-plugin-jsx

[10]

組件實例方法: https://vant-contrib.gitee.io/vant/v4/#/zh-CN/advanced-usage#zu-jian-shi-li-fang-fa

[11]

碼上掘金倒計時簡化版二@若川: https://code.juejin.cn/pen/7168892330752081928

[12]

mdn window.requestAnimationFrame: https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame

[13]

CountDown 組件文檔: https://vant-contrib.gitee.io/vant/#/zh-CN/count-down

[14]

文檔: https://taroify.gitee.io/taroify.com/components/countdown

[15]

源碼: https://github.com/mallfoundry/taroify/tree/main/packages/core/src/countdown

分析 vant4 源碼,學會用 vue3 + ts 開發(fā)毫秒級渲染的倒計時組件,真是妙啊

·················?若川簡介?·················

你好,我是若川,畢業(yè)于江西高?!,F(xiàn)在是一名前端開發(fā)“工程師”。寫有《學習源碼整體架構系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經(jīng)堅持寫了8年,點擊查看年度總結。
同時,持續(xù)組織了一年多源碼共讀活動,幫助5000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。

掃碼加我微信 lxchuan12、拉你進源碼共讀

今日話題

目前建有江西|湖南|湖北?籍 前端群,想進群的可以加我微信 lxchuan12?進群。分享、收藏、點贊、在看我的文章就是對我最大的支持~文章來源地址http://www.zghlxwxcb.cn/news/detail-446190.html

到了這里,關于分析 vant4 源碼,學會用 vue3 + ts 開發(fā)毫秒級渲染的倒計時組件,真是妙啊的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Vant4在Vue3.3中如何按需導入組件和樣式

    Vant4在Vue3.3中如何按需導入組件和樣式

    最近我在Vue 3.3的項目中對Vant4做按需導入時,盡管按照Vant4的官方指南進行操作,但樣式仍然無法正確加載。經(jīng)過深入研究和多篇文章的比較,我終于找到了在Vue3中如何正確的按需導入Vant 4組件和樣式的方法。由于Vue3.3和Vant4相對較新,相關資料可能還不夠完善,因此我認為

    2024年01月21日
    瀏覽(98)
  • 項目實戰(zhàn):《智慧線上購物商城》:基于vue3+vite+vant4組件(一)

    項目實戰(zhàn):《智慧線上購物商城》:基于vue3+vite+vant4組件(一)

    本項目主要是基于vue3和vite以及vant4組件所開發(fā)的移動端購物商城。項目沒有接口,所運用的存儲數(shù)據(jù)為json數(shù)據(jù)通過axios請求,以及Localstorage等技術實現(xiàn)數(shù)據(jù)。 開發(fā)的模型參考以下的網(wǎng)站,感興趣的小伙伴可以去看看。 AxureShop原型演示 AxureShop原型演示 https://demo.axureshop.com/?

    2024年02月02日
    瀏覽(92)
  • # vue3 vant4 Tabbar 標簽欄組件的封裝 和Popup彈出層的封裝

    # vue3 vant4 Tabbar 標簽欄組件的封裝 和Popup彈出層的封裝

    需求如上,標簽欄里第三個是圖片,整個項目有兩種場景, 標簽欄正常跳轉頁面, 標簽攔渲染別的圖片時候,點擊就是打開彈出層, 封裝了標簽欄,彈出層兩部分,作為公共組件 標簽欄的封裝 徽標樣式需要調整,list現(xiàn)在是自己暫時再state里寫的假數(shù)據(jù) 下面是再使用標簽組

    2024年01月20日
    瀏覽(160)
  • Vite + Vue3 +Vant4構建項目時,按需引入使用Toast組件,引用 showToast 時出現(xiàn)編譯報錯的解決方案

    Vite + Vue3 +Vant4構建項目時,按需引入使用Toast組件,引用 showToast 時出現(xiàn)編譯報錯的解決方案

    一.問題定位 在Vite + Vue3 +Vant4構建項目時,需要使用Toast組件顯示提示信息,按照官方文檔使用函數(shù)調用 使用后直接報錯,說是找不到對應的樣式文件(如下圖): 在項目中查找node-moudles文件,確實沒有找到,只有一個toast文件(如下圖): 在百度搜索解決方法,說是需要單

    2024年01月17日
    瀏覽(97)
  • uniapp vue3版本+ts使用 vant小程序 組件庫

    1.首先從uniapp官網(wǎng)下載vue3版本+ts的模板 2.安裝vant微信小程序版本 3.在項目src目錄創(chuàng)建wxcomponents文件夾,在wxcomponents文件夾下創(chuàng)建vant文件夾 4.從node_modules文件夾下的@vant文件夾里面的weapp,weapp下的dist文件夾,將dist文件夾里面的文件復制到/wxcomponents/vant 5.全局引用? ?在 pages

    2024年02月13日
    瀏覽(101)
  • 基于Vant組件庫二次封裝組件(TS+Vue3.x環(huán)境)

    基于Vant組件庫二次封裝組件(TS+Vue3.x環(huán)境)

    1. 今天的需求是封裝一個 Navigation Bar 導航欄組件,目的是給到App幾乎所有的頁面復用: ?? ? 2. 因為之前的項目里使用過Vant組件庫,筆者第一時間想到了Vant組件庫中的 NavBar 組件,和當前App的需求匹配度很高。Vant組件庫的 NavBar 組件: 3. 相信你也發(fā)現(xiàn)了,Vant組件庫默認主題

    2023年04月18日
    瀏覽(100)
  • 實用的開源應用全新開源源碼Vue3+TS的前后臺分離的開發(fā)平臺源碼開源技術社區(qū)平臺

    實用的開源應用全新開源源碼Vue3+TS的前后臺分離的開發(fā)平臺源碼開源技術社區(qū)平臺

    開源全新開源源碼Vue3+TS的前后臺分離的開發(fā)平臺源碼。創(chuàng)意、新奇、有趣、實用的開源應用、系統(tǒng)、軟件、硬件及技術,一個探索、發(fā)現(xiàn)、分享、使用與互動交流的開源技術社區(qū)平臺。致力于打造活力開源社區(qū),共建開源新生態(tài)! 功能簡介 個人辦公:待辦事項、抄送傳閱、

    2024年02月13日
    瀏覽(171)
  • 【Vue H5項目實戰(zhàn)】從0到1的自助點餐系統(tǒng)—— 搭建腳手架(Vue3.2 + Vite + TS + Vant + Pinia + Node.js)

    【Vue H5項目實戰(zhàn)】從0到1的自助點餐系統(tǒng)—— 搭建腳手架(Vue3.2 + Vite + TS + Vant + Pinia + Node.js)

    H5 項目基于 Web 技術,可以在智能手機、平板電腦等移動設備上的瀏覽器中運行,無需下載和安裝任何應用程序,且H5 項目的代碼和資源可以集中在服務器端進行管理,只需更新服務器上的代碼,即可讓所有顧客訪問到最新的系統(tǒng)版本。 本系列將以肯德基自助點餐頁面為模板

    2024年02月13日
    瀏覽(133)
  • 【Vant4】Vant4 樣式不顯示問題 && Toast 輕提示不顯示 && Notify 消息提示不顯示

    【Vant4】Vant4 樣式不顯示問題 && Toast 輕提示不顯示 && Notify 消息提示不顯示

    使用 Toast 輕提示 和 Notify 消息提示 時沒有樣式,如下圖 引入所需的樣式,例如: 我要使用 消息提示 (Notify),就引入 import \\\'vant/es/notify/style\\\' 我要使用 輕提示 (Toast),就引入 import \\\'vant/es/toast/style\\\' HomeView.vue End 2023/3/7 一改 【Vue3】vue3的keepAlive保存滾動位置 CKEditor5 添加代碼高亮

    2023年04月18日
    瀏覽(20)
  • 3d環(huán)形圖開發(fā)(vue3+vite+ts)

    3d環(huán)形圖開發(fā)(vue3+vite+ts)

    開發(fā)效果(待完善): ? 技術支持: Echarts? echarts-gl 安裝: 注:echarts與echarts-gl版本需對應,可參考官網(wǎng) pnpm add echarts@4.9.0 echarts-gl@1.1.2 ?組件封裝:

    2024年02月07日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包