[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fcomponents":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fcomponents":1039,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fcomponents":1062},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":1035,"stem":1036,"id":1037,"extension":1038},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fcomponents","组件与模板","Angular 组件由 TypeScript 类、模板与样式组成，通过 @Component 装饰器配置。见 Angular 基础。","技能小册",[12,13],"angular","components","2021-07-11",false,{"type":17,"value":18,"toc":1026},"minimark",[19,22,50,54,404,423,426,532,536,547,717,726,729,777,780,845,886,890,966,969,972,1022],[20,21,8],"h1",{"id":8},[23,24,25,26,30,31,34,35,38,39,43,44,49],"p",{},"Angular 组件由 ",[27,28,29],"strong",{},"TypeScript 类","、",[27,32,33],{},"模板","与",[27,36,37],{},"样式","组成，通过 ",[40,41,42],"code",{},"@Component"," 装饰器配置。见 ",[45,46,48],"a",{"href":47},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fbasics","Angular 基础","。",[51,52,53],"h2",{"id":53},"组件定义",[55,56,61],"pre",{"className":57,"code":58,"language":59,"meta":60,"style":60},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { Component, input, output, signal } from \"@angular\u002Fcore\";\n\n@Component({\n  selector: \"app-counter\",\n  standalone: true,\n  template: `\n    \u003Cbutton type=\"button\" (click)=\"increment()\">{{ count() }}\u003C\u002Fbutton>\n  `,\n})\nexport class CounterComponent {\n  \u002F** 父组件可绑定：[initial]=\"5\" *\u002F\n  initial = input(0);\n  changed = output\u003Cnumber>();\n\n  count = signal(0);\n\n  increment() {\n    this.count.update((c) => c + 1);\n    this.changed.emit(this.count());\n  }\n}\n","ts","",[40,62,63,116,123,139,159,173,184,190,198,207,224,231,256,281,286,304,309,319,363,392,398],{"__ignoreMap":60},[64,65,68,72,76,80,83,86,88,91,93,96,99,102,106,110,113],"span",{"class":66,"line":67},"line",1,[64,69,71],{"class":70},"sVHd0","import",[64,73,75],{"class":74},"sP7_E"," {",[64,77,79],{"class":78},"su5hD"," Component",[64,81,82],{"class":74},",",[64,84,85],{"class":78}," input",[64,87,82],{"class":74},[64,89,90],{"class":78}," output",[64,92,82],{"class":74},[64,94,95],{"class":78}," signal",[64,97,98],{"class":74}," }",[64,100,101],{"class":70}," from",[64,103,105],{"class":104},"sjJ54"," \"",[64,107,109],{"class":108},"s_sjI","@angular\u002Fcore",[64,111,112],{"class":104},"\"",[64,114,115],{"class":74},";\n",[64,117,119],{"class":66,"line":118},2,[64,120,122],{"emptyLinePlaceholder":121},true,"\n",[64,124,126,129,133,136],{"class":66,"line":125},3,[64,127,128],{"class":74},"@",[64,130,132],{"class":131},"sGLFI","Component",[64,134,135],{"class":78},"(",[64,137,138],{"class":74},"{\n",[64,140,142,146,149,151,154,156],{"class":66,"line":141},4,[64,143,145],{"class":144},"skxfh","  selector",[64,147,148],{"class":74},":",[64,150,105],{"class":104},[64,152,153],{"class":108},"app-counter",[64,155,112],{"class":104},[64,157,158],{"class":74},",\n",[64,160,162,165,167,171],{"class":66,"line":161},5,[64,163,164],{"class":144},"  standalone",[64,166,148],{"class":74},[64,168,170],{"class":169},"syTEX"," true",[64,172,158],{"class":74},[64,174,176,179,181],{"class":66,"line":175},6,[64,177,178],{"class":144},"  template",[64,180,148],{"class":74},[64,182,183],{"class":104}," `\n",[64,185,187],{"class":66,"line":186},7,[64,188,189],{"class":108},"    \u003Cbutton type=\"button\" (click)=\"increment()\">{{ count() }}\u003C\u002Fbutton>\n",[64,191,193,196],{"class":66,"line":192},8,[64,194,195],{"class":104},"  `",[64,197,158],{"class":74},[64,199,201,204],{"class":66,"line":200},9,[64,202,203],{"class":74},"}",[64,205,206],{"class":78},")\n",[64,208,210,213,217,221],{"class":66,"line":209},10,[64,211,212],{"class":70},"export",[64,214,216],{"class":215},"sbsja"," class",[64,218,220],{"class":219},"sbgvK"," CounterComponent",[64,222,223],{"class":74}," {\n",[64,225,227],{"class":66,"line":226},11,[64,228,230],{"class":229},"sutJx","  \u002F** 父组件可绑定：[initial]=\"5\" *\u002F\n",[64,232,234,238,242,245,247,251,254],{"class":66,"line":233},12,[64,235,237],{"class":236},"sucvu","  initial",[64,239,241],{"class":240},"smGrS"," =",[64,243,85],{"class":244},"sVXei",[64,246,135],{"class":78},[64,248,250],{"class":249},"srdBf","0",[64,252,253],{"class":78},")",[64,255,115],{"class":74},[64,257,259,262,264,266,269,273,276,279],{"class":66,"line":258},13,[64,260,261],{"class":236},"  changed",[64,263,241],{"class":240},[64,265,90],{"class":244},[64,267,268],{"class":74},"\u003C",[64,270,272],{"class":271},"sZMiF","number",[64,274,275],{"class":74},">",[64,277,278],{"class":78},"()",[64,280,115],{"class":74},[64,282,284],{"class":66,"line":283},14,[64,285,122],{"emptyLinePlaceholder":121},[64,287,289,292,294,296,298,300,302],{"class":66,"line":288},15,[64,290,291],{"class":236},"  count",[64,293,241],{"class":240},[64,295,95],{"class":244},[64,297,135],{"class":78},[64,299,250],{"class":249},[64,301,253],{"class":78},[64,303,115],{"class":74},[64,305,307],{"class":66,"line":306},16,[64,308,122],{"emptyLinePlaceholder":121},[64,310,312,315,317],{"class":66,"line":311},17,[64,313,314],{"class":244},"  increment",[64,316,278],{"class":74},[64,318,223],{"class":74},[64,320,322,326,329,332,334,337,339,341,345,347,350,353,356,359,361],{"class":66,"line":321},18,[64,323,325],{"class":324},"s39Yj","    this",[64,327,328],{"class":74},".",[64,330,331],{"class":78},"count",[64,333,328],{"class":74},[64,335,336],{"class":131},"update",[64,338,135],{"class":144},[64,340,135],{"class":74},[64,342,344],{"class":343},"s99_P","c",[64,346,253],{"class":74},[64,348,349],{"class":215}," =>",[64,351,352],{"class":78}," c",[64,354,355],{"class":240}," +",[64,357,358],{"class":249}," 1",[64,360,253],{"class":144},[64,362,115],{"class":74},[64,364,366,368,370,373,375,378,380,383,385,387,390],{"class":66,"line":365},19,[64,367,325],{"class":324},[64,369,328],{"class":74},[64,371,372],{"class":78},"changed",[64,374,328],{"class":74},[64,376,377],{"class":131},"emit",[64,379,135],{"class":144},[64,381,382],{"class":324},"this",[64,384,328],{"class":74},[64,386,331],{"class":131},[64,388,389],{"class":144},"())",[64,391,115],{"class":74},[64,393,395],{"class":66,"line":394},20,[64,396,397],{"class":74},"  }\n",[64,399,401],{"class":66,"line":400},21,[64,402,403],{"class":74},"}\n",[23,405,406,407,411,412,415,416,419,420,422],{},"上例使用 ",[45,408,410],{"href":409},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fsignals\u002Fbasics","Signal"," 与 ",[27,413,414],{},"input\u002Foutput"," API（Angular 17.1+ 推荐）；",[40,417,418],{},"signal"," 需从 ",[40,421,109],{}," 导入。",[51,424,425],{"id":425},"数据绑定",[427,428,429,445],"table",{},[430,431,432],"thead",{},[433,434,435,439,442],"tr",{},[436,437,438],"th",{},"语法",[436,440,441],{},"方向",[436,443,444],{},"示例",[446,447,448,464,479,494,515],"tbody",{},[433,449,450,456,459],{},[451,452,453],"td",{},[40,454,455],{},"{{ expr }}",[451,457,458],{},"插值",[451,460,461],{},[40,462,463],{},"{{ title }}",[433,465,466,471,474],{},[451,467,468],{},[40,469,470],{},"[property]=\"expr\"",[451,472,473],{},"属性绑定",[451,475,476],{},[40,477,478],{},"[disabled]=\"isBusy\"",[433,480,481,486,489],{},[451,482,483],{},[40,484,485],{},"(event)=\"handler()\"",[451,487,488],{},"事件绑定",[451,490,491],{},[40,492,493],{},"(click)=\"save()\"",[433,495,496,501,508],{},[451,497,498],{},[40,499,500],{},"[(ngModel)]",[451,502,503,504,507],{},"双向（须导入 ",[40,505,506],{},"FormsModule","）",[451,509,510,511],{},"见 ",[45,512,514],{"href":513},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fforms","表单",[433,516,517,526,529],{},[451,518,519,522,523],{},[40,520,521],{},"[class.foo]"," \u002F ",[40,524,525],{},"[style.width.px]",[451,527,528],{},"类与样式",[451,530,531],{},"按表达式切换",[51,533,535],{"id":534},"内置控制流angular-17","内置控制流（Angular 17+）",[23,537,538,539,542,543,546],{},"推荐使用新语法（编译期优化，无需 ",[40,540,541],{},"CommonModule"," 中的 ",[40,544,545],{},"*ngIf"," 等结构指令即可使用控制流块）：",[55,548,552],{"className":549,"code":550,"language":551,"meta":60,"style":60},"language-html shiki shiki-themes material-theme-lighter github-light github-dark","@if (user(); as u) {\n  \u003Cp>{{ u.name }}\u003C\u002Fp>\n} @else {\n  \u003Cp>未登录\u003C\u002Fp>\n}\n\n@for (item of items(); track item.id) {\n  \u003Cli>{{ item.label }}\u003C\u002Fli>\n} @empty {\n  \u003Cli>暂无数据\u003C\u002Fli>\n}\n\n@switch (status()) {\n  @case ('ok') { \u003Cspan>成功\u003C\u002Fspan> }\n  @default { \u003Cspan>未知\u003C\u002Fspan> }\n}\n","html",[40,553,554,559,580,585,602,606,610,615,633,638,655,659,663,668,691,713],{"__ignoreMap":60},[64,555,556],{"class":66,"line":67},[64,557,558],{"class":78},"@if (user(); as u) {\n",[64,560,561,564,567,569,572,575,577],{"class":66,"line":118},[64,562,563],{"class":74},"  \u003C",[64,565,23],{"class":566},"sQzsp",[64,568,275],{"class":74},[64,570,571],{"class":78},"{{ u.name }}",[64,573,574],{"class":74},"\u003C\u002F",[64,576,23],{"class":566},[64,578,579],{"class":74},">\n",[64,581,582],{"class":66,"line":125},[64,583,584],{"class":78},"} @else {\n",[64,586,587,589,591,593,596,598,600],{"class":66,"line":141},[64,588,563],{"class":74},[64,590,23],{"class":566},[64,592,275],{"class":74},[64,594,595],{"class":78},"未登录",[64,597,574],{"class":74},[64,599,23],{"class":566},[64,601,579],{"class":74},[64,603,604],{"class":66,"line":161},[64,605,403],{"class":78},[64,607,608],{"class":66,"line":175},[64,609,122],{"emptyLinePlaceholder":121},[64,611,612],{"class":66,"line":186},[64,613,614],{"class":78},"@for (item of items(); track item.id) {\n",[64,616,617,619,622,624,627,629,631],{"class":66,"line":192},[64,618,563],{"class":74},[64,620,621],{"class":566},"li",[64,623,275],{"class":74},[64,625,626],{"class":78},"{{ item.label }}",[64,628,574],{"class":74},[64,630,621],{"class":566},[64,632,579],{"class":74},[64,634,635],{"class":66,"line":200},[64,636,637],{"class":78},"} @empty {\n",[64,639,640,642,644,646,649,651,653],{"class":66,"line":209},[64,641,563],{"class":74},[64,643,621],{"class":566},[64,645,275],{"class":74},[64,647,648],{"class":78},"暂无数据",[64,650,574],{"class":74},[64,652,621],{"class":566},[64,654,579],{"class":74},[64,656,657],{"class":66,"line":226},[64,658,403],{"class":78},[64,660,661],{"class":66,"line":233},[64,662,122],{"emptyLinePlaceholder":121},[64,664,665],{"class":66,"line":258},[64,666,667],{"class":78},"@switch (status()) {\n",[64,669,670,673,675,677,679,682,684,686,688],{"class":66,"line":283},[64,671,672],{"class":78},"  @case ('ok') { ",[64,674,268],{"class":74},[64,676,64],{"class":566},[64,678,275],{"class":74},[64,680,681],{"class":78},"成功",[64,683,574],{"class":74},[64,685,64],{"class":566},[64,687,275],{"class":74},[64,689,690],{"class":78}," }\n",[64,692,693,696,698,700,702,705,707,709,711],{"class":66,"line":288},[64,694,695],{"class":78},"  @default { ",[64,697,268],{"class":74},[64,699,64],{"class":566},[64,701,275],{"class":74},[64,703,704],{"class":78},"未知",[64,706,574],{"class":74},[64,708,64],{"class":566},[64,710,275],{"class":74},[64,712,690],{"class":78},[64,714,715],{"class":66,"line":306},[64,716,403],{"class":78},[23,718,719,722,723,49],{},[40,720,721],{},"track"," 表达式用于列表 diff，规则类似 React\u002FVue 的 ",[27,724,725],{},"稳定 key",[51,727,728],{"id":728},"指令与管道",[730,731,732,750,767],"ul",{},[621,733,734,737,738,30,740,743,744,522,747,49],{},[27,735,736],{},"结构型指令","（旧）：",[40,739,545],{},[40,741,742],{},"*ngFor"," 仍可用，新项目优先 ",[40,745,746],{},"@if",[40,748,749],{},"@for",[621,751,752,755,756,30,759,762,763,766],{},[27,753,754],{},"属性型指令","：如 ",[40,757,758],{},"NgClass",[40,760,761],{},"NgStyle","（",[40,764,765],{},"@angular\u002Fcommon","）。",[621,768,769,772,773,776],{},[27,770,771],{},"管道","：模板内转换显示，如 ",[40,774,775],{},"{{ date \\| date:'short' }}","；纯管道利于变更检测。",[51,778,779],{"id":779},"内容投影",[55,781,783],{"className":549,"code":782,"language":551,"meta":60,"style":60},"\u003C!-- 父模板 -->\n\u003Capp-card>\n  \u003Ch2 card-title>标题\u003C\u002Fh2>\n  \u003Cp>正文\u003C\u002Fp>\n\u003C\u002Fapp-card>\n",[40,784,785,790,799,820,837],{"__ignoreMap":60},[64,786,787],{"class":66,"line":67},[64,788,789],{"class":229},"\u003C!-- 父模板 -->\n",[64,791,792,794,797],{"class":66,"line":118},[64,793,268],{"class":74},[64,795,796],{"class":566},"app-card",[64,798,579],{"class":74},[64,800,801,803,805,809,811,814,816,818],{"class":66,"line":125},[64,802,563],{"class":74},[64,804,51],{"class":566},[64,806,808],{"class":807},"s9AJx"," card-title",[64,810,275],{"class":74},[64,812,813],{"class":78},"标题",[64,815,574],{"class":74},[64,817,51],{"class":566},[64,819,579],{"class":74},[64,821,822,824,826,828,831,833,835],{"class":66,"line":141},[64,823,563],{"class":74},[64,825,23],{"class":566},[64,827,275],{"class":74},[64,829,830],{"class":78},"正文",[64,832,574],{"class":74},[64,834,23],{"class":566},[64,836,579],{"class":74},[64,838,839,841,843],{"class":66,"line":161},[64,840,574],{"class":74},[64,842,796],{"class":566},[64,844,579],{"class":74},[55,846,848],{"className":549,"code":847,"language":551,"meta":60,"style":60},"\u003C!-- app-card 模板 -->\n\u003Cng-content select=\"[card-title]\" \u002F>\n\u003Cng-content \u002F>\n",[40,849,850,855,878],{"__ignoreMap":60},[64,851,852],{"class":66,"line":67},[64,853,854],{"class":229},"\u003C!-- app-card 模板 -->\n",[64,856,857,859,862,865,868,870,873,875],{"class":66,"line":118},[64,858,268],{"class":74},[64,860,861],{"class":566},"ng-content",[64,863,864],{"class":807}," select",[64,866,867],{"class":74},"=",[64,869,112],{"class":104},[64,871,872],{"class":108},"[card-title]",[64,874,112],{"class":104},[64,876,877],{"class":74}," \u002F>\n",[64,879,880,882,884],{"class":66,"line":125},[64,881,268],{"class":74},[64,883,861],{"class":566},[64,885,877],{"class":74},[51,887,889],{"id":888},"与-vue-react-对照简表","与 Vue \u002F React 对照（简表）",[427,891,892,907],{},[430,893,894],{},[433,895,896,898,901,904],{},[436,897],{},[436,899,900],{},"Angular",[436,902,903],{},"Vue 3",[436,905,906],{},"React",[446,908,909,922,945],{},[433,910,911,913,916,919],{},[451,912,33],{},[451,914,915],{},"HTML + 指令",[451,917,918],{},"SFC template",[451,920,921],{},"JSX",[433,923,924,927,935,940],{},[451,925,926],{},"输入",[451,928,929,522,932],{},[40,930,931],{},"input()",[40,933,934],{},"@Input",[451,936,937],{},[40,938,939],{},"defineProps",[451,941,942],{},[40,943,944],{},"props",[433,946,947,950,958,963],{},[451,948,949],{},"输出",[451,951,952,522,955],{},[40,953,954],{},"output()",[40,956,957],{},"@Output",[451,959,960],{},[40,961,962],{},"defineEmits",[451,964,965],{},"回调 props",[51,967,968],{"id":968},"参考文献",[23,970,971],{},"以下链接在编写时均可正常访问：",[427,973,974,984],{},[430,975,976],{},[433,977,978,981],{},[436,979,980],{},"资料",[436,982,983],{},"说明",[446,985,986,999,1011],{},[433,987,988,996],{},[451,989,990],{},[45,991,995],{"href":992,"rel":993},"https:\u002F\u002Fangular.dev\u002Fguide\u002Fcomponents",[994],"nofollow","组件概览",[451,997,998],{},"官方",[433,1000,1001,1008],{},[451,1002,1003],{},[45,1004,1007],{"href":1005,"rel":1006},"https:\u002F\u002Fangular.dev\u002Fguide\u002Ftemplates",[994],"模板语法",[451,1009,1010],{},"绑定与控制流",[433,1012,1013,1020],{},[451,1014,1015],{},[45,1016,1019],{"href":1017,"rel":1018},"https:\u002F\u002Fangular.dev\u002Fguide\u002Fcomponents\u002Finputs",[994],"组件输入输出",[451,1021,414],{},[1023,1024,1025],"style",{},"html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sQzsp, html code.shiki .sQzsp{--shiki-light:#E53935;--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s9AJx, html code.shiki .s9AJx{--shiki-light:#9C3EDA;--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":60,"searchDepth":118,"depth":118,"links":1027},[1028,1029,1030,1031,1032,1033,1034],{"id":53,"depth":118,"text":53},{"id":425,"depth":118,"text":425},{"id":534,"depth":118,"text":535},{"id":728,"depth":118,"text":728},{"id":779,"depth":118,"text":779},{"id":888,"depth":118,"text":889},{"id":968,"depth":118,"text":968},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fframe\u002FAngular\u002Fcomponents","knowledge\u002Fknowledge\u002Fbooklet\u002Fframe\u002FAngular\u002Fcomponents.md","md",{"items":1040},[1041,1045,1048,1052,1054,1058],{"path":1042,"title":1043,"description":1044,"category":10,"score":175},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fecology","生态集成","Angular 官方维护路由、HTTP、表单、动画等；UI 与状态扩展由社区与官方 Material 团队提供。涵盖官方\u002F半官方库、常用第三方库、与 Vue\u002FReact 生态对照、选型建议与常见坑。",{"path":409,"title":1046,"description":1047,"category":10,"score":175},"Signal 基础","Signals 是 Angular 16 引入的响应式原语：可读写的 signal、派生的 computed、副作用 effect。用于组件内状态与跨组件细粒度更新，涵盖 API、input signal、与变更检测的关系、最佳实践与常见坑。",{"path":1049,"title":1050,"description":1051,"category":10,"score":175},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fsignals\u002Frxjs","RxJS 互操作","Angular 内置 RxJS 处理异步流（HTTP、HttpClient、路由事件、FormControl 的 valueChanges 等）。Signal 适合同步\u002F短链路状态；长生命周期流仍常用 Observable。涵盖 async 管道、toSignal\u002FtoObservable、常用操作符、最佳实践与常见坑。",{"path":513,"title":514,"description":1053,"category":10,"score":175},"Angular 提供 响应式表单（Reactive Forms） 与 模板驱动表单（Template-driven）。复杂表单推荐 Reactive Forms（模型在 TypeScript 中，易测试）。涵盖 FormGroup\u002FFormArray、Typed Forms、自定义校验器、最佳实践与常见坑。",{"path":1055,"title":1056,"description":1057,"category":10,"score":175},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fstate","状态管理","Angular 没有强制单一状态库：服务 + DI、Signal、RxJS 即可覆盖多数场景；大型应用可选用 NgRx。涵盖选型、服务作为状态容器、跨组件共享、NgRx 与 SignalStore、常见坑。",{"path":1059,"title":1060,"description":1061,"category":10,"score":175},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fhttp","HTTP 与数据","Angular 通过 HttpClient（@angular\u002Fcommon\u002Fhttp）发起 HTTP 请求，返回 RxJS Observable。见 RxJS 互操作、依赖注入。",{"series":1063,"title":12,"items":1064,"index":125,"prev":1104,"next":1105},"booklet\u002Fframe\u002Fangular",[1065,1067,1069,1073,1074,1078,1080,1082,1084,1088,1092,1096,1098,1100],{"path":47,"title":48,"date":1066,"pinned":15},"2020-03-07",{"path":409,"title":1046,"date":1068,"pinned":15},"2026-06-12",{"path":1070,"title":1071,"date":1072,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fperformance\u002Fchange-detection","变更检测","2023-10-12",{"path":7,"title":8,"date":14,"pinned":15},{"path":1075,"title":1076,"date":1077,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fdi","依赖注入","2021-01-24",{"path":1042,"title":1043,"date":1079,"pinned":15},"2026-07-12",{"path":513,"title":514,"date":1081,"pinned":15},"2025-05-26",{"path":1059,"title":1060,"date":1083,"pinned":15},"2024-12-27",{"path":1085,"title":1086,"date":1087,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fproject","工程化","2021-09-01",{"path":1089,"title":1090,"date":1091,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Frouter","路由","2023-02-04",{"path":1093,"title":1094,"date":1095,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Fperformance\u002Fruntime","运行时优化","2022-11-01",{"path":1049,"title":1050,"date":1097,"pinned":15},"2026-04-06",{"path":1055,"title":1056,"date":1099,"pinned":15},"2025-04-29",{"path":1101,"title":1102,"date":1103,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fframe\u002Fangular\u002Ftest","测试","2021-08-25",{"path":1070,"title":1071,"date":1072,"pinned":15},{"path":1075,"title":1076,"date":1077,"pinned":15}]