成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

源碼分析 @angular/cdk 之 Portal

BearyChat / 511人閱讀

摘要:這些依賴對象也進一步暴露了其設(shè)計思想。關(guān)鍵功能包括在上下文內(nèi)掛載在上下文外掛載在上下文外共享數(shù)據(jù)。在構(gòu)造必須依賴,所以可以直接創(chuà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é)點動態(tài)的顯示到父節(jié)點外的 DOM 節(jié)點上,該技術(shù)的一個經(jīng)典用例應(yīng)該就是 Dialog 了。設(shè)想一下在設(shè)計 Dialog 時所需要的主要功能點:當(dāng)點擊一個 button 時,一般需要在 body 標(biāo)簽前動態(tài)掛載一個組件視圖;該 dialog 組件視圖需要共享數(shù)據(jù)。由此看出,Portal 核心就是在任意一個 DOM 節(jié)點內(nèi)動態(tài)生成一個視圖,該 視圖卻可以置于框架上下文環(huán)境之外。那 Angular 中有沒有類似相關(guān)技術(shù)來解決這個問題呢?

Angular Portal 就是用來在任意一個 DOM 節(jié)點內(nèi)動態(tài)生成一個視圖,該視圖既可以是一個組件視圖,也可以是一個模板視圖,并且生成的視圖可以掛載在任意一個 DOM 節(jié)點,甚至該節(jié)點可以置于 Angular 上下文環(huán)境之外,也同樣可以與該視圖共享數(shù)據(jù)。該 Portal 技術(shù)主要就涉及兩個簡單對象:PortalOutletPortal。從字面意思就可知道,PortalOutlet 應(yīng)該就是把某一個 DOM 節(jié)點包裝成一個掛載容器供 Portal 來掛載,等同于 插頭-插線板 模式的 插線板Portal 應(yīng)該就是把組件視圖或者模板視圖包裝成一個 Portal 掛載到 PortalOutlet 上,等同于 插頭-插線板 模式的 插頭。這與 @angular/router 中 Router 和 RouterOutlet 設(shè)計思想很類似,在寫路由時,router-outlet 就是個掛載點,Angular 會把由 Router 包裝的組件掛載到 router-outlet 上,所以這個設(shè)計思想不是個新東西。

如何使用 Portal

Portal 只是一個抽象泛型類,而 ComponentPortalTemplatePortal 才是包裝組件或模板對應(yīng)的 Portal 具體類,查看兩個類的構(gòu)造函數(shù)的主要依賴,都基本是依賴于:該組件或模板對象;視圖容器即掛載點,是通過 ViewContainerRef 包裝的對象;如果是組件視圖還得依賴 injector,模板視圖得依賴 context 變量。這些依賴對象也進一步暴露了其設(shè)計思想。

抽象類 BasePortalOutletPortalOutlet 的基本實現(xiàn),同時包含了三個重要方法:attach 表示把 Portal 掛載到 PortalOutlet 上,并定義了兩個抽象方法,來具體實現(xiàn)掛載組件視圖還是模板視圖:

abstract attachComponentPortal(portal: ComponentPortal): ComponentRef;
abstract attachTemplatePortal(portal: TemplatePortal): EmbeddedViewRef;

detach 表示從 PortalOutlet 中拆卸出該 Portal,而 PortalOutlet 中可以掛載多個 Portal,dispose 表示整體并永久銷毀 PortalOutlet。其中,還有一個重要類 DomPortalOutletBasePortalOutlet 的子類,可以在 Angular 上下文之外 創(chuàng)建一個 PortalOutlet,并把 Portal 掛載到該 PortalOutlet 上,比如將 body 最后子元素 div 包裝為一個 PortalOutlet,然后將組件視圖或模板視圖掛載到該掛載點上。這里的的難點就是如果該掛載點在 Angular 上下文之外,那掛載點內(nèi)的 Portal 如何與 Angular 上下文內(nèi)的組件共享數(shù)據(jù)。 DomPortalOutlet 還實現(xiàn)了上面的兩個抽象方法:attachComponentPortalattachTemplatePortal,如果對代碼細節(jié)感興趣可接著看下文。

現(xiàn)在已經(jīng)知道了 @angular/cdk/portal 中最重要的兩個核心,即 PortalPortalOutlet,接下來寫一個 demo 看看如何使用 PortalPortalOutlet 來在 Angular 上下文之外 創(chuàng)建一個 ComponentPortalTemplatePortal。

Demo 關(guān)鍵功能包括:在 Angular 上下文內(nèi) 掛載 TemplatePortal/ComponentPortal;在 Angular 上下文外 掛載 TemplatePortal/ComponentPortal;在 Angular 上下文外 共享數(shù)據(jù)。接下來讓我們逐一實現(xiàn)每個功能點。

Angular 上下文內(nèi)掛載 Portal

在 Angular 上下文內(nèi)掛載 Portal 比較簡單,首先需要做的第一步就是實例化出一個掛載容器 PortalOutlet,可以通過實例化 DomPortalOutlet 得到該掛載容器。查看 DomPortalOutlet 的構(gòu)造依賴主要包括:掛載的元素節(jié)點 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ù) 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

Template Portal 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 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ù)點還是 attach() 方法的實現(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è)計步驟就和上文完全一樣:實例化一個處于 Angular 上下文之外的 PortalOutlet,然后掛載 ComponentPortal 和 TemplatePortal:

