佛的眼泪 發表於 2023-6-28 18:49:00

angular入门

<p><span style="font-size: 13px">程序设计原则:</span></p>
<p><span style="font-size: 13px">1、YAGNI:You Are't Gonna Need It(不写不需要的代码)</span></p>
<p><span style="font-size: 13px">2、DRY:Don't Repeat Yourself(不要cv自己的代码)</span></p>
<p><span style="font-size: 13px">3、OCP:Open Close Principle(开闭原则:对扩展开放、对修改封闭)</span></p>
<p>4、Low Coupling, High Cohesion(高内聚低耦合)</p>
<p>5、Dimeter Law(迪米特法则,也称为"最少知识法则")一个对象/组件只负责必须的少量功能</p>
<h3>angular框架</h3>
<p><span style="font-size: 13px">MVVM框架的组成:数据绑定、指令系统、组件式编程、路由和导航、状态保持、第三方组件库。</span></p>
<p><span style="font-size: 13px">angular是由Google开发的2009年开发的MVVM框架,可用于开发web、移动、桌面应用的<span style="color: rgba(255, 102, 0, 1)">中大型</span>框架。</span></p>
<p><span style="font-size: 13px">速度与功能:Canvas 、 svg 、 视频播放 、 Web Worker 、WebSocket、 服务端渲染。</span></p>
<p><span style="font-size: 13px">Angular开发方式:脚手架的方式,不能使用script的引入方式。</span></p>
<h4>1、项目启动过程分析</h4>
<p><span style="font-size: 13px">1)、<span style="color: rgba(255, 102, 0, 1)">angular.json</span>:NG项目的配置:</span></p>
<p><span style="font-size: 13px">  index:'src/index.html'&nbsp; --&gt; 渲染dom树的入口&nbsp; &lt;app-root /&gt;</span></p>
<p><span style="font-size: 13px">  main:'src/main.ts'&nbsp; --&gt; 编译打包的入口文件</span></p>
<p><span style="font-size: 13px">2)、main.js --&gt; <span style="color: rgba(255, 102, 0, 1)">bootstrapModule</span>(AppModule)引导启动一个模块,ng中一个模块就是一个容器</span><br><span style="font-size: 13px">  model:模型,即数据,MVVM中的第一个M</span><br><span style="font-size: 13px">  module:模块,主要出现在 node.js、ES6和angular中</span></p>
<p><span style="font-size: 13px">  modal:弹框(模态对话框)</span></p>
<p><span style="font-size: 13px">3)、app.module.ts --&gt; bootatrap:</span></p>
<p><span style="font-size: 13px">4)、app.component --&gt; <span style="color: rgba(255, 102, 0, 1)">selector</span>:'app-root'&nbsp; &nbsp;templateUrl::'app.component.html'</span></p>
<p><span style="font-size: 13px">5)、app.component.html --&gt; HTML片段</span></p>
<h4>2、angular核心概念之1:模块</h4>
<p>  <span style="font-size: 13px">Module:不同于node.js或ES6中的模块,NG中的模块就是一个抽象的容器,用于对组件进行分组。</span></p>
<p><span style="font-size: 13px">  整个应用初始时有且只有一个主组件:AppModule</span></p>
<h4>3、angular核心概念之2:组件</h4>
<p><span style="font-size: 13px">  组件:是一段可以反复使用的页面片段,如页头。。。</span></p>
<p><span style="font-size: 13px">  组件 = 模板template + 脚本script + 样式style。</span></p>
<p><span style="font-size: 13px">  NG中任何一个组件都<span style="color: rgba(255, 102, 0, 1)">必须声明在具体的模块</span>中。</span></p>
<p><span style="font-size: 13px">  创建组件流程:</span></p>
<p><span style="font-size: 13px">  1)、创建组件class</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 13px">import { Component } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@angular/core</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 装饰器 Decorator,用于指定class的用途</span>
<span style="color: rgba(0, 0, 0, 1)">@Component({
selector: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">myc01</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
template: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">&lt;h2&gt;我的组件c02&lt;/h2&gt;&lt;hr&gt;</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
styleUrls: [],
})
export </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyC01Component {}</span></span></pre>
</div>
<p><span style="font-size: 13px">  2)、在某一个模块中注册组件class</span></p>
<p><span style="font-size: 13px">  3)、使用已经注册过的组件</span></p>
<p><span style="font-size: 13px">Angular提供的创建组件化的简化工具:</span></p>
<p><span style="color: rgba(255, 102, 0, 1); font-size: 13px">ng generate component 组件名&nbsp; <span style="color: rgba(0, 0, 0, 1)">or&nbsp; <span style="color: rgba(255, 102, 0, 1)">npx ng generate(g) component 组件名</span></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1); font-size: 13px">上述可简化为&nbsp; <span style="color: rgba(255, 102, 0, 1)">ng g c 组件名</span></span></p>
<p><span style="font-size: 13px">扩展:Nodejs官方安装的工具:</span></p>
<p><span style="font-size: 13px">  npm:第三方模块的维护工具</span></p>
<p><span style="font-size: 13px">  <span style="color: rgba(255, 102, 0, 1)">npx</span>:第三方可执行文件的 执行工具,Node Package Executor,npx可用于执行当前项目中node_modules/.bin目录下的可执行文件。</span></p>
<h4><span style="font-size: 13px">4、angular核心概念3:数据绑定</span></h4>
<p><span style="font-size: 13px">一、数据绑定</span></p>
<p><span style="font-size: 13px">1)、HTML绑定&nbsp; {{ NG表达式 }}</span></p>
<p><span style="font-size: 13px">  NG表达式中可以执行的代码:算数运算,比较运算,逻辑运算,三目运算,调用函数。</span></p>
<p><span style="font-size: 13px">  <span style="color: rgba(255, 102, 0, 1)">创建对象</span>和<span style="color: rgba(255, 102, 0, 1)">JSON序列化</span>不可以在NG表达式中使用。</span></p>
<p><span style="font-size: 13px">2)、属性绑定</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 形式1、直接在属性上用 {{ }}&nbsp; &nbsp; &lt;p title="{{title}"/&gt;</p>
<p>  形式2、使用 [ ] 做属性绑定&nbsp; &nbsp; &lt;p ="title" /&gt;</p>
<p><span style="font-size: 13px">3)、指令绑定</span></p>
<p>①、循环绑定: *ngFor</p>
<div class="cnblogs_code">
<pre>&lt;ul&gt;
    &lt;li *ngFor="let item of empList; index as i"&gt;{{i+1}}-{{item}}&lt;/li&gt;
