vue異步組件使用及加載失敗異常處理
引言
在構(gòu)建大型單頁(yè)應(yīng)用時(shí),組件的按需加載和延遲加載對(duì)于性能優(yōu)化至關(guān)重要。Vue.js 提供了一種實(shí)現(xiàn)這個(gè)需求的方式,那就是異步組件。異步組件允許我們將組件的加載延遲到實(shí)際需要的時(shí)候,而不是一開(kāi)始就全部加載。這不僅可以減少首屏加載時(shí)間,還可以提高應(yīng)用的響應(yīng)速度。本文將介紹Vue2中異步組件的概念、使用方法以及一些技巧,重點(diǎn)介紹一下高階異步組件及高階異步組件加載失敗后,如何實(shí)現(xiàn)重新加載。
什么是異步組件
在Vue中,通常我們使用import語(yǔ)句來(lái)導(dǎo)入組件,然后在components選項(xiàng)中注冊(cè)它們。這種方式會(huì)導(dǎo)致所有組件在應(yīng)用程序初始化時(shí)都被加載,可能會(huì)影響應(yīng)用的初始加載性能。異步組件的概念就是延遲加載組件,只有在需要時(shí)才進(jìn)行加載,從而提高了應(yīng)用的加載速度。
如何區(qū)別一個(gè)組件是同步組件還是異步組件呢?我們?nèi)粘i_(kāi)發(fā)過(guò)程中,常見(jiàn)的那些組件引用哪些是異步組件,哪些不是呢?
下面我們來(lái)舉例說(shuō)明:
// Welcome.vue
import HelloWorld from './HelloWorld.vue'
export default {
components: {HelloWorld},
template: '<HelloWorld/>'
}
在上面的例子中我們定義了一個(gè)組件Welcome.vue,在該組件中引入了局部組件HelloWorld,對(duì)于Welcome而言,此處的HelloWorld組件是作為同步組件引入的。
如果想使用異步組件的形式引入,該如何修改上面的代碼呢?
// Welcome.vue
//import HelloWorld from './HelloWorld.vue'
const HellowWold = ()=>import('./HelloWorld.vue')
export default {
components: {HelloWorld},
template: '<HelloWorld/>'
}
將組件改成上面的形式注冊(cè)局部組件,此時(shí)就是注冊(cè)了一個(gè)異步組件。組件自身的實(shí)現(xiàn)并沒(méi)有所謂的同步異步一說(shuō),關(guān)鍵在于如何引入組件。
上面異步組件的引入形式,常見(jiàn)于vue-router中注冊(cè)路由表時(shí)。這樣能能讓不同的路由獨(dú)立打包,按需加載。
異步組件的幾種書(shū)寫(xiě)形式
普通異步組件,通過(guò)vue內(nèi)部曝露出的resolve方法返回對(duì)應(yīng)的組件
Vue.component('async-component', function(resolve, reject) {
import('./AsyncComponent.vue').then((module) => {
resolve(module.default);
}).catch((error) => {
reject(error);
});
});
promise異步組件
Vue.component('async-component',()=>import('./AsyncComponent.vue'))
高階異步組件
// 高級(jí)異步組件
const AsyncComponent = () => ({
// 需要加載的組件 (應(yīng)該是一個(gè) `Promise` 對(duì)象)
component: import('./MyComponent.vue'),
// 異步組件加載時(shí)使用的組件
loading: LoadingComponent,
// 加載失敗時(shí)使用的組件
error: ErrorComponent,
// 展示加載時(shí)組件的延時(shí)時(shí)間。默認(rèn)值是 200 (毫秒)
delay: 200,
// 如果提供了超時(shí)時(shí)間且組件加載也超時(shí)了,
// 則使用加載失敗時(shí)使用的組件。默認(rèn)值是:`Infinity`
timeout: 3000
})
異步組件的應(yīng)用場(chǎng)景
路由懶加載
在 Vue Router 中,我們可以使用異步組件來(lái)實(shí)現(xiàn)路由懶加載。懶加載是一種優(yōu)化策略,它只加載當(dāng)前需要顯示的組件,而不是一次性加載所有的組件。這樣就可以減少首屏加載時(shí)間,提高應(yīng)用的響應(yīng)速度。
我們可以將每個(gè)路由配置中的 component 選項(xiàng)替換為一個(gè)返回 Promise 的函數(shù),這樣 Vue Router 就會(huì)自動(dòng)將這個(gè)組件注冊(cè)為異步組件,并在需要的時(shí)候進(jìn)行加載。例如:
const router = new VueRouter({
routes: [
{ path: '/foo', component: () => import('./Foo.vue') }
]
})
加載聯(lián)邦模塊
模塊聯(lián)邦:(Module Federation)是一種軟件架構(gòu)模式,主要用于解決在復(fù)雜分布式系統(tǒng)中,不同模塊間的依賴(lài)管理和共享問(wèn)題。這種模式通過(guò)將大型應(yīng)用拆分并獨(dú)立開(kāi)發(fā)、構(gòu)建和部署各個(gè)模塊,使得它們可以在運(yùn)行時(shí)動(dòng)態(tài)地加載和共享。
日常開(kāi)發(fā)中,開(kāi)發(fā)人員可能將A應(yīng)用中的某一組件獨(dú)立打包js,以中間件或者SDK的形式供其他應(yīng)用使用。而B(niǎo)作為引用方,如何加載遠(yuǎn)程js,引入對(duì)應(yīng)的組件呢?
下面以我在開(kāi)發(fā)中的一個(gè)實(shí)際應(yīng)用舉例,介紹兩種常規(guī)解決方法:
項(xiàng)目組中B應(yīng)用有一個(gè)遠(yuǎn)程服務(wù)的js文件,其中打包了我們需要引入的組件。在我們自身項(xiàng)目中需引入該組件,之所以采用加載js,而非npm包的形式,主要是為了解耦,后續(xù)該組件的迭代更新都不影響我們自身應(yīng)用,自身應(yīng)用也無(wú)需發(fā)版即可使用最新版本的組件。
首先,為方便后續(xù)使用,我們先封裝一個(gè)異步方法,用于加載和執(zhí)行對(duì)應(yīng)的js文件。加載執(zhí)行js的方式大致有兩種:
方法一:通過(guò)fetch請(qǐng)求獲取遠(yuǎn)程js內(nèi)容,然后通過(guò)eval函數(shù)執(zhí)行對(duì)應(yīng)的js文件。這種方式要考慮跨域問(wèn)題和eval安全執(zhí)行策略問(wèn)題,有些瀏覽器禁止在非安全環(huán)境下執(zhí)行eval函數(shù)。
fetch('path/to/remote/js/file.js')
.then(response => response.text())
.then(jsCode => {
// 執(zhí)行js
new Function('return ' + jsCode)();
})
.catch(error => {
console.error('Error loading remote component:', error);
});
方法二:通過(guò)動(dòng)態(tài)創(chuàng)建script標(biāo)簽來(lái)執(zhí)行對(duì)應(yīng)的js文件。這種方式比較穩(wěn)妥,無(wú)需考慮跨域問(wèn)題。
const script = document.createElement('script')
script.type = 'text/javascript'
script.onload = () => resolve(void 0)
script.onerror = (err) => {
console.error(`資源加載失?。篳, src)
reject(err)
}
script.src = src
document.head.appendChild(script)
這里我們項(xiàng)目中采用第二種動(dòng)態(tài)標(biāo)簽的形式,封裝了一個(gè)類(lèi),主要用于加載遠(yuǎn)程js,便于后續(xù)使用。其代碼簡(jiǎn)寫(xiě)如下:
import { Vue } from 'vue-property-decorator'
export class AsyncComponentLoader {
static cache: Record<string, any> = {}
static async loadAsyncComponent(src: string, cachable: boolean = false) {
if (!src) throw new Error('無(wú)法加載遠(yuǎn)程組件:未傳入遠(yuǎn)程組件加載地址')
const name = 'remote_sdk_key'
// 引入緩存,避免重復(fù)加載
if (cachable && AsyncComponentLoader.cache[name]) {
///遠(yuǎn)程組件js執(zhí)行后,在window上掛載,后續(xù)的邏輯有賴(lài)于遠(yuǎn)程js如何打包的,具體問(wèn)題具體分析
Vue.component('RemoteComp',window[name]?.default)
return
} else {
await AsyncComponentLoader.loadScript(src)
Vue.component('RemoteComp',window[name]?.default)
AsyncComponentLoader.cache[name] = window[name]
}
}
static async loadScript(src) {
// 加載遠(yuǎn)程js并執(zhí)行
return new Promise((resolve, reject) => {
const script = document.createElement('script')
script.type = 'text/javascript'
script.onload = () => resolve(void 0)
script.onerror = (err) => {
console.error(`資源加載失?。篳, src)
reject(err)
}
script.src = src
document.head.appendChild(script)
})
}
}
同步引入
創(chuàng)建一個(gè)新的Vue組件文件AsyncComponent,在AsyncComponent文件中,你可以編寫(xiě)一個(gè)方法來(lái)請(qǐng)求遠(yuǎn)程JS文件,并將其動(dòng)態(tài)導(dǎo)入為組件。例如:
import { Vue, Component, Prop } from 'vue-property-decorator'
import { AsyncComponentLoader } from './AsyncComponentLoader'
@Component
export default class extends Vue {
@Prop() src!: string
// sdk加載成功標(biāo)識(shí)
sdkLoaded = false
// sdk加載loading
showLoading = false
async created() {
//加載組件js
this.loadComponent()
}
async loadComponent() {
this.showLoading = true
AsyncComponentLoader.loadAsyncComponent(this.src, true)
.then(() => {
this.sdkLoaded = true
this.$emit('onload')
//強(qiáng)制父組件重新渲染
this.$parent?.$forceUpdate()
})
.catch(() => {
this.$emit('onerror')
})
.finally(() => {
this.showLoading = false
})
}
genError() {
const h = this.$createElement
const style = { height: '150px', cursor: 'pointer', backgroundColor: '#fff' }
return (
///加載失敗時(shí)顯示
<div style={style} onClick={this.loadComponent}>
加載失敗,點(diǎn)擊重新加載
</div>
)
}
render() {
const h = this.$createElement
if (this.showLoading) {
//加載loading
const directives = [{ name: 'loading', value: this.showLoading }]
return <div {...{ directives }} style="width: 100%;height: 150px"></div>
}
if (!this.sdkLoaded) {
return this.genError()
}
return this.$slots.default
}
}
在上面代碼中定義了一個(gè)組件,該組件在created鉤子函數(shù)中去加載遠(yuǎn)程js組件。在加載過(guò)程中,顯示loading,加載成功后顯示默認(rèn)插槽內(nèi)容,在插槽里,可以直接使用注冊(cè)的遠(yuǎn)程組件,如果js加載失敗,則顯示對(duì)應(yīng)的error,并支持點(diǎn)擊重新加載。
使用方式:
<async-load src="path/to/remote/js/file.js">
<RemoteComp :env="env" />
</async-load>
異步引入
通過(guò)直接注冊(cè)一個(gè)高階異步組件的形式,來(lái)引入遠(yuǎn)程js組件
Vue.component('async-component', function() {
// 顯示loading狀態(tài)
const loadingComponent = {
template: '<div>Loading...</div>'
};
// 顯示error狀態(tài)
const errorComponent = {
template: '<div>Error! Failed to load component.</div>'
};
return {
loading: loadingComponent,
error:errorComponent,
component: new Promise((resolve,reject)=>{
// 加載遠(yuǎn)程組件的js文件
const script = document.createElement('script');
script.src = 'path_to_remote_component.js';
script.onload = () => {
// 注冊(cè)遠(yuǎn)程組件
resolve({
template: '<div>遠(yuǎn)程組件的模板</div>',
// 遠(yuǎn)程組件的其他配置
});
};
script.onerror = (error) => {
reject(error)
};
document.head.appendChild(script);
}),
delay: 0,
timeout: 3000
}
});
注冊(cè)的異步組件可以直接使用,該組件使用方式:
<async-component></async-component>
無(wú)論成功還是失敗,異步組件的加載只執(zhí)行一次,之后就一直保留該狀態(tài)。這也就意味著,當(dāng)異步組件作為局部組件引入時(shí),一旦加載失敗,后續(xù)無(wú)論路由如何跳轉(zhuǎn),該異步組件也一直渲染的是errorComp。除非刷新整個(gè)頁(yè)面,重新加載響應(yīng)異步組件。但是很多時(shí)候,作為局部組件加載失敗,我們只想重新加載失敗的那部分,局部刷新,該如何做呢
異步組件加載失敗異常處理
通常,異步組件作為路由組件,一個(gè)路由就是一個(gè)頁(yè)面,這個(gè)時(shí)候加載失敗時(shí),我們一般都是刷新整個(gè)瀏覽器頁(yè)面就行。但是針對(duì)上面我們說(shuō)的,當(dāng)一個(gè)異步組件作為頁(yè)面的一部分渲染時(shí),如果加載失敗,如何只加載這部分,而不需要刷新整個(gè)瀏覽器頁(yè)面也是很有必要的。
在vue的issue中,也有人提出了類(lèi)似的問(wèn)題: https://github.com/vuejs/vue/issues/8524
在這個(gè)問(wèn)題中,vue的作者尤大給出的解決方案是強(qiáng)制父組件重新渲染。

根據(jù)以上回答,我做了以下嘗試,將上面異步組件的errorComponent重新改了下,增加了刷新方法,調(diào)用強(qiáng)制刷新方法$forceUpdate,強(qiáng)制父組件刷新。
@Component
class ErrorComp extends Vue {
async refresh() {
// 強(qiáng)制父組件刷新,用以重新加載異步組件
this.$parent?.$forceUpdate()
}
render() {
const h = this.$createElement
return (
<div style="min-height:150px;padding: 10px" onClick={this.refresh}>
加載失敗!請(qǐng)刷新重試
</div>
)
}
}
然而,經(jīng)實(shí)際代碼試驗(yàn),這種直接調(diào)用父實(shí)例刷新方法,并不能重新加載異步組件,對(duì)應(yīng)的異步組件依然渲染為errorComponent。此時(shí),我們就需要執(zhí)行下調(diào)試,看看強(qiáng)制刷新后,為什么沒(méi)有重新加載異步組件。
首先,代碼執(zhí)行到vue源碼中的createComponent中,這是vue在解析組件類(lèi)型標(biāo)簽中很重要的一個(gè)函數(shù),不了解的可以看下相關(guān)源碼。源碼中的Ctor就是上面我們注冊(cè)異步組件時(shí)Vue.component('async-component', function() {/**bula bula/})的第二個(gè)函數(shù)入?yún)ⅰ?/p>
function createComponent (
Ctor,
data,
context,
children,
tag
) {
if (isUndef(Ctor)) {
return
}
var baseCtor = context.$options._base;
// plain options object: turn it into a constructor
//異步組件這里Ctor是個(gè)函數(shù),所以不走extend方法
if (isObject(Ctor)) {
Ctor = baseCtor.extend(Ctor);
}
// if at this stage it's not a constructor or an async component factory,
// reject.
if (typeof Ctor !== 'function') {
if (process.env.NODE_ENV !== 'production') {
warn(("Invalid Component definition: " + (String(Ctor))), context);
}
return
}
// async component
var asyncFactory;
//由于沒(méi)有走extend方法,自然沒(méi)有對(duì)應(yīng)的cid,異步組件可以執(zhí)行到這個(gè)里面
if (isUndef(Ctor.cid)) {
asyncFactory = Ctor; //在異步組件加載失敗以后,可以在此處打上斷點(diǎn),然后點(diǎn)擊重新加載,觀察后續(xù)執(zhí)行過(guò)程
//這里重點(diǎn)要進(jìn)入這個(gè)方法,這個(gè)方法決定了異步組件渲染的是loading組件還是遠(yuǎn)程組件或者error組件
Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context);
if (Ctor === undefined) {
// return a placeholder node for async component, which is rendered
// as a comment node but preserves all the raw information for the node.
// the information will be used for async server-rendering and hydration.
return createAsyncPlaceholder(
asyncFactory,
data,
context,
children,
tag
)
}
}
//后續(xù)代碼省略不看
……
}
在上述代碼中我們重點(diǎn)關(guān)注resolveAsyncComponent方法的執(zhí)行,在下面代碼中,我們可以看到,方法在最開(kāi)始的時(shí)候就對(duì)factory.error進(jìn)行了判斷。在我們首次執(zhí)行異步組件加載時(shí),由于加載失敗,此時(shí)會(huì)將factory.error置為true。所以后續(xù)我們強(qiáng)制父組件重新渲染時(shí),在這個(gè)函數(shù)里,第一行判斷成功就直接返回了factory.errorComp組件,所以我們?nèi)绻叵虻谝淮文菢又匦录虞d該遠(yuǎn)程組件,我們需要把函數(shù)里面所有的提前返回都杜絕調(diào),以便于執(zhí)行到最終的加載邏輯中。
function resolveAsyncComponent (
factory,
baseCtor
) {
//此處加載失敗,直接返回了errorComp,如重新加載,將對(duì)應(yīng)的factory.error設(shè)為false
if (isTrue(factory.error) && isDef(factory.errorComp)) {
return factory.errorComp
}
//由于是失敗重新加載,factory.resolved無(wú)值,無(wú)需處理
if (isDef(factory.resolved)) {
return factory.resolved
}
var owner = currentRenderingInstance;
if (owner && isDef(factory.owners) && factory.owners.indexOf(owner) === -1) {
// already pending
factory.owners.push(owner);
}
// 失敗重新時(shí),將loading重新置為false
if (isTrue(factory.loading) && isDef(factory.loadingComp)) {
return factory.loadingComp
}
//為了進(jìn)入這個(gè)判斷里面,這里將factory.owners置為null
if (owner && !isDef(factory.owners)) {
var owners = factory.owners = [owner];
var sync = true;
var timerLoading = null;
var timerTimeout = null
;(owner).$on('hook:destroyed', function () { return remove(owners, owner); });
var forceRender = function (renderCompleted) {
for (var i = 0, l = owners.length; i < l; i++) {
(owners[i]).$forceUpdate();
}
if (renderCompleted) {
owners.length = 0;
if (timerLoading !== null) {
clearTimeout(timerLoading);
timerLoading = null;
}
if (timerTimeout !== null) {
clearTimeout(timerTimeout);
timerTimeout = null;
}
}
};
var resolve = once(function (res) {
// cache resolved
factory.resolved = ensureCtor(res, baseCtor);
// invoke callbacks only if this is not a synchronous resolve
// (async resolves are shimmed as synchronous during SSR)
if (!sync) {
forceRender(true);
} else {
owners.length = 0;
}
});
var reject = once(function (reason) {
warn(
"Failed to resolve async component: " + (String(factory)) +
(reason ? ("\nReason: " + reason) : '')
);
if (isDef(factory.errorComp)) {
//執(zhí)行失敗時(shí),將factory.error設(shè)為true
factory.error = true;
forceRender(true);
}
});
//這里傳入上面定義的resolve,reject方法
var res = factory(resolve, reject);
if (isObject(res)) {
if (isPromise(res)) {
// () => Promise
if (isUndef(factory.resolved)) {
res.then(resolve, reject);
}
} else if (isPromise(res.component)) {
res.component.then(resolve, reject);
if (isDef(res.error)) {
//此處初始化factory.errorComp,這里的res.error就是我們先前定義高階異步組件時(shí),函數(shù)返回對(duì)象中的error
factory.errorComp = ensureCtor(res.error, baseCtor);
}
if (isDef(res.loading)) {
factory.loadingComp = ensureCtor(res.loading, baseCtor);
if (res.delay === 0) {
factory.loading = true;
} else {
timerLoading = setTimeout(function () {
timerLoading = null;
if (isUndef(factory.resolved) && isUndef(factory.error)) {
factory.loading = true;
forceRender(false);
}
}, res.delay || 200);
}
}
if (isDef(res.timeout)) {
timerTimeout = setTimeout(function () {
timerTimeout = null;
if (isUndef(factory.resolved)) {
reject(
"timeout (" + (res.timeout) + "ms)"
);
}
}, res.timeout);
}
}
}
sync = false;
// return in case resolved synchronously
return factory.loading
? factory.loadingComp
: factory.resolved
}
}
根據(jù)上面源碼中代碼執(zhí)行結(jié)果,重新調(diào)整刷新方法如下:
@Component
class ErrorComp extends Vue {
async refresh() {
// 異步組件加載失敗后,在不刷新頁(yè)面的情況下重新加載遠(yuǎn)程組件
// 該方法hack了vue內(nèi)部實(shí)現(xiàn),非必要不使用,且依賴(lài)于vue源碼中resolveAsyncComponent方法,需注意vue版本
// @ts-ignore
const asyncFactory: any = this.constructor.asyncFactory //注意這里的asyncFactory不是本身就有的,需要手動(dòng)掛載。這里是為了統(tǒng)一封裝errorComp組件,便于其他異步組件也可以使用該errorComp
if (!asyncFactory) return window.location.reload()
// 異步組件加載失敗后,該標(biāo)識(shí)為true,返回之前設(shè)置的error component,如需重新加載,需重設(shè)error
asyncFactory.error = false
// 重設(shè)loading,否則重新加載后返回的是loading component
asyncFactory.loading = false
// 重設(shè)實(shí)例,否則無(wú)法進(jìn)入異步組件加載邏輯,不同版本的變量命名不同,應(yīng)用里用的是2.6.10版本,變量為owners,2.5中為contexts
asyncFactory.contexts = null
asyncFactory.owners = null
// 強(qiáng)制父組件刷新,用以重新加載異步組件
this.$parent?.$forceUpdate()
}
render() {
const h = this.$createElement
return (
<div style="min-height:150px;padding: 10px">
加載失敗!請(qǐng)
<span style="cursor: pointer;color: #3693ff" onClick={this.refresh}>
刷新
</span>
重試
</div>
)
}
}
在上面代碼中,在$forceUpdate方法之前執(zhí)行了一些重置操作,用于清空異步組件的加載狀態(tài)。這里需要強(qiáng)調(diào)一下,代碼中的constructor.asyncFactory不是本身就有的,需要手動(dòng)掛載。這里是為了統(tǒng)一封裝errorComp組件,便于其他異步組件也可以使用該errorComp。至于后面的owners和contexts是由于不同版本的vue,在此處的實(shí)現(xiàn)略有不同,為了兼容性,這里兩個(gè)變量值都重置了一下。至于如何掛載asyncFactory,以下面?zhèn)未a為例:
import ErrorComp from 'ErrorComp'
Vue.component('async-component', function asyncComponent() {
const error = ErrorComp.extend()
//這里掛載一下,便于后面失敗時(shí)重新加載引用
error.asyncFactory = asyncComponent
return {
loading: loadingComp,
error:error,
component: new Promise((resolve,reject)=>{
// ……
})
}
})
經(jīng)試驗(yàn),改造后的代碼可以實(shí)現(xiàn)異步組件加載失敗重新加載。如果有遇到相似問(wèn)題的,可以參考下該方案。不過(guò)由于該方案有較強(qiáng)的侵入性,依賴(lài)于vue源碼的內(nèi)部實(shí)現(xiàn),不同vue版本,在這方面的實(shí)現(xiàn)策略不同,可能會(huì)導(dǎo)致不同的執(zhí)行效果,所以請(qǐng)注意使用的vue版本及其在這一塊的實(shí)現(xiàn)細(xì)節(jié)。本文中對(duì)應(yīng)的代碼適應(yīng)于vue 2.5-2.6,我并沒(méi)有查詢(xún)其他版本的vue源碼,有興趣的可以自行參考此方案做響應(yīng)調(diào)整。
結(jié)語(yǔ)
通過(guò)使用Vue2中的異步組件,我們可以?xún)?yōu)化應(yīng)用程序的性能和加載速度,提升用戶(hù)體驗(yàn)。同時(shí),合理地處理加載狀態(tài)和錯(cuò)誤情況,以及靈活地使用高階異步組件和按需加載,可以讓我們更好地利用異步組件的優(yōu)勢(shì),為用戶(hù)提供更好的應(yīng)用體驗(yàn)。
到此這篇關(guān)于vue異步組件使用及加載失敗異常處理的文章就介紹到這了,更多相關(guān)vue異步組件加載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue前端登錄token信息驗(yàn)證功能實(shí)現(xiàn)
最近公司新啟動(dòng)了個(gè)項(xiàng)目,用的是vue框架在做,下面這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)token登錄驗(yàn)證的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
Vue3+vite路由配置優(yōu)化(自動(dòng)化導(dǎo)入)
這篇文章主要介紹了Vue3+vite路由配置優(yōu)化(自動(dòng)化導(dǎo)入),需要的朋友可以參考下2023-09-09
vue過(guò)濾器實(shí)現(xiàn)日期格式化的案例分析
這篇文章主要介紹了vue過(guò)濾器實(shí)現(xiàn)日期格式化的案例分析,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
vue自定義開(kāi)發(fā)滑動(dòng)圖片驗(yàn)證組件
這篇文章主要為大家詳細(xì)介紹了vue自定義開(kāi)發(fā)滑動(dòng)圖片驗(yàn)證組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
vue3語(yǔ)法中使用vscode打開(kāi)滿(mǎn)屏紅線(xiàn)報(bào)錯(cuò)的完美解決方法
這篇文章主要介紹了vue3語(yǔ)法中使用vscode打開(kāi)滿(mǎn)屏紅線(xiàn)報(bào)錯(cuò)的完美解決方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
vue使用video插件vue-video-player的示例
這篇文章主要介紹了vue使用video插件vue-video-player的示例,幫助大家更好的理解和使用vue插件,感興趣的朋友可以了解下2020-10-10
Vue中使用crypto-js AES對(duì)稱(chēng)加密算法實(shí)現(xiàn)加密解密
?在數(shù)字加密算法中,通過(guò)可劃分為對(duì)稱(chēng)加密和非對(duì)稱(chēng)加密,本文主要介紹了Vue中使用crypto-js AES對(duì)稱(chēng)加密算法實(shí)現(xiàn)加密解密,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03

