摘要:這些依賴對象也進(jìn)一步暴露了其設(shè)計思想。關(guān)鍵功能包括在上下文內(nèi)掛載在上下文外掛載在上下文外共享數(shù)據(jù)。在構(gòu)造必須依賴,所以可以直接創(chuàng)建嵌入視圖,然后手動強(qiáng)制執(zhí)行變更檢測。提供了兩個指令和。
@angular/material 是 Angular 官方根據(jù) Material Design 設(shè)計語言提供的 UI 庫,開發(fā)人員在開發(fā) UI 庫時發(fā)現(xiàn)很多 UI 組件有著共同的邏輯,所以他們把這些共同邏輯抽出來多帶帶做一個包 @angular/cdk,這個包與 Material Design 設(shè)計語言無關(guān),可以被任何人按照其他設(shè)計語言構(gòu)建其他風(fēng)格的 UI 庫。學(xué)習(xí) @angular/material 或 @angular/cdk 這些包的源碼,主要是為了學(xué)習(xí)大牛們是如何高效使用 TypeScript 語言的;學(xué)習(xí)他們?nèi)绾伟?RxJS 這個包使用的這么出神入化;最主要是為了學(xué)習(xí)他們是怎么應(yīng)用 Angular 框架提供的技術(shù)。只有深入研究這些大牛們寫的代碼,才能更快提高自己的代碼質(zhì)量,這是一件事半功倍的事情。Portal 是什么
最近在學(xué)習(xí) React 時,發(fā)現(xiàn) React 提供了 Portals 技術(shù),該技術(shù)主要用來把子節(jié)點(diǎn)動態(tài)的顯示到父節(jié)點(diǎn)外的 DOM 節(jié)點(diǎn)上,該技術(shù)的一個經(jīng)典用例應(yīng)該就是 Dialog 了。設(shè)想一下在設(shè)計 Dialog 時所需要的主要功能點(diǎn):當(dāng)點(diǎn)擊一個 button 時,一般需要在 body 標(biāo)簽前動態(tài)掛載一個組件視圖;該 dialog 組件視圖需要共享數(shù)據(jù)。由此看出,Portal 核心就是在任意一個 DOM 節(jié)點(diǎn)內(nèi)動態(tài)生成一個視圖,該 視圖卻可以置于框架上下文環(huán)境之外。那 Angular 中有沒有類似相關(guān)技術(shù)來解決這個問題呢?
Angular Portal 就是用來在任意一個 DOM 節(jié)點(diǎn)內(nèi)動態(tài)生成一個視圖,該視圖既可以是一個組件視圖,也可以是一個模板視圖,并且生成的視圖可以掛載在任意一個 DOM 節(jié)點(diǎn),甚至該節(jié)點(diǎn)可以置于 Angular 上下文環(huán)境之外,也同樣可以與該視圖共享數(shù)據(jù)。該 Portal 技術(shù)主要就涉及兩個簡單對象:PortalOutlet 和 Portal
Portal
抽象類 BasePortalOutlet 是 PortalOutlet 的基本實(shí)現(xiàn),同時包含了三個重要方法:attach 表示把 Portal 掛載到 PortalOutlet 上,并定義了兩個抽象方法,來具體實(shí)現(xiàn)掛載組件視圖還是模板視圖:
abstract attachComponentPortal(portal: ComponentPortal ): ComponentRef ; abstract attachTemplatePortal (portal: TemplatePortal ): EmbeddedViewRef ;
detach 表示從 PortalOutlet 中拆卸出該 Portal,而 PortalOutlet 中可以掛載多個 Portal,dispose 表示整體并永久銷毀 PortalOutlet。其中,還有一個重要類 DomPortalOutlet 是 BasePortalOutlet 的子類,可以在 Angular 上下文之外 創(chuàng)建一個 PortalOutlet,并把 Portal 掛載到該 PortalOutlet 上,比如將 body 最后子元素 div 包裝為一個 PortalOutlet,然后將組件視圖或模板視圖掛載到該掛載點(diǎn)上。這里的的難點(diǎn)就是如果該掛載點(diǎn)在 Angular 上下文之外,那掛載點(diǎn)內(nèi)的 Portal 如何與 Angular 上下文內(nèi)的組件共享數(shù)據(jù)。 DomPortalOutlet 還實(shí)現(xiàn)了上面的兩個抽象方法:attachComponentPortal 和 attachTemplatePortal,如果對代碼細(xì)節(jié)感興趣可接著看下文。
現(xiàn)在已經(jīng)知道了 @angular/cdk/portal 中最重要的兩個核心,即 Portal 和 PortalOutlet,接下來寫一個 demo 看看如何使用 Portal 和 PortalOutlet 來在 Angular 上下文之外 創(chuàng)建一個 ComponentPortal 和 TemplatePortal。
Demo 關(guān)鍵功能包括:在 Angular 上下文內(nèi) 掛載 TemplatePortal/ComponentPortal;在 Angular 上下文外 掛載 TemplatePortal/ComponentPortal;在 Angular 上下文外 共享數(shù)據(jù)。接下來讓我們逐一實(shí)現(xiàn)每個功能點(diǎn)。
Angular 上下文內(nèi)掛載 Portal在 Angular 上下文內(nèi)掛載 Portal 比較簡單,首先需要做的第一步就是實(shí)例化出一個掛載容器 PortalOutlet,可以通過實(shí)例化 DomPortalOutlet 得到該掛載容器。查看 DomPortalOutlet 的構(gòu)造依賴主要包括:掛載的元素節(jié)點(diǎn) Element,可以通過 @ViewChild DOM 查詢得到該組件內(nèi)的某一個 DOM 元素;組件工廠解析器 ComponentFactoryResolver,可以通過當(dāng)前組件構(gòu)造注入拿到,該解析器是為了當(dāng) Portal 是 ComponentPortal 時解析出對應(yīng)的 Component;當(dāng)前程序?qū)ο?ApplicationRef,主要用來掛載組件視圖;注入器 Injector,這個很重要,如果是在 Angular 上下文外掛載組件視圖,可以用 Injector 來和組件視圖共享數(shù)據(jù)。
第二步就是使用 ComponentPortal 和 TemplatePortal 包裝對應(yīng)的組件和模板,需要留意的是 TemplatePortal 還必須依賴 ViewContainerRef 對象來調(diào)用 createEmbeddedView() 來創(chuàng)建嵌入視圖。
第三步就是調(diào)用 PortalOutlet 的 attach() 方法掛載 Portal,進(jìn)而根據(jù) Portal 是 ComponentPortal 還是 TemplatePortal 分別調(diào)用 attachComponentPortal() 和 attachTemplatePortal() 方法。
通過以上三步,就可以知道該如何設(shè)計代碼:
@Component({ selector: "portal-dialog", template: `Component Portal
` }) export class DialogComponent {} @Component({ selector: "app-root", template: `
Open a ComponentPortal Inside Angular Context
Open a TemplatePortal Inside Angular Context
`, }) export class AppComponent { private _appRef: ApplicationRef; constructor(private _componentFactoryResolver: ComponentFactoryResolver, private _injector: Injector, @Inject(DOCUMENT) private _document) {} @ViewChild("_openComponentPortalInsideAngularContext", {read: ViewContainerRef}) _openComponentPortalInsideAngularContext: ViewContainerRef; openComponentPortalInsideAngularContext() { if (!this._appRef) { this._appRef = this._injector.get(ApplicationRef); } // instantiate a DomPortalOutlet const portalOutlet = new DomPortalOutlet(this._openComponentPortalInsideAngularContext.element.nativeElement, this._componentFactoryResolver, this._appRef, this._injector); // instantiate a ComponentPortal Template Portal Inside Angular Context
const componentPortal = new ComponentPortal(DialogComponent); // attach a ComponentPortal to a DomPortalOutlet portalOutlet.attach(componentPortal); } @ViewChild("_templatePortalInsideAngularContext", {read: TemplateRef}) _templatePortalInsideAngularContext: TemplateRef ; @ViewChild("_openTemplatePortalInsideAngularContext", {read: ViewContainerRef}) _openTemplatePortalInsideAngularContext: ViewContainerRef; openTemplatePortalInsideAngularContext() { if (!this._appRef) { this._appRef = this._injector.get(ApplicationRef); } // instantiate a DomPortalOutlet const portalOutlet = new DomPortalOutlet(this._openTemplatePortalInsideAngularContext.element.nativeElement, this._componentFactoryResolver, this._appRef, this._injector); // instantiate a TemplatePortal<> const templatePortal = new TemplatePortal(this._templatePortalInsideAngularContext, this._openTemplatePortalInsideAngularContext); // attach a TemplatePortal to a DomPortalOutlet portalOutlet.attach(templatePortal); } }
查閱上面設(shè)計的代碼,發(fā)現(xiàn)沒有什么太多新的東西。通過 @ViewChild DOM 查詢到模板對象和視圖容器對象,注意該裝飾器的第二個參數(shù) {read:},用來指定具體查詢哪種標(biāo)識如 TemplateRef 還是 ViewContainerRef。當(dāng)然,最重要的技術(shù)點(diǎn)還是 attach() 方法的實(shí)現(xiàn),該方法的源碼解析可以接著看下文。
完整代碼可見 demo。
Angular 上下文外掛載 Portal從上文可知道,如果想要把 Portal 掛載到 Angular 上下文外,關(guān)鍵是 PortalOutlet 的依賴 outletElement 得處于 Angular 上下文之外。這個 HTMLElement 可以通過 _document.body.appendChild(element) 來手動創(chuàng)建:
let container = this._document.createElement("div"); container.classList.add("component-portal"); container = this._document.body.appendChild(container);
有了處于 Angular 上下文之外的一個 Element,后面的設(shè)計步驟就和上文完全一樣:實(shí)例化一個處于 Angular 上下文之外的 PortalOutlet,然后掛載 ComponentPortal 和 TemplatePortal:
@Component({ selector: "app-root", template: `Open a ComponentPortal Outside Angular Context
Open a TemplatePortal Outside Angular Context
`, }) export class AppComponent { ... openComponentPortalOutSideAngularContext() { let container = this._document.createElement("div"); container.classList.add("component-portal"); container = this._document.body.appendChild(container); if (!this._appRef) { this._appRef = this._injector.get(ApplicationRef); } // instantiate a DomPortalOutlet const portalOutlet = new DomPortalOutlet(container, this._componentFactoryResolver, this._appRef, this._injector); // instantiate a ComponentPortal Template Portal Outside Angular Context
const componentPortal = new ComponentPortal(DialogComponent); // attach a ComponentPortal to a DomPortalOutlet portalOutlet.attach(componentPortal); } @ViewChild("_templatePortalOutsideAngularContext", {read: TemplateRef}) _template: TemplateRef ; @ViewChild("_templatePortalOutsideAngularContext", {read: ViewContainerRef}) _viewContainerRef: ViewContainerRef; openTemplatePortalOutSideAngularContext() { let container = this._document.createElement("div"); container.classList.add("template-portal"); container = this._document.body.appendChild(container); if (!this._appRef) { this._appRef = this._injector.get(ApplicationRef); } // instantiate a DomPortalOutlet const portalOutlet = new DomPortalOutlet(container, this._componentFactoryResolver, this._appRef, this._injector); // instantiate a TemplatePortal<> const templatePortal = new TemplatePortal(this._template, this._viewContainerRef); // attach a TemplatePortal to a DomPortalOutlet portalOutlet.attach(templatePortal); } ...
通過上面代碼,就可以在 Angular 上下文之外創(chuàng)建一個視圖,這個技術(shù)對創(chuàng)建 Dialog 會非常有用。
完整代碼可見 demo。
Angular 上下文外共享數(shù)據(jù)最難點(diǎn)還是如何與處于 Angular 上下文外的 Portal 共享數(shù)據(jù),這個問題需要根據(jù) ComponentPortal 還是 TemplatePortal 分別處理。其中,如果是 TemplatePortal,解決方法卻很簡單,注意觀察 TemplatePortal 的構(gòu)造依賴,發(fā)現(xiàn)存在第三個可選參數(shù) context,難道是用來向 TemplatePortal 里傳送共享數(shù)據(jù)的?沒錯,的確如此。可以查看 DomPortalOutlet.attachTemplatePortal() 的 75 行,就是把 portal.context 傳給組件視圖內(nèi)作為共享數(shù)據(jù)使用,既然如此,TemplatePortal 共享數(shù)據(jù)問題就很好解決了:
@Component({ selector: "app-root", template: `Open a TemplatePortal Outside Angular Context with Sharing Data
`, }) export class AppComponent { sharingTemplateData: string = "lx1035"; @ViewChild("_templatePortalOutsideAngularContextWithSharingData", {read: TemplateRef}) _templateWithSharingData: TemplateRef Template Portal Outside Angular Context, the Sharing Data is {{name}}
; @ViewChild("_templatePortalOutsideAngularContextWithSharingData", {read: ViewContainerRef}) _viewContainerRefWithSharingData: ViewContainerRef; setTemplateSharingData(value) { this.sharingTemplateData = value; } openTemplatePortalOutSideAngularContextWithSharingData() { let container = this._document.createElement("div"); container.classList.add("template-portal-with-sharing-data"); container = this._document.body.appendChild(container); if (!this._appRef) { this._appRef = this._injector.get(ApplicationRef); } // instantiate a DomPortalOutlet const portalOutlet = new DomPortalOutlet(container, this._componentFactoryResolver, this._appRef, this._injector); // instantiate a TemplatePortal const templatePortal = new TemplatePortal(this._templateWithSharingData, this._viewContainerRefWithSharingData, {name: this.sharingTemplateData}); // <--- key point // attach a TemplatePortal to a DomPortalOutlet portalOutlet.attach(templatePortal); } ...
那 ComponentPortal 呢?查看 ComponentPortal 的第三個構(gòu)造依賴 Injector,它依賴的是注入器。TemplatePortal 的第三個參數(shù) context 解決了共享數(shù)據(jù)問題,那 ComponentPortal 可不可以通過第三個參數(shù)注入器解決共享數(shù)據(jù)問題?沒錯,完全可以。可以構(gòu)造一個自定義的 Injector,把共享數(shù)據(jù)存儲到 Injector 里,然后 ComponentPortal 從 Injector 中取出該共享數(shù)據(jù)。查看 Portal 的源碼包,官方還很人性的提供了一個 PortalInjector 類供開發(fā)者實(shí)例化一個自定義注入器。現(xiàn)在思路已經(jīng)有了,看看代碼具體實(shí)現(xiàn):
let DATA = new InjectionToken("Sharing Data with Component Portal"); @Component({ selector: "portal-dialog-sharing-data", template: ` Component Portal Sharing Data is: {{data}}
` }) export class DialogComponentWithSharingData { constructor(@Inject(DATA) public data: any) {} // <--- key point } @Component({ selector: "app-root", template: `
Open a ComponentPortal Outside Angular Context with Sharing Data
`, }) export class AppComponent { ... sharingComponentData: string = "lx1036"; setComponentSharingData(value) { this.sharingComponentData = value; } openComponentPortalOutSideAngularContextWithSharingData() { let container = this._document.createElement("div"); container.classList.add("component-portal-with-sharing-data"); container = this._document.body.appendChild(container); if (!this._appRef) { this._appRef = this._injector.get(ApplicationRef); } // Sharing data by Injector(Dependency Injection) const map = new WeakMap(); map.set(DATA, this.sharingComponentData); // <--- key point const injector = new PortalInjector(this._injector, map); // instantiate a DomPortalOutlet const portalOutlet = new DomPortalOutlet(container, this._componentFactoryResolver, this._appRef, injector); // <--- key point // instantiate a ComponentPortalconst componentPortal = new ComponentPortal(DialogComponentWithSharingData); // attach a ComponentPortal to a DomPortalOutlet portalOutlet.attach(componentPortal); }
通過 Injector 就可以實(shí)現(xiàn) ComponentPortal 與 AppComponent 共享數(shù)據(jù)了,該技術(shù)對于 Dialog 實(shí)現(xiàn)尤其重要,設(shè)想對于 Dialog 彈出框,需要在 Dialog 中展示來自于外部組件的數(shù)據(jù)依賴,同時 Dialog 還需要把數(shù)據(jù)傳回給外部組件。Angular Material 官方就在 @angular/cdk/portal 基礎(chǔ)上構(gòu)造一個 @angular/cdk/overlay 包,專門處理類似覆蓋層組件的共同問題,這些類似覆蓋層組件如 Dialog, Tooltip, SnackBar 等等。
完整代碼可見 demo。
解析 attach() 源碼不管是 ComponentPortal 還是 TemplatePortal,PortalOutlet 都會調(diào)用 attach() 方法把 Portal 掛載進(jìn)來,具體掛載過程是怎樣的?查看 BasePortalOutlet 的 attach() 的源碼實(shí)現(xiàn):
/** Attaches a portal. */ attach(portal: Portal): any { ... if (portal instanceof ComponentPortal) { this._attachedPortal = portal; return this.attachComponentPortal(portal); } else if (portal instanceof TemplatePortal) { this._attachedPortal = portal; return this.attachTemplatePortal(portal); } ... }
attach() 主要邏輯就是根據(jù) Portal 類型分別調(diào)用 attachComponentPortal 和 attachTemplatePortal 方法。下面將分別查看兩個方法的實(shí)現(xiàn)。
attachComponentPortal()還是以 DomPortalOutlet 類為例,如果掛載的是組件視圖,就會調(diào)用 attachComponentPortal() 方法,第一步就是通過組件工廠解析器 ComponentFactoryResolver 解析出組件工廠對象:
attachComponentPortal(portal: ComponentPortal ): ComponentRef { let componentFactory = this._componentFactoryResolver.resolveComponentFactory(portal.component); let componentRef: ComponentRef ; ...
然后如果 ComponentPortal 定義了 ViewContainerRef,就調(diào)用 ViewContainerRef.createComponent 創(chuàng)建組件視圖,并依次插入到該視圖容器中,最后設(shè)置 ComponentPortal 銷毀回調(diào):
if (portal.viewContainerRef) { componentRef = portal.viewContainerRef.createComponent( componentFactory, portal.viewContainerRef.length, portal.injector || portal.viewContainerRef.parentInjector); this.setDisposeFn(() => componentRef.destroy()); }
如果 ComponentPortal 沒有定義 ViewContainerRef,就用上文的組件工廠 ComponentFactory 來創(chuàng)建組件視圖,但還不夠,還需要把組件視圖掛載到組件樹上,并設(shè)置 ComponentPortal 銷毀回調(diào),回調(diào)包括需要從組件樹中拆卸出該視圖,并銷毀該組件:
else { componentRef = componentFactory.create(portal.injector || this._defaultInjector); this._appRef.attachView(componentRef.hostView); this.setDisposeFn(() => { this._appRef.detachView(componentRef.hostView); componentRef.destroy(); }); }
需要注意的是 this._appRef.attachView(componentRef.hostView);,當(dāng)把組件視圖掛載到組件樹時會自動觸發(fā)變更檢測(change detection)。
目前組件視圖只是掛載到視圖容器里,最后還需要在 DOM 中渲染出來:
this.outletElement.appendChild(this._getComponentRootNode(componentRef));
這里需要了解的是,視圖容器 ViewContainerRef、視圖 ViewRef、組件視圖 ComponentRef.hostView、嵌入視圖 EmbeddedViewRef 的關(guān)系。組件視圖和嵌入視圖都是視圖對象的具體形態(tài),而視圖是需要掛載到視圖容器內(nèi)才能正常工作,視圖容器內(nèi)可以掛載多個視圖,而所謂的視圖容器就是包裝任意一個 DOM 元素所生成的對象。視圖容器可以通過 @ViewChild 或者當(dāng)前組件構(gòu)造注入獲得,如果是通過 @ViewChild 查詢拿到當(dāng)前組件模板內(nèi)某個元素如 div,那 Angular 就會根據(jù)這個 div 元素生成一個視圖容器;如果是當(dāng)前組件構(gòu)造注入獲得,那就根據(jù)當(dāng)前組件掛載點(diǎn)如 app-root 生成視圖容器。所有的視圖都會依次作為子節(jié)點(diǎn)掛載到容器內(nèi)。attachTemplatePortal()
根據(jù)上文的類似設(shè)計,掛載 TemplatePortal 的源碼 就很簡單了。在構(gòu)造 TemplatePortal 必須依賴 ViewContainerRef,所以可以直接創(chuàng)建嵌入視圖 EmbeddedViewRef,然后手動強(qiáng)制執(zhí)行變更檢測。不像上文 this._appRef.attachView(componentRef.hostView); 會檢測整個組件樹,這里 viewRef.detectChanges(); 只檢測該組件及其子組件:
attachTemplatePortal(portal: TemplatePortal ): EmbeddedViewRef { let viewContainer = portal.viewContainerRef; let viewRef = viewContainer.createEmbeddedView(portal.templateRef, portal.context); viewRef.detectChanges();
最后在 DOM 渲染出視圖:
viewRef.rootNodes.forEach(rootNode => this.outletElement.appendChild(rootNode));
現(xiàn)在,就可以理解了如何把 Portal 掛載到 PortalOutlet 容器內(nèi)的具體過程,它并不復(fù)雜。
Portal 快捷指令讓我們重新回顧下 Portal 技術(shù)要解決的問題以及如何實(shí)現(xiàn):Portal 是為了解決可以在 Angular 框架執(zhí)行上下文之外動態(tài)創(chuàng)建子視圖,首先需要先實(shí)例化出 PortalOutlet 對象,然后實(shí)例化出一個 ComponentPortal 或 TemplatePortal,最后把 Portal 掛載到 PortalOutlet 上。整個過程非常簡單,但是難道 @angular/cdk/portal 沒有提供什么快捷方式,避免讓開發(fā)者寫大量重復(fù)代碼么?有。@angular/cdk/portal 提供了兩個指令:CdkPortal 和 CdkPortalOutlet。該兩個指令會隱藏所有實(shí)現(xiàn)細(xì)節(jié),開發(fā)者只需要簡單調(diào)用就行,使用方式可以查看官方 demo。
demo 實(shí)踐過程中,發(fā)現(xiàn)兩個問題:組件視圖都會多產(chǎn)生一個 p 標(biāo)簽;AppComponent 模板中掛載點(diǎn)作為 ViewContainerRef 時,掛載點(diǎn)還不能為 ng-template 和 ng-container,和印象中有出入。有時間在查找,誰知道原因,也可留言幫助解答,先謝了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/107849.html
摘要:模塊庫開發(fā)實(shí)例隨著前端框架的誕生,也會隨之出現(xiàn)一些組件庫,方便日常業(yè)務(wù)開發(fā)。在瀏覽器中,渲染是將模型映射到視圖的過程。然而視圖可以是頁面中的段落表單按鈕等其他元素,這些頁面元素內(nèi)部使用來表示。 angular模塊庫開發(fā)實(shí)例 隨著前端框架的誕生,也會隨之出現(xiàn)一些組件庫,方便日常業(yè)務(wù)開發(fā)。今天就聊聊angular4組件庫開發(fā)流程。 下圖是button組件的基礎(chǔ)文件。 showImg(htt...
摘要:但是,最后一步,事件怎么綁定呢這塊沒有深入研究了,不過我想,應(yīng)該這樣去實(shí)現(xiàn)也是沒有問題的。的具體做法是,把方法放到了一個叫做的組件上去實(shí)現(xiàn)這個功能,然后再把內(nèi)容放進(jìn)這個組件。其他的邏輯比如顯示隱藏之類,全部都放到組件自身上去實(shí)現(xiàn)。 1、Dialog組件提供什么功能,解決什么問題? zent的Dialog組件,使用姿勢是這樣的(代碼摘自zent官方文檔:https://www.youza...
摘要:谷歌在之后的版本加入了服務(wù)。但對于不能訪問谷歌服務(wù)器的地區(qū),問題就來了如果谷歌谷歌服務(wù)認(rèn)為網(wǎng)絡(luò)無法聯(lián)網(wǎng),就不會自動連接到該熱點(diǎn)。并且讓網(wǎng)絡(luò)的標(biāo)志上面顯示感嘆號標(biāo)志。這個感嘆號會使廣大強(qiáng)迫癥晚期患者無法接受。 本文原作者 長鳴鳥 ,未經(jīng)同意,轉(zhuǎn)載不帶名的嚴(yán)重鄙視。谷歌在Android5.0之后的版本加入了CaptivePotalLogin服務(wù)。本服務(wù)的功能是檢查網(wǎng)絡(luò)連接互聯(lián)網(wǎng)情況,主要針...
摘要:一例子看到一個有趣的現(xiàn)象,就是多層嵌套的數(shù)組經(jīng)過后,平鋪成了,接下來以該例解析二作用源碼進(jìn)行基本的判斷和初始化后,調(diào)用該方法就是重命名了,即解析注意,該數(shù)組在里面滾了一圈后,會結(jié)果三作用的包裹器源碼第一次第二次如果字符串中有連續(xù)多個的話 showImg(https://segmentfault.com/img/remote/1460000019968077?w=1240&h=698);...
閱讀 3421·2021-10-20 13:49
閱讀 2793·2021-09-29 09:34
閱讀 3691·2021-09-01 11:29
閱讀 3081·2019-08-30 11:01
閱讀 838·2019-08-29 17:10
閱讀 866·2019-08-29 12:48
閱讀 2777·2019-08-29 12:40
閱讀 1348·2019-08-29 12:30