<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                在angular中可以簡單的這樣的認為:每個界面就一個組件。比如當前我們需要一個教師添加界面,那么就對應需要一個教師添加組件`TeacherAddComponent`。 # 創建組件 我們在`app`文件夾下,創建`TeacherAddComponent`的C層`teacher-add.component.ts`以及V層`teacher-add.component.html`并輸入以下內容: app/teacher-add.component.ts ```js import {Component, OnInit} from '@angular/core'; /** * 教師添加組件 */ @Component({ templateUrl: './teacher-add.component.html' ? }) export class TeacherAddComponent implements OnInit { ? ngOnInit(): void { } } ``` * ? 定義項目模板`teacher-add.component.html` * ? 初始化組件 teacher-add.component.html ```html <form id="teacherAddForm"> <div> <label for="name">姓名:</label> <input type="text" id="name" name="name"/> </div> <div> <label for="username">用戶名:</label> <input type="text" id="username" name="username"> </div> <div> <label for="email">郵箱:</label> <input type="email" id="email" name="email"> </div> <div> <label>性別:</label> <label> <input type="radio" name="sex" value="true"> 男</label> <label> <input type="radio" name="sex" value="false"> 女</label> </div> <div> <button>提交</button> </div> </form> ``` # 綁定路由 app/app-routing.module.ts ```js import {NgModule} from '@angular/core'; import {Routes, RouterModule} from '@angular/router'; import {TeacherAddComponent} from './teacher-add.component'; const routes: Routes = [ { ? path: 'add', ? component: TeacherAddComponent ? } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } ``` * ? routes數組中的每一項的類型均是對象`{}`。 * ? 該對象中的`path`屬性規定了訪問路徑。 * ? 該對象中的`component`屬性規定了對應的組件。 上面的過程我們還可以稱為:編排路由的索引,即訪問某些URL應該對應找到些組件。在英文中`map`譯成名詞是地圖,譯成動詞則可取編排索引之意,所以上述過程在英文中又叫做`mapping`。以`ing`結尾的代表正在進行的動作,所以我們剛剛在綁定路由的過程中,恰恰是在`mapping`。而`mapping`在計算機的專業術語中,又稱為`映射`。 # 測試 ![](https://img.kancloud.cn/7c/52/7c52145d5bb11a50cca22ca124a0f9cf_1111x132.png) 這個錯誤大概再說:TeacherAddComponent組件并不屬于任何模塊`或者`它雖然屬于某個模塊(潛臺詞)但該模塊并沒有并導入到當前模塊中。 之所以出現了該錯誤由于我同大家一樣,在編寫教程的時候,早就把教程中在前面講過的一張圖忘的一干二凈了。 ![](https://img.kancloud.cn/4d/be/4dbe104efb560c95003f6f1cf6f3fe83_390x403.png) > 我們如此聰明的大腦會自動忘掉一些我們認為并不重要的事情然后為更重要的事情來騰挪出記憶空間。我們成長的過程其實是一次次地抽象、匯總、總結的過程,把原本繁瑣的東西一點點的總結抽像壓縮到大腦恰恰可以掌握的程度。而最終的壓縮空間取決于我們在歷史上對此類知識的掌握以及我們主動去思考的時間。 由上圖可以看出:**組件是依賴于模塊而存在的** ## 組件添加到模塊 我們此時,再讀1.5.1小節,還會收獲:在`AppMoudle`的`@NgMoudle`注解的`declarations`選項是用來聲明該模塊下的組件的。 app.module.ts 變更前 ```js @NgModule({ declarations: [ AppComponent ], ``` app.module.ts 變更后 ```js import {TeacherAddComponent} from './teacher-add.component'; @NgModule({ declarations: [ AppComponent, TeacherAddComponent ], ``` 此時,我們訪問:[http://localhost:4200/add](http://localhost:4200/add)地址時,控制臺的錯誤消失。隨之而來的新問題是:為什么還在顯示`AppComponent`,而不是顯示`TeacherAddComponent`。這是由于: * ① 系統定義了啟動組件為`AppComponent`,則在系統啟動時,永遠會啟動該組件。 * ② 路由定義僅代表定義了轉發規則,但并不代表立即啟動此規則。 * ③ 由啟動的的組件`AppComponent`來決定是否啟用路由規則。 ## 在`AppComponent`中啟用路由 在`AppComponent`的V層的適當的位置添加代碼`<router-outlet></router-outlet>`,則表示:?加載路由組件(啟用路由)?將路由組件顯示的內容顯示在當前位置。 app.component.html ``` <router-outlet></router-outlet> ? <table> <tr> <th>序號</th> <th>姓名</th> <th>用戶名</th> <th>郵箱</th> <th>性別</th> <th>注冊時間</th> <th>操作</th> </tr> <tr *ngFor="let teacher of teachers" > <td>{{teacher.id}}</td> <td>{{teacher.name}}</td> <td>{{teacher.username}}</td> <td>{{teacher.email}}</td> <td> <span *ngIf="teacher.sex">女</span> <span *ngIf="!teacher.sex">男</span> </td> <td>{{teacher.createTime | date: 'yyyy-MM-dd'}}</td> <td>刪除</td> </tr> </table> ``` * ? 放到教師列表前面 效果: ![](https://img.kancloud.cn/01/6c/016c7c32a76f3b0e1309a8081a18d66e_485x208.png) ```html <table> <tr> <th>序號</th> <th>姓名</th> <th>用戶名</th> <th>郵箱</th> <th>性別</th> <th>注冊時間</th> <th>操作</th> </tr> <tr *ngFor="let teacher of teachers" > <td>{{teacher.id}}</td> <td>{{teacher.name}}</td> <td>{{teacher.username}}</td> <td>{{teacher.email}}</td> <td> <span *ngIf="teacher.sex">女</span> <span *ngIf="!teacher.sex">男</span> </td> <td>{{teacher.createTime | date: 'yyyy-MM-dd'}}</td> <td>刪除</td> </tr> </table> <router-outlet></router-outlet> ? ``` * ?放至教師列表后面 ![](https://img.kancloud.cn/11/bd/11bd40daabf785e650559b51a279617c_514x215.png) # 本節小測 嘗試再建立`TeacherEditComponent`組件,將其映射到`edit`地址上并測試。 ## 上節答案 由于`bootstrap`屬性的接收值是一個數組,那么我認為是可以輸入多個啟動組件的。為了驗證自己想的是否正確,我直接將`TeacherAddComponent`也加入到啟動的列表中。 ```js import {TeacherAddComponent} from './teacher-add.component'; bootstrap: [AppComponent, TeacherAddComponent] ``` 訪問[http://localhost:4200/](http://localhost:4200/)結果: `TeacherAddComponent_Host.ngfactory.js? [sm]:1 ERROR Error: The selector "ng-component" did not match any elements` > 結論一:不行,啟動組件只支持一個。 其實到這我們直接記往該結論就可以了,在很多項目中我們的確只使用一個`AppComponent`組件就夠了,這個結論雖然不見得是`絕對正確`的,但已經解決了我們當前碰到的問題,本著`夠用的就是最好的`原則我們已經圓滿的完成了任務。 ***** 前面我們講過知識就是在不斷的證真與證違中積累及升華的。下面我進一步的展示一下該理論。 看報錯提示好像與啟動組件的個數無關,下面我繼承測試:在啟動屬性上只保留`TeacherAddComponent`,刪除原`AppComponent`組件,看是否正常啟動`TeacherAddComponent`。 ```js bootstrap: [TeacherAddComponent] ``` 結果仍然是: `TeacherAddComponent_Host.ngfactory.js? [sm]:1 ERROR Error: The selector "ng-component" did not match any elements` 此時,便發生了證違。即證明結論是`違`的,這將是對此知識點升華的開始。 > 結論二:結論一不一定正確。 ***** 觀察報錯信息,說這個"ng-component" `selector` 沒有匹配上任何的元素。然后我們通過觀察`AppComponent`與`TeacherAddComponent`發現:`TeacherAddComponent`較`AppComponent`少了個`selector`屬性 app.component.ts ```js @Component({ selector: 'app-root', ? templateUrl: './app.component.html', styleUrls: ['./app.component.sass'] }) /** * 實現OnInit接口,該接口規定了ngOnInit方法。 * angular在組件準備完畢后,將自動調用ngOnInit方法 */ export class AppComponent implements OnInit { ``` * ?此處有selector屬性 teacher-add.component.ts ```js @Component({ ? templateUrl: './teacher-add.component.html' }) export class TeacherAddComponent implements OnInit { ngOnInit(): void { } } ``` ? 未添加selector 嘗試添加selector teacher-add.component.ts ```js @Component({ selector: 'app-teacher-add', templateUrl: './teacher-add.component.html' }) ``` 此時報錯信息變成了: `TeacherAddComponent_Host.ngfactory.js? [sm]:1 ERROR Error: The selector "app-teacher-add" did not match any elements` 看來的確有影響,但卻沒有解決根本問題。 > 結論:是否配置selector對啟動成功與否無影響 。如果未給組件配置selector,則系統為其添加默認selector => `ng-component`。 ***** 我們繼續瞎猜加驗證。剛剛報錯的`app-teacher-add`是我剛剛手動添加的,然后報錯了。那么以前使用`AppComponent`,其中的`selector`是`app-root`為什么不報錯呢?試試將兩個組件的`selector`換一下: teacher-add.component.ts ```js @Component({ selector: 'app-root', templateUrl: './teacher-add.component.html' }) export class TeacherAddComponent implements OnInit { ngOnInit(): void { } } ``` app.component.ts ```js @Component({ selector: 'app-teacher-add', templateUrl: './app.component.html', styleUrls: ['./app.component.sass'] }) /** * 實現OnInit接口,該接口規定了ngOnInit方法。 * angular在組件準備完畢后,將自動調用ngOnInit方法 */ export class AppComponent implements OnInit { ``` 結果: ![](https://img.kancloud.cn/a6/7c/a67c21674248bc1e9d60eba16e1a335f_278x192.png) 正常顯示了! > 結論:可以變更啟動的組件,但該組件的`selector`必須是`app-root` ***** 我們繼續猜:該組件的`selector`必須是`app-root`,為什么不可以是其它呢?可以在哪指定了`app-root`這個值。全項目搜索下看看能不能找到這個指定的它的位置。 ![](https://img.kancloud.cn/b0/67/b0678bc5653a11b7ccaab381d1702cd0_960x207.png) 從搜索的結果上不難看出,原來在`index.html`中規定了這個`app-root`,打開該文件然后將其修改為:`app-teacher-add`呢? index.html ```html <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>WebApp</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> </head> <body> <app-teacher-add></app-teacher-add> </body> </html> ``` 結果: `TeacherAddComponent_Host.ngfactory.js? [sm]:1 ERROR Error: The selector "app-root" did not match any elements` 我好像懂了:啟動時找`TeacherAddComponent`沒錯,`TeacherAddComponent`的selector為`app-root`(我們前面剛改了),系統啟動時在`index.html`中查找該selector`app-root`,如果沒找到則報 `The selector "app-root" did not match any elements`,即這個選擇器沒有匹配任何元素的錯誤。 > 結論三:啟用組件的selector必須在index.html中被使用。 ***** 最后,我們再來徹底推翻原結論一,即啟動組件只能有一個。 我們先進行組件的恢復,將`TeacherAddComponent`的`selector`設置為`app-teacher-add`,將`AppComponent`的`selector` 設置為`app-root`。保持`index.html`中的`<app-teacher-add></app-teacher-add>`不變。 系統正常顯示教師添加界面。 然后將兩個組件都添加到啟動中: ```js bootstrap: [TeacherAddComponent, AppComponent] ``` 再將`app-root`也添加到`index.html`中。 index.html ```html <body> <app-teacher-add></app-teacher-add> <app-root></app-root> </body> ``` 測試: ![](https://img.kancloud.cn/b3/f4/b3f4d18cb1d020038e8b77b7d9473a5d_493x276.png) > 結論四:啟用組件可以為多個,但每個組的selector必須在index.html中被使用。 **總結:** 結論四并不見得正確,但它此時已經解決了我前面所有的問題。在當前來講,已經是最適用的合理的答案。 > 結論是否絕對正確并不重要,重要的是它是否適用于當前自己遇到的所有同類問題。 [源碼地址](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.3.1.0) # 參考文檔 | 名稱 | 鏈接 | 預計學習時長(分) | | --- | --- | --- | | 入口組件 | [https://www.angular.cn/guide/entry-components](https://www.angular.cn/guide/entry-components) | 10 | | 啟動過程 | [https://www.angular.cn/guide/bootstrapping](https://www.angular.cn/guide/bootstrapping) | 15 | | 路由配置 | [https://www.angular.cn/guide/router#configuration](https://www.angular.cn/guide/router#configuration) | 5 | | 路由出口 | [https://www.angular.cn/guide/router#router-outlet](https://www.angular.cn/guide/router#router-outlet) | 5 | | 組件簡介 | [https://www.angular.cn/guide/architecture-components](https://www.angular.cn/guide/architecture-components) | 25 | | 源碼地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.3.1](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.3.1) | - |
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看