&lt;/ul&gt;</pre>
</div>
<p>②、选择绑定: *ngIf</p>
<div class="cnblogs_code">
<pre>&lt;div *ngIf="isPaidUser; else elseBlock" class="vip"&gt;会员专享&lt;/div&gt;
&lt;ng-template #elseBlock&gt;&lt;span&gt;非会员&lt;/span&gt;&lt;/ng-template&gt;</pre>
</div>
<p>③、样式绑定 &nbsp; &nbsp;和&nbsp; &nbsp;</p>
<div class="cnblogs_code">
<pre>&lt;div ="myStyleObj"&gt;样式绑定&lt;/div&gt;</pre>
</div>
<div class="cnblogs_code">
<pre>&lt;button ="myClassObj" (click)="loadMore()"&gt;加载更多&lt;/button&gt;
// ts
myClassObj =<span> {
    btn: true<span>,
    'btn-success': true<span>,
};</span></span></span></pre>
</div>
<p>④、特殊的选择绑定 </p>
<div class="cnblogs_code">
<pre>&lt;div ="userLevel"&gt;
    &lt;p *ngSwitchCase="'normal'"&gt;欢迎您,普通客户&lt;/p&gt;
    &lt;div *ngSwitchCase="'vip'"&gt;欢迎贵宾归来&lt;/div&gt;
    &lt;h3 *ngSwitchCase="'blackgold'"&gt;黑金您好,可以为您服务吗?&lt;/h3&gt;
    &lt;span *ngSwitchDefault&gt;您尚未登录&lt;/span&gt;
&lt;/div&gt;</pre>
</div>
<p>⑤、自定义指令:</p>
<p>创建指令的命令:<span style="color: rgba(255, 102, 0, 1)">ng g directive 指令名</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">自定义指令都是作为元素属性来使用的,selector应该是:[指令名]</span></p>
<p>Angular中的指令分为3类:</p>
<p>  1)、组件指令:NG中Component继承自Directive。</p>
<p>  2)、结构型指令:<span style="color: rgba(255, 102, 0, 1)">会影响DOM树的结构</span>,必须以&nbsp;<span style="color: rgba(255, 102, 0, 1)">*&nbsp;</span>开头。</p>
<p>  3)、属性型指令:不会影响DOM树的结构,只会影响元素的外观或行为,必须以&nbsp;<span style="color: rgba(255, 102, 0, 1)">[ ]&nbsp;</span>括起来。</p>
<p><span style="font-size: 13px">④、事件绑定</span></p>
<div class="cnblogs_code">
<pre>&lt;button (click)=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">printUname()</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;输出用户名&lt;/button&gt;</pre>
</div>
<p><span style="font-size: 13px">⑤、双向数据绑定&nbsp; &nbsp; <span style="color: rgba(255, 102, 0, 1)">[(ngModel)]</span></span></p>
<p>&nbsp;  方向1、Model =&gt; View:模型变则视图变,用<span style="color: rgba(255, 204, 0, 1)"> [ ]</span> 表示</p>
<p>  方向2、View =&gt; Model:视图(表单元素)变则模型变,用<span style="color: rgba(255, 204, 0, 1)"> ( )</span> 绑定</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 首先在app.module.ts中引入模块</span>
import { FormsModule } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@angular/forms</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> BrowserModule:浏览器模块,其中导出了CommonModule模块,所以 ngIf 等可以直接使用,不包含ngModel。FormsModule包含了ngModel</span>
imports: ,</pre>
</div>
<div>
<div class="cnblogs_code">
<pre>&lt;input <span style="color: rgba(255, 102, 0, 1)">[(ngModel)]</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">uname</span><span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(255, 102, 0, 1)">(ngModelChange)</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">doUnameChange()</span><span style="color: rgba(128, 0, 0, 1)">"</span> placeholder=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请输入用户名</span><span style="color: rgba(128, 0, 0, 1)">"</span> &gt;</pre>
</div>
</div>
<div><span style="color: rgba(255, 102, 0, 1)">ngModelChange</span>:监听模型数据的改变</div>
<h4>5、angular核心概念4:过滤器/管道</h4>
<p>1)、Filter:用于在View中呈现数据时显示为另外一种格式,过滤器的本质是一个函数,接收原始数据转换为新的格式输出:function(oldVal){return newVal}</p>
<p>使用过滤器:{{<span style="color: rgba(255, 102, 0, 1)"> e.sex| 过滤器名 </span>}}</p>
<p>angular2.x中,过滤器更名为 "<span style="color: rgba(255, 102, 0, 1)">管道(Pipe)</span>"</p>
<p>自定义管道的流程:</p>
<p> ①、创建管道class,实现转换功能</p>
<div class="cnblogs_code">
<pre>import { Pipe } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@angular/core</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
@Pipe({
name: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">sex</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
})
export </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SexPipe {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 管道中执行过滤任务的是一个固定的函数</span>
<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 102, 0, 1)">transform</span>(val: number,lang='zh') {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (val === <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">男</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
    } </span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (val === <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">女</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
    } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">未知</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
    }
}
}</span></pre>
</div>
<p> ②、在模块中注册管道</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> app.module.ts中注册声明</span>
import { SexPipe } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./sex.pipe</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
declarations:</span></pre>
</div>
<p> ③、使用管道(可以使用 : 进行传参)</p>
<div class="cnblogs_code">
<pre>&lt;p&gt;性别过滤器:{{ <span style="color: rgba(255, 102, 0, 1)">0 | sex:'en'</span> }}&lt;/p&gt;</pre>
</div>
<p>创建管道的简便方式:<span style="color: rgba(255, 204, 0, 1)">ng g pipe 管道名</span></p>
<p>2)、预定义管道</p>
<p>angular中提供了几个预定义管道:lowercase、uppercase、titlecase、slice(切割字符串,其他显示为...)、json(object序列化为json字符串)、number(number:'4.2-3' 表示保留4位整数,保留至少2位小数,最多保留3位小数)、currency:'¥'(表示金额前加¥符号)、date(date:'yyyy-MM-dd HH:mm:ss')</p>
<p>3)、创建对象</p>
<p>&nbsp; ①、手工创建式&nbsp;-------&nbsp; 自己创建&nbsp; new</p>
<p>&nbsp; ②、依赖注入式 -------&nbsp; 无需手工new,只需要声明依赖</p>
<h4>6、Angular核心概念5:服务和依赖注入</h4>
<p>1、Service:angular认为组件是与用户交互的一种对象,其中内容都应该与用户操作有关的;而与用户操作无关的内容都应该剥离出去,放在“服务对象”中,<strong>为组件服务</strong>。例如:日志记录、计时统计、数据服务器的访问等。</p>
<p>提供者就会创建被依赖的对象,注入给服务需要者。</p>
<p><img src="https://img2023.cnblogs.com/blog/2338509/202306/2338509-20230617185021064-1253367456.png"></p>
<p>&nbsp;第一步:构建服务对象并指定服务提供者。</p>
<div class="cnblogs_code">
<pre>import { Injectable } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@angular/core</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 所有的服务对象都是"可被注入的"</span>
<span style="color: rgba(0, 0, 0, 1)">@Injectable({
providedIn: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">root</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">指定当前服务对象在"根模块"中提供--AppModule</span>
<span style="color: rgba(0, 0, 0, 1)">})
export </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> LogService {
doLog(action: </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">) {
    let uname </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">admin</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
    let time </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Date().getTime();
    console.log(`管理员:${uname} 时间:${time} 动作:${action}`);
}
}</span></pre>
</div>
<p>第二步:在组件中声明依赖,服务提供者就会自动注入进来,组件直接使用服务对象即可。</p>
<div class="cnblogs_code">
<pre>import { Component } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@angular/core</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
import { LogService } </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">../log.service</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
@Component({
selector: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">app-myc07</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
templateUrl: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./myc07.component.html</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
styleUrls: [</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./myc07.component.css</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">],
})
export </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Myc07Component {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 依赖注入:组件--服务使用者,必须声明依赖</span>
<span style="color: rgba(0, 0, 0, 1)">log;
constructor(log: LogService) {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.log =<span style="color: rgba(0, 0, 0, 1)"> log;
}
doAdd() {
    let action </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">添加新的商品:xxx</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.log.doLog(action);
}
}</span></pre>
</div>
<p>2、使用Angular官方提供的服务对象——HttpClient Service</p>
<p>HttpClient:服务对象用于向指定URL发送异步请求,使用步骤:</p>
<p>①、在主模块app.module.ts中导入HttpClient服务所在的模块</p>
<div class="cnblogs_code">
<pre>import { HttpClientModule } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@angular/common/http</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
imports:</span></pre>
</div>
<p>②、在需要使用异步请求的组件中声明依赖于HttpClient服务对象,就可以使用该对象发起异步请求了。</p>
<div class="cnblogs_code">
<pre>constructor(<span style="color: rgba(0, 0, 255, 1)">private</span> http: HttpClient) {}<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">依赖注入
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 观察者模式</span>
<span style="color: rgba(0, 0, 255, 1)">this</span>.http.<span style="color: rgba(0, 0, 255, 1)">get</span>(url).<span style="color: rgba(0, 0, 0, 1)">subscribe</span>((res) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">得到了订阅的异步响应消息</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, res);
});</span></pre>
</div>
<p>面试题:前端有哪些异步请求工具?</p>
<p>①、原生XHR</p>
<p>const xhr = new XMLHttpRequest()&nbsp; &nbsp;浏览器支持的原生技术,基于回调方式处理响应,有回调地狱的问题。</p>
<p>②、jQuery.ajax()</p>
<p> 本质还是XHR,进一步封装而已,使用上比原生要简单,基于回调方式处理响应。</p>
<p>③、Axios</p>
<p>&nbsp; &nbsp; 本质还是XHR,比原生要简单,基于“Promise”处理响应,请求可以排队也可以并发。</p>
<p>④、Angular HttpClient</p>
<p> 底层也是XHR,比原生简单,基于“<span style="color: rgba(255, 102, 0, 1)">观察者模式</span>”处理响应,请求可以排队、并发、撤销。</p>
<p>⑤、Fetch</p>
<p> 本质不再是XHR,是W3C提出的新技术,有望取代XHR,目前部分浏览器不支持。天然基于Promise。</p>
<p>3、高阶话题:服务对象的作用范围</p>
<p> &nbsp; 声明服务提供者的方式:</p>
<p>  ①、在根模块中提供服务对象——在整个应用中服务是单例。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Injectable({
providedIn: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">root</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
})</span></pre>
</div>
<p>  ②、在组件中提供服务对象——在每一个组件实例中,服务都有一个实例。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Component({<br>  ...<br></span><span style="color: rgba(0, 0, 0, 1)">providers:
})</span></pre>
</div>
<p>注意:项目中只要服务对象中有属性,只能用方式②,否则推荐使用方式①。</p>
<p>&nbsp;</p>
<h4>扩展TypeScript</h4>
<p>1、TS对属性和方法的访问定义了3种访问修饰符:</p>
<p>private:私有的,私有成员只能在本类内部使用。</p>
<p>protected:受保护的,只能在本类内部和子类的内部使用,其他地方不允许。</p>
<p>public:公共的,公共成员可以在本类内部和外部使用。</p>
<p>提示:一般情况下,class内属性不应该让外界随意访问,通常设置为private;方法一般运行调用,通常设置为public。&nbsp;</p>
<p>下面2种写法作用相同:</p>
<p><img src="https://img2023.cnblogs.com/blog/2338509/202306/2338509-20230618104140755-1429049036.png"></p>
<p>&nbsp;2、类和接口,class和interface</p>
<p>interface:特殊的类,要求某个class必须具备XX方法,例如管道类必须提供transform方法。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 要求小汽车必须提供start和stop方法
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> Runnable{
start:Function,
stop:Function
}
export </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Car implements Runnable{
start(){}
stop(){}
}</span></pre>
</div>
<h4>7、生命周期</h4>
<p>生命周期钩子函数调用的顺序:</p>
<p>1)、constructor:组件对象被创建时</p>
<p>2)、ngOnChanges():组件绑定的属性值发生改变</p>
<p>3)、<span style="color: rgba(255, 102, 0, 1)">ngOnInit</span>():初始化指令/组件完毕——类似于Vue中的mounted</p>
<p>4)、ngDoCheck():组件检测到了系统对自己的影响</p>
<p>5)、ngAfterContentInit():组件内容初始化完成</p>
<p>6)、ngAfterContentChecked():组件的内容发生变化需要检查</p>
<p>7)、ngAfterViewInit():组件的视图初始化完成</p>
<p>8)、ngAfterViewChecked():组件的视图发生变化需要检查</p>
<p>9)、<span style="color: rgba(255, 102, 0, 1)">ngOnDestroy</span>():组件即将被销毁(从DOM树上卸载),适合执行一些资源释放性语句。</p>
<h4>8、组件间的数据通讯</h4>
<p>1、父子间的组件传递:vue和angular中的父子间消息传递原理一样,都可以使用口诀:'Props Down Events Up'</p>
<p><img src="https://img2023.cnblogs.com/blog/2338509/202306/2338509-20230618171307096-690868056.png"></p>
<p>&nbsp;</p>
<p>2、子传父:子通过触发特定的事件,把数据传递给父组件,父组件提供事件处理的方法</p>
<p><img src="https://img2023.cnblogs.com/blog/2338509/202306/2338509-20230618171213865-789625064.png"></p>
<p>父子组件传值的简便方式:父亲直接使用子组件的引用</p>
<p><img src="https://img2023.cnblogs.com/blog/2338509/202306/2338509-20230618175819751-1441047594.png"></p>
<p>&nbsp;提示:ViewChild装饰器用于将子组件识别符与某个属性关联起来,第一个参数必须是已经存在的子组件识别符(带#),第二个参数是static指定组件是否为“静态组件”——不会时有时无的组件。</p>
<p>注意:通过ViewChild方式父组件可以获得子组件中的任意数据——一定程度上违反了“最少知识法则”。</p>
<div>
<div><span style="color: rgba(255, 102, 0, 1)"><code>@ViewChild</code></span>的作用是声明对子组件元素的<strong>实例引用</strong>,意思是通过注入的方式将<span style="color: rgba(255, 102, 0, 1)">子组件注入</span>到<code>@ViewChild</code>容器中,你可以想象成依赖注入的方式注入。</div>
<div>只不过<code>@ViewChild</code>不能在构造器<code>constructor</code>中注入,<strong>因为<code>@ViewChild()</code>会在<code>ngAfterViewInit()</code>回调函数之前执行(</strong>可以在<code>ngAfterViewInit<span style="font-family: &quot;Microsoft YaHei&quot;">生命周期钩子中获取到改子组件的实例</span></code><strong>)</strong></div>
<div>&nbsp;</div>
</div>
<h4>9、路由和导航</h4>
<p>多页面应用:一个项目中有多个完整的HTML文件,使用超链接跳转——销毁一颗DOM树,同步请求另一颗,得到之后再重建新的DOM树;不足:DOM树会重复创建,间隔中客户端一片空白。</p>
<p>单页面应用:整个项目中有且只有一个“完整的”HTML文件,其他页面都只是DIV片段。整个项目中客户端只需要下载一个HTML页面,创建一个完整的DOM树,页面跳转都只是一个div替换另一个div而已——能够实现过场动画。不利于SEO访问优化。</p>
<p>1)、angular定义路由步骤:</p>
<p><img src="https://img2023.cnblogs.com/blog/2338509/202306/2338509-20230618190528567-1705915135.png"></p>
<p>&nbsp;注意:</p>
<p>  ①、路由词典中的路由地址不能以 / 开头或结尾,中间可以。</p>
<p>  ②、路由中可以指定一个默认首页地址: { path:' ' }。</p>
<p>  ③、路由词典中每个路由要嘛指定component,要嘛指定redirectTo,同时需要指定路由匹配方式pathMatch。</p>
<p>  ④、路由 ** 匹配所有地址。该地址只能用于整个路由词典的最后一个。</p>
<p>2)、路由跳转/导航</p>
<p>  路由跳转的方式:</p>
<p>  方式1、使用模板方法</p>
<div class="cnblogs_code">
<pre>&lt;!-- 传统的链接可以跳转,但是属于DOM树完全重建 --&gt;
&lt;!-- &lt;a href=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ucenter</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;&lt;/a&gt; --&gt;
&lt;!-- 可以用于任何标签上,跳转地址应该以 / 开头 --&gt;
&lt;a routerLink=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/ucenter</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;进入用户中心&lt;/a&gt;
&lt;button routerLink=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">/ucenter</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;进入用户中心&lt;/button&gt;</pre>
</div>
<p>  方式2、使用脚本方法</p>
<p>  Router类是RouterModule提供的一个服务类,声明依赖即可使用。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 服务注入</span>
import { Router } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">@angular/router</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
constructor(</span><span style="color: rgba(0, 0, 255, 1)">private</span> router: Router) {}</pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">this</span>.router.navigateByUrl(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">/url</span><span style="color: rgba(128, 0, 0, 1)">'</span>);</pre>
</div>
<p>3)、路由参数的获取</p>
<div class="cnblogs_code">
<pre> constructor(<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> route: ActivatedRoute) {}
ngOnInit() {
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.route.<span style="color: rgba(0, 0, 255, 1)">params</span>.subscribe((data) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">得到了订阅的路由参数:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, data);
    });
}</span></pre>
</div>
<p>4)、路由嵌套</p>
<p>5)、路由守卫</p>
<p>  某些路由地址只能在特定条件下才能访问。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; ng g guard xxx</p>
<p>  步骤:</p>
<p>  ①、创建路由守卫class</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">@Injectable({
    providedIn: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">root</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
})
export </span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> LoginGuard{
    canActivate(){
         </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">允许激活      </span>
<span style="color: rgba(0, 0, 0, 1)">    }
}</span></pre>
</div>
<p>  ②、在路由词典中使用守卫</p>
<div class="cnblogs_code">
<pre>path: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ucenter</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
component: UserCenterComponent,
canActivate: , </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">导航守卫</span></pre>
</div>
<h3>&nbsp;</h3>
<h3>&nbsp;angular移动开发</h3>
<p>创建移动APP可用的技术:</p>
<p><img src="https://img2023.cnblogs.com/blog/2338509/202306/2338509-20230619122951236-152195934.png"></p>
<p>&nbsp;关于三大框架的组件/资源库:</p>
<p>github上搜索 awesome vue、awesome&nbsp; angular、awesome react</p>
<p>UI组件库——ionic</p>
<h3>Rxjs解决异步</h3>
<p>1、回调函数解决异步</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">function getPromiseData(cb:Function){
setTimeout(()</span>=&gt;<span style="color: rgba(0, 0, 0, 1)">{
    let userName </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
    cb(userName)
},</span><span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">)
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 使用</span>
getPromiseData((data:<span style="color: rgba(0, 0, 255, 1)">string</span>)=&gt;<span style="color: rgba(0, 0, 0, 1)">{console.log(data);
})</span></pre>
</div>
<p>2、promise</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">function getPromiseData(){
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Promise((resplve,reject)=&gt;<span style="color: rgba(0, 0, 0, 1)">{
    setTimeout(()</span>=&gt;<span style="color: rgba(0, 0, 0, 1)">{
      let userName </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
      resplve(userName)
    },</span><span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">)
})
}

getPromiseData().then(res</span>=&gt;console.log(res))</pre>
</div>
<p>3、rxjs获取异步方法:比Promise要强大,可以中途撤销,可以发射多个值,提供了多种函数工具等。</p>
<div class="cnblogs_code">
<pre>import {Observable} <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">rxjs</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
function getRxjsData(){
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Observable((observe)=&gt;<span style="color: rgba(0, 0, 0, 1)">{
    setTimeout(()</span>=&gt;<span style="color: rgba(0, 0, 0, 1)">{
      let userName </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
      observe.next(userName)
    },3</span><span style="color: rgba(128, 0, 128, 1)">000</span><span style="color: rgba(0, 0, 0, 1)">)
})
}

getRxjsData().subscribe(data</span>=&gt;<span style="color: rgba(0, 0, 0, 1)">{
console.log(data);
})</span></pre>
</div>
<p>1)、unsubscribe</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> stream =<span style="color: rgba(0, 0, 0, 1)"> getRxjsData()
</span><span style="color: rgba(0, 0, 255, 1)">const</span> d = stream.subscribe(data=&gt;<span style="color: rgba(0, 0, 0, 1)">{
console.log(data);
})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取消订阅</span>
setTimeout(()=&gt;<span style="color: rgba(0, 0, 0, 1)">{
d.unsubscribe()
},</span><span style="color: rgba(128, 0, 128, 1)">1000</span>)</pre>
</div>
<p>2)、多次执行</p>
<p>  以下代码promise其实只会执行1次</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">function getPromiseIntervalData(){
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Promise((resolve)=&gt;<span style="color: rgba(0, 0, 0, 1)">{
    setInterval(()</span>=&gt;<span style="color: rgba(0, 0, 0, 1)">{
      let userName </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
      resolve(userName)
    },</span><span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">)
})
}</span></pre>
</div>
<p>  使用rxjs:会源源不断的执行</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">function getRxjsIntervalData(){
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Observable((observe)=&gt;<span style="color: rgba(0, 0, 0, 1)">{
    setInterval(()</span>=&gt;<span style="color: rgba(0, 0, 0, 1)">{
      let userName </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">张三</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
      observe.next(userName)
    },</span><span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">)
})
}</span></pre>
</div>
<p>3)、rxjs提供的工具函数map、filter</p>
<div class="cnblogs_code">
<pre>import { filter, map } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">rxjs/operators</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
function getRxjsData() {
let count </span>= <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Observable((observe) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    setInterval(() </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      count</span>++<span style="color: rgba(0, 0, 0, 1)">;
      observe.next(count);
    }, </span><span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">);
});
}

</span><span style="color: rgba(0, 0, 255, 1)">const</span> stream =<span style="color: rgba(0, 0, 0, 1)"> getRxjsData();
stream
.pipe(
    filter((val) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (val % <span style="color: rgba(128, 0, 128, 1)">2</span> === <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
    })
)
.subscribe((data) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    console.log(data);
});</span></pre>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/nielifang/p/17485966.html
頁: [1]
查看完整版本: angular入门