网站资料如何做参考文献,深远互动 网站建设,怎么做一种网站为别人宣传,电商推广和网络推广的策略1 基础
关于Angular的基础部分#xff0c;几个核心部分和框架#xff0c;在之前都写过了。Angular1--Hello-CSDN博客
Angular的几个核心部分和框架#xff1a;
模板就是组件中的template#xff0c;对应MVC的V。
组件类就是Component类#xff0c;对应对应MVC的C。
服…1 基础
关于Angular的基础部分几个核心部分和框架在之前都写过了。Angular1--Hello-CSDN博客
Angular的几个核心部分和框架
模板就是组件中的template对应MVC的V。
组件类就是Component类对应对应MVC的C。
服务就是service类对应MVC的M。
这个理解不能说100%对但是基本成立吧。有了这个概念后面就好理解多了。 2 复杂一点的游戏
来自官网例程Playground • Angular
main.ts
import {A11yModule} from angular/cdk/a11y;
import {CommonModule} from angular/common;
import {Component, ElementRef, ViewChild, computed, signal} from angular/core;
import {MatSlideToggleChange, MatSlideToggleModule} from angular/material/slide-toggle;
import {bootstrapApplication} from angular/platform-browser;const RESULT_QUOTES [[Not quite right!,You missed the mark!,Have you seen an angle before?,Your measurements are all over the place!,Your precision needs work!,],[Not too shabby., Getting sharper, keep it up!, Not perfect, but getting better!],[Your angles are on point!,Your precision is unparalleled!,Your geometric skills are divine!,Amazing! Youre acute-y!,Wow! So precise!,],
];const CHANGING_QUOTES [[Im such a-cute-y!, Im a tiny slice of pi!, Youre doing great!],[Im wide open!, Keep going!, Wow!, Wheee!!],[Im so obtuse!, The bigger the better!, Lifes too short for right angles!, Whoa!],
];function getChangingQuote(rotateValue: number): string {let possibleQuotes CHANGING_QUOTES[1];if (rotateValue 110) {possibleQuotes CHANGING_QUOTES[0];} else if (rotateValue 230) {possibleQuotes CHANGING_QUOTES[2];}const randomQuoteIndex Math.floor(Math.random() * possibleQuotes.length);return possibleQuotes[randomQuoteIndex];
}function getResultQuote(accuracy: number) {let possibleQuotes RESULT_QUOTES[1];if (accuracy 50) {possibleQuotes RESULT_QUOTES[0];} else if (accuracy 85) {possibleQuotes RESULT_QUOTES[2];}let randomQuoteIndex Math.floor(Math.random() * possibleQuotes.length);return possibleQuotes[randomQuoteIndex];
}Component({selector: app-root,imports: [CommonModule, MatSlideToggleModule, A11yModule],styleUrl: game.css,templateUrl: game.html,
})
export class Playground {protected readonly isGuessModalOpen signal(false);protected readonly isAccessiblePanelOpen signal(false);protected readonly rotateVal signal(40);protected readonly goal signal(85);protected readonly animatedAccuracy signal(0);protected readonly gameStats signal({level: 0,totalAccuracy: 0,});protected readonly resultQuote signal();private isDragging false;private currentInteractions: {lastChangedAt: number; face: number; quote: string} {lastChangedAt: 75,face: 0,quote: Hi, Im NG the Angle!,};ViewChild(staticArrow) staticArrow!: ElementRef;protected readonly totalAccuracyPercentage computed(() {const {level, totalAccuracy} this.gameStats();if (level 0) {return 0;}return totalAccuracy / level;});protected readonly updatedInteractions computed(() {if (this.rotateVal() 75 Math.abs(this.rotateVal() - this.currentInteractions.lastChangedAt) 70 Math.random() 0.5) {this.currentInteractions {lastChangedAt: this.rotateVal(),face: Math.floor(Math.random() * 6),quote: getChangingQuote(this.rotateVal()),};}return this.currentInteractions;});constructor() {this.resetGame();}resetGame() {this.goal.set(Math.floor(Math.random() * 360));this.rotateVal.set(40);}getRotation() {return rotate(${this.rotateVal()}deg);}getIndicatorStyle() {return 0.487 * this.rotateVal() - 179.5;}getIndicatorRotation() {return rotate(${253 this.rotateVal()}deg);}mouseDown() {this.isDragging true;}stopDragging() {this.isDragging false;}mouseMove(e: MouseEvent) {const vh30 0.3 * document.documentElement.clientHeight;if (!this.isDragging) return;let pointX e.pageX - (this.staticArrow.nativeElement.offsetLeft 2.5);let pointY e.pageY - (this.staticArrow.nativeElement.offsetTop vh30);let calculatedAngle 0;if (pointX 0 pointY 0) {calculatedAngle 90 - (Math.atan2(Math.abs(pointY), pointX) * 180) / Math.PI;} else if (pointX 0 pointY 0) {calculatedAngle 90 (Math.atan2(pointY, pointX) * 180) / Math.PI;} else if (pointX 0 pointY 0) {calculatedAngle 270 - (Math.atan2(pointY, Math.abs(pointX)) * 180) / Math.PI;} else {calculatedAngle 270 (Math.atan2(Math.abs(pointY), Math.abs(pointX)) * 180) / Math.PI;}this.rotateVal.set(calculatedAngle);}adjustAngle(degreeChange: number) {this.rotateVal.update((x) x degreeChange 0 ? 360 (x degreeChange) : (x degreeChange) % 360,);}touchMove(e: Event) {let firstTouch (e as TouchEvent).touches[0];if (firstTouch) {this.mouseMove({pageX: firstTouch.pageX, pageY: firstTouch.pageY} as MouseEvent);}}guess() {this.isGuessModalOpen.set(true);const calcAcc Math.abs(100 - (Math.abs(this.goal() - this.rotateVal()) / 180) * 100);this.resultQuote.set(getResultQuote(calcAcc));this.animatedAccuracy.set(calcAcc 20 ? calcAcc - 20 : 0);this.powerUpAccuracy(calcAcc);this.gameStats.update(({level, totalAccuracy}) ({level: level 1,totalAccuracy: totalAccuracy calcAcc,}));}powerUpAccuracy(finalAcc: number) {if (this.animatedAccuracy() finalAcc) return;let difference finalAcc - this.animatedAccuracy();if (difference 20) {this.animatedAccuracy.update((x) x 10.52);setTimeout(() this.powerUpAccuracy(finalAcc), 30);} else if (difference 4) {this.animatedAccuracy.update((x) x 3.31);setTimeout(() this.powerUpAccuracy(finalAcc), 40);} else if (difference 0.5) {this.animatedAccuracy.update((x) x 0.49);setTimeout(() this.powerUpAccuracy(finalAcc), 50);} else if (difference 0.1) {this.animatedAccuracy.update((x) x 0.1);setTimeout(() this.powerUpAccuracy(finalAcc), 100);} else {this.animatedAccuracy.update((x) x 0.01);setTimeout(() this.powerUpAccuracy(finalAcc), 100);}}close() {this.isGuessModalOpen.set(false);this.resetGame();}getText() {const roundedAcc Math.floor(this.totalAccuracyPercentage() * 10) / 10;let emojiAccuracy ;for (let i 0; i 5; i) {emojiAccuracy roundedAcc 20 * (i 1) ? : ⬜️;}return encodeURI( ${emojiAccuracy} \n My angles are ${roundedAcc}% accurate on level ${this.gameStats().level}. \n\nHow Angular are you? \nhttps://angular.dev/playground,);}toggleA11yControls(event: MatSlideToggleChange) {this.isAccessiblePanelOpen.set(event.checked);}
}bootstrapApplication(Playground);game.html
div classwrapperdiv classcolh1Goal: {{ goal() }}º/h1div idquote [class.show]rotateVal() 74{{ updatedInteractions().quote }}/divdividangle(mouseup)stopDragging()(mouseleave)stopDragging()(mousemove)mouseMove($event)(touchmove)touchMove($event)(touchend)stopDragging()(touchcanceled)stopDragging()div classarrow idstatic #staticArrowdiv classcenter/divif(rotateVal() 20) {div classsvg [style.transform]getIndicatorRotation()svg xmlnshttp://www.w3.org/2000/svg viewBox0 0 75 75defslinearGradient idgradient x10% y10% x20% y2100%stop offset0% stop-colorvar(--orange-red) /stop offset50% stop-colorvar(--vivid-pink) /stop offset100% stop-colorvar(--electric-violet) //linearGradient/defspath[style.stroke-dashoffset]getIndicatorStyle()classsvg-arrowstrokeurl(#gradient)dm64.37,45.4c-3.41,11.62-14.15,20.1-26.87,20.1-15.46,0-28-12.54-28-28s12.54-28,28-28,28,12.54,28,28/polylineclasssvg-arrowstrokeurl(#gradient)points69.63 36.05 65.29 40.39 60.96 36.05//svg/div}div classfacesvg xmlnshttp://www.w3.org/2000/svg viewBox0 0 103.41 84.33 [class.show]rotateVal() 74switch(updatedInteractions().face) {case(0) {gpath classc dm65.65,55.83v11c0,7.73-6.27,14-14,14h0c-7.73,0-14-6.27-14-14v-11/line classc x151.52 y165.83 x251.65 y257.06/path classc dm19.8,44.06c7.26,7.89,18.83,13,31.85,13s24.59-5.11,31.85-13/path classb dm3,14.33c3.35-5.71,9.55-9.54,16.65-9.54,6.66,0,12.53,3.37,16,8.5/path classb dm100.3,14.33c-3.35-5.71-9.55-9.54-16.65-9.54-6.66,0-12.53,3.37-16,8.5//g}case(1) {gpath classd dm22.11,48.83c-.08.65-.14,1.3-.14,1.97,0,11.94,13.37,21.62,29.87,21.62s29.87-9.68,29.87-21.62c0-.66-.06-1.32-.14-1.97H22.11Z/circle cx19.26 cy12.56 r12.37/circle cx84.25 cy12.56 r12.37/circle classe cx14.86 cy8.94 r4.24/circle classe cx80.29 cy8.76 r4.24//g}case(2) {gcircle cx19.2 cy12.72 r12.37/circle cx84.19 cy12.72 r12.37/circle classe cx14.8 cy9.09 r4.24/circle classe cx80.22 cy8.92 r4.24/path classc dm19.45,44.33c7.26,7.89,18.83,13,31.85,13s24.59-5.11,31.85-13//g}case(3) {gpath classb dm3.11,14.33c3.35-5.71,9.55-9.54,16.65-9.54,6.66,0,12.53,3.37,16,8.5/path classb dm100.41,14.33c-3.35-5.71-9.55-9.54-16.65-9.54-6.66,0-12.53,3.37-16,8.5/path classc dm19.91,44.06c7.26,7.89,18.83,13,31.85,13s24.59-5.11,31.85-13//g}case(4) {gcircle cx19.26 cy12.5 r12.37/circle classe cx14.86 cy8.88 r4.24/path classc dm19.51,44.11c7.26,7.89,18.83,13,31.85,13s24.59-5.11,31.85-13/path classb dm100.08,14.33c-3.35-5.71-9.55-9.54-16.65-9.54-6.66,0-12.53,3.37-16,8.5//g}default {gcircle cx19.14 cy12.44 r12.37/circle cx84.13 cy12.44 r12.37/circle classe cx14.74 cy8.82 r4.24/circle classe cx80.17 cy8.64 r4.24/circle classb cx52.02 cy53.33 r14//g}}/svg/div/divdivclassgrabbable[style.transform]getRotation()(mousedown)mouseDown()(touchstart)mouseDown()div classarrow idmoving/div/div/div/divdiv classcoldiv classoverall-statsh4level: {{ gameStats().level 1 }}/h4h4accuracy: {{ totalAccuracyPercentage() 0 ? (totalAccuracyPercentage() | number : 1.1-1) % : ?? }}/h4button idguess classgradient-button (click)guess() [disabled]isGuessModalOpen()span/spanspanguess/span/button/div/divif(isGuessModalOpen()) {dialog idresult cdkTrapFocusbutton idclose (click)close()X/buttondiv classresult-statsh2goal: {{ goal() }}º/h2h2actual: {{ rotateVal() | number : 1.1-1 }}º/h2/divh2 classaccuracyspan{{ animatedAccuracy() | number : 1.1-1 }}%/spanaccurate/h2svg classpersonified xmlnshttp://www.w3.org/2000/svg viewBox0 0 119.07 114.91gpolyline classi points1.5 103.62 56.44 1.5 40.73 8.68/line classi x159.1 y118.56 x256.44 y21.5/polyline classi points1.61 103.6 117.57 102.9 103.74 92.56/line classi x1103.86 y1113.41 x2117.57 y2102.9/path classi dm12.97,84.22c6.4,4.04,10.47,11.28,10.2,19.25//gif(animatedAccuracy() 95) {gpath classi dm52.68,72.99c-.04.35-.07.71-.07,1.07,0,6.5,7.28,11.77,16.26,11.77s16.26-5.27,16.26-11.77c0-.36-.03-.72-.07-1.07h-32.37Z/circle cx51.13 cy53.25 r6.73/circle cx86.5 cy53.25 r6.73/circle classg cx48.73 cy51.28 r2.31/circle classg cx84.35 cy51.18 r2.31//g} else if (animatedAccuracy() 80) {gpath classh dm52.59,70.26c3.95,4.3,10.25,7.08,17.34,7.08s13.38-2.78,17.34-7.08/path classh dm43.44,54.08c1.82-3.11,5.2-5.19,9.06-5.19,3.62,0,6.82,1.84,8.71,4.63/path classh dm96.41,54.08c-1.82-3.11-5.2-5.19-9.06-5.19-3.62,0-6.82,1.84-8.71,4.63//g} else if (animatedAccuracy() 60) {gpath classh dm77.38,76.81v5.99c0,4.21-3.41,7.62-7.62,7.62h0c-4.21,0-7.62-3.41-7.62-7.62v-5.99/line classh x169.69 y182.25 x269.76 y277.47/path classh dm52.42,70.4c3.95,4.3,10.25,7.08,17.34,7.08s13.38-2.78,17.34-7.08/path classh dm43.28,54.21c1.82-3.11,5.2-5.19,9.06-5.19,3.62,0,6.82,1.84,8.71,4.63/path classh dm96.24,54.21c-1.82-3.11-5.2-5.19-9.06-5.19-3.62,0-6.82,1.84-8.71,4.63//g} else if (animatedAccuracy() 40) {gcircle cx51.55 cy53.15 r6.73/circle cx86.92 cy53.15 r6.73/circle classg cx49.15 cy51.17 r2.31/circle classg cx84.77 cy51.08 r2.31/line classh x161.21 y176.81 x278.15 y276.81//g} else {gcircle cx51.55 cy53.12 r6.73/circle cx86.92 cy53.12 r6.73/circle classg cx49.15 cy51.14 r2.31/circle classg cx84.77 cy51.05 r2.31/path classh dm84.01,81.41c-2.37-5.86-8.11-10-14.83-10s-12.45,4.14-14.83,10//g}/svgdiv{{ resultQuote() }}/divdiv classresult-buttonsbutton (click)close() classgradient-buttonspan/spanspanagain?/span/buttona target_blank classgradient-button [href]https://twitter.com/intent/tweet?text getText()span/spanspanshareimg srcassets/share.svg aria-hiddentrue/span/a/div/dialog}div classaccessibilityif(isAccessiblePanelOpen()) {divbutton [disabled]isGuessModalOpen() (click)adjustAngle(-25) aria-labeldecrease angle a lot--/buttonbutton [disabled]isGuessModalOpen() (click)adjustAngle(-5) aria-labeldecrease angle a little-/buttonbutton [disabled]isGuessModalOpen() (click)adjustAngle(5) aria-labelincrease angle a little/buttonbutton [disabled]isGuessModalOpen() (click)adjustAngle(25) aria-labelincrease angle a lot/button/div}mat-slide-toggle [disabled]isGuessModalOpen() idtoggle colorprimary (change)toggleA11yControls($event)Show Accessible Controls/mat-slide-toggle/div
/divgame.css
.wrapper {height: 100%;width: 100%;max-width: 1000px;margin: auto;display: flex;justify-content: flex-end;align-items: center;
}.col {width: 100%;display: flex;flex-direction: column;justify-content: space-between;align-items: center;
}.overall-stats {display: flex;flex-direction: column;align-items: center;padding: 1rem;font-size: 1.3rem;user-select: none;
}#goal {font-size: 2rem;
}#quote {margin-top: 10px;opacity: 0;transition: all 0.3s ease;
}#quote.show {opacity: 1;
}.gradient-button {text-decoration: none;color: black;margin: 8px;position: relative;cursor: pointer;font-size: 1rem;border: none;font-weight: 600;width: fit-content;height: fit-content;padding-block: 0;padding-inline: 0;
}.gradient-button span:nth-of-type(1) {position: absolute;border-radius: 0.25rem;height: 100%;width: 100%;left: 0;top: 0;background: linear-gradient(90deg, var(--orange-red) 0%, var(--vivid-pink) 50%, var(--electric-violet) 100%);
}.gradient-button span:nth-of-type(2) {position: relative;padding: 0.75rem 1rem;background: white;margin: 1px;border-radius: 0.2rem;transition: all .3s ease;opacity: 1;display: flex;align-items: center;
}.gradient-button:enabled:hover span:nth-of-type(2),
.gradient-button:enabled:focus span:nth-of-type(2) {opacity: 0.9;
}a.gradient-button:hover span:nth-of-type(2),
a.gradient-button:focus span:nth-of-type(2) {opacity: 0.9;
}.gradient-button:disabled {cursor: not-allowed;color: #969696;
}.gradient-button img {display: inline;height: 0.8rem;margin-left: 4px;
}#angle {height: 60vh;width: 60vh;display: flex;flex-direction: column;justify-content: flex-start;align-items: center;padding: 10px;margin: 10px;
}.grabbable {height: 30vh;width: 25px;position: absolute;cursor: pointer;transform-origin: bottom center;
}.arrow {height: 30vh;width: 4px;background-color: black;position: absolute;
}.arrow::before,
.arrow::after {content: ;position: absolute;top: -4px;left: -6px;height: 20px;transform: rotate(45deg);width: 4px;background-color: black;border-radius: 0px 0px 5px 5px;
}.arrow::after {left: 6px;transform: rotate(-45deg);
}#static div.center {height: 4px;width: 4px;background-color: black;position: absolute;bottom: -2px;border-radius: 100%;
}#static div.svg {height: 75px;width: 75px;position: absolute;bottom: -37.5px;left: -35.5px;transform-origin: center;transform: rotate(294deg);
}#static svg .svg-arrow {fill: none;stroke-linecap: round;stroke-miterlimit: 10;stroke-width: 3px;
}#static svg path {stroke-dasharray: 180;
}#moving {transform-origin: bottom center;left: calc(50% - 2px);
}.face svg {position: absolute;height: 13vh;width: 13vh;bottom: 2vh;left: 4vh;opacity: 0;transition: all 0.2s ease;
}.face svg.show {opacity: 1;
}.face svg .b {stroke-width: 6px;
}.face svg .b, .c {stroke-miterlimit: 10;
}.face svg .b, .c, .d {fill: none;stroke: #000;stroke-linecap: round;
}.face svg .e {fill: #fff;
}.face svg .c, .d {stroke-width: 7px;
}.face svg .d {stroke-linejoin: round;
}#result {background-color: white;border-radius: 8px;border: 1px solid #f6f6f6;box-shadow: 0 3px 14px 0 rgba(0,0,0,.2);position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 50%;display: flex;flex-direction: column;justify-content: space-around;align-items: center;padding: 2rem;z-index: 10;
}svg.personified {height: 125px;
}.personified .g {fill: #fff;
}.personified .h {stroke-miterlimit: 10;stroke-width: 4px;
}.personified .h, .personified .i {fill: none;stroke: #000;stroke-linecap: round;
}.personified .i {stroke-linejoin: round;stroke-width: 3px;
} #close {border: none;background: none;position: absolute;top: 8px;right: 8px;font-size: 19px;cursor: pointer;
}.result-stats,
.result-buttons {display: flex;width: 100%;justify-content: center;
}.result-stats * {margin: 4px 16px;
}.result-buttons {margin-top: 16px;
}.accuracy {font-weight: 700;margin: 1rem;
}.accuracy span {font-size: 4rem;margin-right: 6px;
}#copy {display: none;
}.accessibility {position: fixed;left: 10px;bottom: 10px;
}#toggle {margin-top: 8px;
}.accessibility button {width: 2rem;height: 2rem;font-size: 1rem;border: 2px solid var(--electric-violet);border-radius: 4px;cursor: pointer;margin: 0 4px;background-color: #fff;transition: all 0.3s ease;box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.3607843137);
}.accessibility button:focus:enabled, .accessibility button:hover:enabled {background-color: #e8dbf4;
}.accessibility button:disabled {cursor: not-allowed;background-color: #eee;
}media screen and (max-width: 650px) {.wrapper {flex-direction: column-reverse;align-items: center;}.overall-stats {align-items: center;margin-bottom: 16px;}#result {box-sizing: border-box;min-width: auto;height: 100%;width: 100%;padding: 20px;top: 0;left: 0;border-radius: 0;transform: none;}
}效果如下 从代码可以出代码的主体还是一个组件。
Component({selector: app-root,imports: [CommonModule, MatSlideToggleModule, A11yModule],styleUrl: game.css,templateUrl: game.html,
})
export class Playground {
...
}
这里实现没有提取出来都是放在组件里面所以挺大的。
这里的函数定义如下 protected readonly totalAccuracyPercentage computed(() {const {level, totalAccuracy} this.gameStats();if (level 0) {return 0;}return totalAccuracy / level;});
这里的computed(()是可以实时获取并响应this.gameStats()的变化。
还有一个就是
ViewChild(staticArrow) staticArrow!: ElementRef;
这个的意思就是在 Angular 组件中获取模板中标记为 #staticArrow 的 DOM 元素或子组件的引用后续可通过 staticArrow 属性安全地操作该元素或组件实例。 3 组件
组件的标准格式
Component({selector: app-user,template: Username: {{ username }},imports: [App1],
})
export class User {username youngTech;
}
一个组件基本上就对对应一个显示区域包含了定义和控制。 组件控制流
事件处理
Component({...template: button (click)greet()
})
class App {greet() {alert(Hi. Greeting!);}
}
这里用双引号做的事件绑定。 在angular的模板中双引号还有几个作用 1. 静态属性值纯字符串表示就是普通字符串不要做解析。 input typetext placeholder请输入用户名 2. 属性绑定动态值绑定表达式 button disabled{{isDisabled}}按钮/button 3. 指令输入Input Binding传递指令或组件的输入参数。 app-child [title]固定标题/app-child 4. 事件绑定Event Binding button (click)handleClick($event)点击/button 5. 特殊场景模板引用变量声明模板局部变量。 input #emailInput typeemail 4 模板
模板中可以增加控制比如if template: if (isLoggedIn) {spanYes, the server is running/span},
//in Componenttemplate: for (user of users; track user.id) {p{{ user.name }}/p},//in classusers [{id: 0, name: Sarah}, {id: 1, name: Amy}, {id: 2, name: Rachel}, {id: 3, name: Jessica}, {id: 4, name: Poornima}];
template: div [contentEditable]isEditable/div,
在模板中还可以做到延迟显示
defer {comments /
} placeholder {pFuture comments/p
} loading (minimum 2s) {pLoading comments.../p
}
效果如下 在模板中可以将图片的关键字换成ngSrc:
Dynamic Image:img [ngSrc]logoUrl [alt]logoAlt width320 height320 /
区别如下
特性ngSrc (Angular 指令)src (原生 HTML)动态绑定✅ 支持 Angular 表达式如变量、函数调用❌ 直接写死字符串无法动态绑定加载控制✅ 避免无效请求和竞争条件❌ 可能发送 404 或重复请求性能优化✅ 可结合懒加载、占位图等策略❌ 无内置优化框架集成✅ 与 Angular 变更检测无缝协作❌ 需手动处理动态更新
数据绑定 template: pUsername: {{ username }}/pp{{ username }}s favorite framework: {{ favoriteFramework }}/plabel forframeworkFavorite Framework1:input idframework typetext [(ngModel)]favoriteFramework //label,
可以看到就是(ngModel)这个。除了ngModel还有以下模板语法
类型语法 / 指令用途说明示例绑定[property]绑定 HTML 属性[src]imgUrl{{ expression }}插值表达式{{ user.name }}bind-xxx等价于 [xxx]bind-titlemsg事件(event)监听事件(click)doSomething()on-xxx等价于 (xxx)on-clicksave()双向绑定[(ngModel)]绑定输入与数据[(ngModel)]user.name条件结构*ngIf条件显示*ngIfisLoggedIn列表结构*ngFor遍历数据渲染*ngForlet item of list切换结构*ngSwitch、*ngSwitchCase类似 switch-case见下方示例样式绑定[ngClass]动态 class 切换[ngClass]{active: isActive}[ngStyle]动态 style[ngStyle]{color: colorVar}属性绑定[attr.xxx]绑定非标准属性[attr.aria-label]label类绑定[class.className]控制某个类是否启用[class.active]isActive样式绑定[style.xxx]控制某个样式值[style.backgroundColor]color内容投影ng-content插槽内容传递用于组件中嵌套插入内容模板引用变量#var在模板中获取 DOM 或组件引用input #nameInput管道expressionpipe数据格式转换自定义指令Directive创建结构/属性指令如[appHighlight]表单控件[formControl], [formGroup]响应式表单语法input [formControl]nameControl 5 路由
路由就是在angular内根据url切换到不同的组件。最小的路由大概是三个部分。
定义路由模块
app.routes.ts
import {Routes} from angular/router;
export const routes: Routes [];
在主模块中导入
app.config.ts
import {ApplicationConfig} from angular/core;
import {provideRouter} from angular/router;
import {routes} from ./app.routes;
export const appConfig: ApplicationConfig {
providers: [provideRouter(routes)],
}; 模板中使用路由
app.ts
import {Component} from angular/core;
import {RouterOutlet} from angular/router;Component({selector: app-root,template: nava href/Home1/a|a href/userUser/a/navrouter-outlet /,imports: [RouterOutlet],
})
export class App {} 6 表单
内容都在angular/forms。
响应式表单ReactiveFormsModule。这个后面还要再看看TODO template: form [formGroup]profileForm (ngSubmit)handleSubmit()input typetext formControlNamename /input typeemail formControlNameemail /button typesubmitSubmit/button/formh2Profile Form/h2pName: {{ profileForm.value.name }}/ppEmail: {{ profileForm.value.email }}/p,imports: [ReactiveFormsModule], 响应式表单的三大核心能力
能力说明示例数据驱动表单状态值、校验完全由代码控制与模板解耦通过 formGroup.get(field).value 获取值动态字段管理运行时增减字段如购物车动态添加商品使用 FormArray 动态操作字段复杂校验支持跨字段校验、异步校验如用户名实时查重自定义 ValidatorFn 或异步校验 在真实 IoT 或企业后台里设备管理、配置页面常常字段多且动态——选 Reactive Forms 几乎是“默认选项”。只有最轻量的表单才考虑模板驱动。 7 其它
7.1 注入
就是类似单例工厂类。。
Injectable({providedIn: root,
})
export class CarService {
...
}
Component({
})
export class App {carService inject(CarService);
} 7.2 HTTP Client 7.3 WebSocket