@Component({
  selector: "app-root",
  template: `
    

Open a ComponentPortal Outside Angular Context

Open a TemplatePortal Outside Angular Context

Template Portal 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 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ù)

最難點還是如何與處于 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

Template Portal Outside Angular Context, the Sharing Data is {{name}}

`, }) export class AppComponent { sharingTemplateData: string = "lx1035"; @ViewChild("_templatePortalOutsideAngularContextWithSharingData", {read: TemplateRef}) _templateWithSharingData: TemplateRef; @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ā)者實例化一個自定義注入器?,F(xiàn)在思路已經(jīng)有了,看看代碼具體實現(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 ComponentPortal const componentPortal = new ComponentPortal(DialogComponentWithSharingData); // attach a ComponentPortal to a DomPortalOutlet portalOutlet.attach(componentPortal); }

通過 Injector 就可以實現(xiàn) ComponentPortal 與 AppComponent 共享數(shù)據(jù)了,該技術(shù)對于 Dialog 實現(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 掛載進來,具體掛載過程是怎樣的?查看 BasePortalOutletattach() 的源碼實現(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)用 attachComponentPortalattachTemplatePortal 方法。下面將分別查看兩個方法的實現(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)前組件掛載點如 app-root 生成視圖容器。所有的視圖都會依次作為子節(jié)點掛載到容器內(nèi)。
attachTemplatePortal()

根據(jù)上文的類似設(shè)計,掛載 TemplatePortal 的源碼 就很簡單了。在構(gòu)造 TemplatePortal 必須依賴 ViewContainerRef,所以可以直接創(chuàng)建嵌入視圖 EmbeddedViewRef,然后手動強制執(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ù)要解決的問題以及如何實現(xiàn):Portal 是為了解決可以在 Angular 框架執(zhí)行上下文之外動態(tài)創(chuàng)建子視圖,首先需要先實例化出 PortalOutlet 對象,然后實例化出一個 ComponentPortal 或 TemplatePortal,最后把 Portal 掛載到 PortalOutlet 上。整個過程非常簡單,但是難道 @angular/cdk/portal 沒有提供什么快捷方式,避免讓開發(fā)者寫大量重復(fù)代碼么?有。@angular/cdk/portal 提供了兩個指令:CdkPortalCdkPortalOutlet。該兩個指令會隱藏所有實現(xiàn)細節(jié),開發(fā)者只需要簡單調(diào)用就行,使用方式可以查看官方 demo。

demo 實踐過程中,發(fā)現(xiàn)兩個問題:組件視圖都會多產(chǎn)生一個 p 標(biāo)簽;AppComponent 模板中掛載點作為 ViewContainerRef 時,掛載點還不能為 ng-templateng-container,和印象中有出入。有時間在查找,誰知道原因,也可留言幫助解答,先謝了。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/107849.html

相關(guān)文章

  • angular模塊庫開發(fā)實例

    摘要:模塊庫開發(fā)實例隨著前端框架的誕生,也會隨之出現(xiàn)一些組件庫,方便日常業(yè)務(wù)開發(fā)。在瀏覽器中,渲染是將模型映射到視圖的過程。然而視圖可以是頁面中的段落表單按鈕等其他元素,這些頁面元素內(nèi)部使用來表示。 angular模塊庫開發(fā)實例 隨著前端框架的誕生,也會隨之出現(xiàn)一些組件庫,方便日常業(yè)務(wù)開發(fā)。今天就聊聊angular4組件庫開發(fā)流程。 下圖是button組件的基礎(chǔ)文件。 showImg(htt...

    JerryZou 評論0 收藏0
  • 讀zent源碼Dialog組件實現(xiàn)

    摘要:但是,最后一步,事件怎么綁定呢這塊沒有深入研究了,不過我想,應(yīng)該這樣去實現(xiàn)也是沒有問題的。的具體做法是,把方法放到了一個叫做的組件上去實現(xiàn)這個功能,然后再把內(nèi)容放進這個組件。其他的邏輯比如顯示隱藏之類,全部都放到組件自身上去實現(xiàn)。 1、Dialog組件提供什么功能,解決什么問題? zent的Dialog組件,使用姿勢是這樣的(代碼摘自zent官方文檔:https://www.youza...

    陳江龍 評論0 收藏0
  • Android系統(tǒng)開發(fā)修改Captive Potal Service(消滅感嘆號)

    摘要:谷歌在之后的版本加入了服務(wù)。但對于不能訪問谷歌服務(wù)器的地區(qū),問題就來了如果谷歌谷歌服務(wù)認(rèn)為網(wǎng)絡(luò)無法聯(lián)網(wǎng),就不會自動連接到該熱點。并且讓網(wǎng)絡(luò)的標(biāo)志上面顯示感嘆號標(biāo)志。這個感嘆號會使廣大強迫癥晚期患者無法接受。 本文原作者 長鳴鳥 ,未經(jīng)同意,轉(zhuǎn)載不帶名的嚴(yán)重鄙視。谷歌在Android5.0之后的版本加入了CaptivePotalLogin服務(wù)。本服務(wù)的功能是檢查網(wǎng)絡(luò)連接互聯(lián)網(wǎng)情況,主要針...

    Zhuxy 評論0 收藏0
  • React源碼解析React.children.map()

    摘要:一例子看到一個有趣的現(xiàn)象,就是多層嵌套的數(shù)組經(jīng)過后,平鋪成了,接下來以該例解析二作用源碼進行基本的判斷和初始化后,調(diào)用該方法就是重命名了,即解析注意,該數(shù)組在里面滾了一圈后,會結(jié)果三作用的包裹器源碼第一次第二次如果字符串中有連續(xù)多個的話 showImg(https://segmentfault.com/img/remote/1460000019968077?w=1240&h=698);...

    kuangcaibao 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<