簡體   English   中英

為什么 Angular 2 看不到動態創建的選擇器?

[英]Why Angular 2 does not see a dynamically created selector?

這是起始頁:

<!DOCTYPE html>
<html>
<head>
    <script>document.write('<base href="/app/" />');</script>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>App</title>
</head>
<body>

<my-app>
    Loading...
</my-app>

<!-- 1. Load libraries -->
<!-- IE required polyfills, in this exact order -->
<script src="/cp/node_modules/es6-shim/es6-shim.min.js"></script>
<script src="/cp/node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="/cp/node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>

<script src="/cp/node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="/cp/node_modules/systemjs/dist/system.src.js"></script>
<script src="/cp/node_modules/rxjs/bundles/Rx.js"></script>
<script src="/cp/node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="/cp/node_modules/angular2/bundles/router.dev.js"></script>
<script src="/cp/node_modules/angular2/bundles/http.dev.js"></script>

<!-- 2. Configure SystemJS -->
<script>
    System.config({
        packages: {
            app: {
                format: 'register',
                defaultExtension: 'js'
            }
        }
    });
    System.import('app/main')
            .then(null, console.error.bind(console));
</script>
</body>
</html>

此組件 ( startComponent ) 加載應用程序的根頁面:

@Component({
    selector: 'my-app',
    templateUrl: 'app/mainPage.html',
    directives: [RouterOutlet,RouterLink,ROUTER_DIRECTIVES],
    providers: [
        ROUTER_PROVIDERS,
        HTTP_PROVIDERS
    ]
})

頁面mainPage.html包含:

<div id="content">
    <a [routerLink]="['NextPage']">NextPage</a>
    <my-content></my-content>
</div>

當我們轉到鏈接NextPage ,初始化這個組件:

@Component({
    selector: 'my-content',
    templateUrl: 'app/nextPage.html'
})

export class NextPageComponent implements OnInit {
    public str = "";

    constructor() {}

    ngOnInit() {
        this.getStr();
    }

    getStr(){
        this.str = "abc";
    }
}

NextPageComponent應該向由startComponent的組件創建的選擇器my-content插入一行“abc”。 但不知何故,他在選擇器my-app的末尾插入了abc行,而不是my-content

也就是說,最終我們得到如下頁面:

<my-app>
    <div id="content">
        <a [routerLink]="['NextPage']">NextPage</a>
        <my-content></my-content>
    </div>
    <my-content _ngcontent-quv-2=""><div>abc</div></my-content>
</my-app>

但是,我想得到這樣一個頁面:

<my-app>
    <div id="content">
        <a [routerLink]="['NextPage']">NextPage</a>
        <my-content><div>abc</div></my-content>
    </div>
</my-app>

為什么會發生這種情況? 我究竟做錯了什么?

Router內部使用DynamicComponentLoader (請參閱Router 的源代碼)來動態實例化組件(名稱幾乎就是這么說的)。

它專門使用loadNextToLocation和文檔狀態

loadNextToLocation(...)

創建 Component 的一個實例並將其附加到在指定為 ElementRef 的位置找到的 View Container。

如您所見,它將組件附加到視圖中。 它不會檢查視圖以查看它是否與其中的某些內容匹配,因此無論您是否有某些與選擇器匹配的元素,它都不會工作,因為同樣,路由器不會在視圖上查找任何內容,而是附加組件在視圖中,換句話說,它正在推動它。

讓我們自己嘗試這種行為。 讓我們在某個組件的視圖中放入一些與某個動態組件選擇器匹配的元素

@Component({
  selector : 'dynamic-cmp',
  template : 'Dynamic template'
})
class DynamicCmp {}

@Component({
  selector: 'my-app',
  template : `
    <dynamic-cmp></dynamic-cmp>    <!-- Element matching DynamicCmp selector -->
    <dynamic-cmp></dynamic-cmp>    <!-- Element matching DynamicCmp selector -->
  `
})
export class App {
  constructor(private _dcl: DynamicComponentLoader, private _eRef: ElementRef) {}
  
  ngOnInit() {
    this._dcl.loadNextToLocation(DynamicCmp, this._eRef);
  }
}

Plnkr與上面的例子

注意:我沒有在指令屬性中添加 DynamicCmp

當您運行該示例並查看 DOM 時,您將看到以下內容

<my-app>
    <dynamic-cmp></dynamic-cmp>
    <dynamic-cmp></dynamic-cmp>
</my-app>
<dynamic-cmp _ngcontent-ybo-2="">Dynamic template</dynamic-cmp>

即使它們與動態組件的選擇器匹配,也有兩個空的dynamic-cmp元素。

這正是 Router 所做的,這就是您看到這種行為的原因。 路由器不依賴於視圖(它不尋找匹配的選擇器)也不依賴於指令,它動態加載組件(推送它們)到指定的視圖中。

我希望這可以澄清正在發生的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM