一、前言
最近公司分配了一些前端任务,公司内部用的是angular的框架,所以这里做一些总结;
二、安装环境
1.安装nodejs和npm(最好是10.x版本以上的稳定版)
2.设置npm的地址为淘宝地址,方式为:
npm config set registry https://registry.npm.taobao.org
然后可以通过npm config get registry
查看是否设置成功【默认是https://registry.npmjs.org】
3.通过命令安装最新版angular/cli
sudo npm install -g @angular/cli
4.注意安装好后使用ng命令会提示找不到,这个时候可以根据上面安装好后的提示,知道ng命令在/usr/local/node_v12/bin/ng【不同版本或不同系统可能不一样,这个要根据自己安装好后的实际提示来弄】
然后可以通过sudo ln -s /usr/local/node_v12/bin/ng /usr/local/bin/ng来添加ng命令;
三、根据ng命令创建一个项目
ng new my-app会创建一个my-app的项目目录(创建过程会提示是否需要路由及选择用CSS还是LESS等,可以先从最简单的弄起)
第二张图片来自:https://blog.csdn.net/qq_38911839/article/details/97792183【其实也是来自b站的教程】
我这边生成了这些文件;
可以通过ng serve来启动(可以加上--open参数来自动打开浏览器访问主页面),还可以用npm start【但加--open无效】
通过ng build来生成dist文件;
四.和Vue的对比
这里着重看一下angular的组件定义方式,主要看app里的app.component.ts这个文件,这个其实就类似Vue里的Xx.vue,它内部的代码是这样的:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'my-app';
}
这个其实和vue十分的像,vue里组件由三部分组成,template【html,就是templateUrl】,script【就是本文件】,style【css,就是styleUrls】,而这里的selector其实就是vue里导入components时对组件的命名,如<v-sidebar>,这里就是<app-root>;
vue的组件的逻辑写在export default里,而angular则也是写在export里,不过是export class 。。,两者真的这部分内容十分的像;vue里这三部分是可以集中在一个文件里,而angular则是默认分开;(还有一点angular定义组件需要import {Component} from ...,vue可以直接写,然后由外部导入;
angular里多了个module模块的概念,其实可以先不用太管它,它类似vue里的声明引用组件的一部分,即angular里将main.js拆成了module和main.ts【可以先大致这么理解】,在module里声明要用到哪些组件;
angular里事件用()包括(内置事件和自定义事件都是),属性用[]包括,而双向数据绑定是[()]包括(因为它其实就是通过绑定属性和通过事件来实现的);
然后就是有一点很重要,事件绑定的方法必须要有()【否则不会调用对应的方法,尽管js里方法和属性不能同名】,比如(click)="test()",但是每个事件它都是会产生一个事件对象的,如果我们不写出来则不会传递(哪怕test()其实是定义为test(e)),比如(click)="test($event)"那么点击时产生的事件参数就会传递给test方法,
如果只是写(click)="test()"则点击时也会调用test方法,但是产生的事件参数是不会传递给test的,所以e参数在test里是undefined(vue里需要测试一下,貌似2里这部分设计的不好【至少方法不用写()我觉得不好,只写个test】,测试一下3是什么情况)
五.初学者需要了解的文件
1.angular.json,类似vue里的vue.config.js,用于配置一些命令(如ng serve),各类目录(静态资源目录,编译输出目录等);
2.browserlist文件是配置生成的dist文件是否需要兼容IE9这些老浏览器的配置;
3.package.json则是项目依赖(类似pom.xml)
4.tsconfig.json是用来配置typescript编译成js时的一些配置(如编译成ES5还是ES6甚至更高版本)
根目录下目前就这些文件比较重要需要了解一下,其他的可以暂时不管
src下的文件里有:
5.index.html是整个前端应用的主页面(里面一般有app-root标签),大多数情况下可以不用管(作用可以结合vue的index.html来思考)
6.main.ts应用逻辑的编译入口【目前也可以不用管】
7.polyfills.ts文件是 兼容文件,它会在angular运行之前运行,用于写一些兼容代码适配不同环境,比如添加global对象【此文件名是填充物的意思,用于填平路使得一致】
8.styles.css则是(如果创建项目时选的是scss之类的则是styles.scss)全局CSS配置,用于写一些基本的css配置,如字体,字体大小,margin之类的;
app目录下的重要文件有:
9.app.module.ts,一般而言一个程序至少需要两个module(app和routing,当然还包括系统自带的browser),它其实可以看成是本来在main.ts里做的工作拆到module里做了一部分,然后main.ts里再引用module;
10.三个component文件(除去spec的这个,这个貌似是测试文件),这三个文件和vue里的功能大致相同【创建组件记得用ng g components components/header,然后就会在app下的components目录下创建header目录,里面会自动产生这四个文件【没有module】
还有几个文件有点特殊,比如.npmrc里面保存的是npm的仓库地址之类的;
六.主要的命令
ng serve运行项目【注意这个支持热更新】【可以加参数--open会自动打开浏览器访问主页面,如果不加那么npm start也可以运行】
ng build编译生成项目;【可以加--prod来表示按prod的方式来编译项目】
ng g component【还可以是directive,pipe,service,class,guard,interface,enum,module等】 components/component-name【g是generate的意思,g可以换成generate】
好像component可以简写成c?即ng g c components/component-name【--spec=false表示不添加.spec.ts测试文件】
ng new app-name创建应用(可以通过--style=less来实现创建过程中不提示选择什么css预处理器)(加上--routing则表示需要路由)(加上--skip-install可以跳过创建项目后自动install依赖的步骤)
创建库项目:ng generate library module-library --prefix=ma
(--prefix是指库项目里的组件前缀【比如项目默认就是app前缀】,一般是和库项目名有关)【创建的库项目也会在项目的angular.json里有配置,里面包括了prefix等配置】
此时在库项目里(lib目录)创建的组件默认就是ma开头,比如ma-module-library这样的标签(如果想改前缀直接在项目根目录的angular.json里的projects找到对应的项目改它的prefix属性值即可;
还有很多其他命令,可以用ng help来查看;【package.json里也有相关配置】(generate可以创建服务Service,普通类,指令,管道,路由等等,不要自己手动去写)
注意,创建项目组件和创建项目库组件有一些区别,创建项目组件只需要在项目根目录执行命令即可(当然也可以进入项目的src/app目录下执行命令),而创建库组件必须要进入到库目录(如projects/furion)的src/lib目录下执行才有效;
项目内或库项目内的tslint.json可以配置检测组件的selector是否符合标准,比如:
{ "注释1": "表示这个配置继承最外层的配置" "extends": "../../tslint.json", "rules": { "component-selector": [ true, "element", "my-prefix", "kebab-case" ] } }
这里的component-selector表示对组件的selector属性的检测配置,true表示开启,element表示是?,my-prefix就是必须以这个为前缀,kebab-case就是v-m的格式,不能是vM或者v_m
angular里的environment.ts是默认的环境对象,要用到环境对象也是通过import {environment} from '../../environments/environment'来实现,这里注意,如果是用ng serve --local则添加environment.local.ts的内容【注意,这里和SpringBoot不一样,SpringBoot会先添加application.properties里的内容,然后才添加对应环境的内容,存在重复则以特定环境为准】,这样通过environment.prop1来访问的属性就是local这个环境变量里的prop1;注意ng serve则默认用的环境属性是environment.ts文件里配置的;
注意环境变量配置文件里有个属性是production: true表示这个文件是生产环境的【应该会被angular做一些优化】
七.常用的类或注解
1.@Injectable()注解来自@augular/core里;被这个注解注解的类,那么其他类的构造方法里如果有这个类的参数(比如XxService,但是注意这个参数必须有private,public之类的关键字修饰才会被ts认为是属性,否则它只是普通的形参),那么会自动创建这个类作为参数传递给它(比如Component的构造方法);
angular内置的一些实用类都是默认可注入的,比如HttpClient;
八.一些概念
angular的XxService其实和SpringBoot的差不多,是可要可不要的,它其实就是普通的一个方法集合类(一系列相关业务,特定领域方法的集合);
可以参考公司的ModuleService,就提供了一个加载menu.json的方法,其他啥也没有,然后布局组件(navigation组件)在构造方法里自动注入这个类对象(ModuleService有@Injectable()),之后也是用这个Service的方法来加载menu.json,但是其实完全可以写一个common类来加载或者直接写在布局组件里去加载也行,不是说必须要有这么一层;
在module里(@NgModule),declarations数组里添加的是组件;在imports里添加的是其他Module(一般是库Module和基本的BrowserModule和AppRoutingModule,这个模块的概念其实就可以理解为子项目的意思【比如Python里一个文件就是一个模块,里面包含了一系列方法和类等】),providers里添加的是各类Service等;bootstrap里貌似只有项目的Module里会添加元素,且目前只看到了AppComponent这一个元素;
注意,一个module里的组件要想被其他地方引用,必须先在该module的exports里导出组件,然后其他地方再导入这个module就可以使用库项目里的组件了;
九.一些特殊属性
1.innerHTML,即[innerHTML] = "kkk",那么kkk的字符串会被渲染为一个html;
2.routerLink是导航栏点击后的路由uri;
十.一些特殊标签
ng-content其实就类似Vue里的slot,即在子组件里定义一个<ng-content ...>“占位”标签,然后在父组件里决定该子组件内部的<ng-content>标签挂载什么标签或者组件;
ng-template可以实现类似ngElse的功能,比如:
<div class="lessons-list" *ngIf="condition else elseTemplate"> 判断条件为真 </div> <ng-template #elseTemplate> <div>判断条件为假</div> </ng-template>
ng-container的作用和ng-template差不多,不过ng-container有一个很大的特点是它本身不会产生html标签【ng-template也一样不会,ng-template基本上就是为了定义指令而存在以及else块,如果直接在ng-template内的元素是不会显示的,而ng-container会显示】,所以<ng-container><p>ss</p></ng-container>最终就是<p>ss</p>,它有个重要的功能是对*ngFor进行过滤(结合*ngIf),由于*ngFor和*ngIf不能同时作用域一个元素上,所以要循环创建标签,但是又要过滤还不引入其他html标签就要用到ng-container,如:
<ul> <ng-container *ngFor="let item of list;let index=index"> <li *ngIf="index%2 === 0"> {{"index is " + index + " value is " + item}} </li> </ng-container> </ul>
十一、语法方面:
1.angular里(其实vue也一样)凡是可能被外部访问的属性/字段都应该是public的,之前自己错误的认为component文件里的属性如果只是给本component用和对应的HTML用就可以是private,现在看来不是(至少银行的流水线编译不通过,虽然本地编译OK),因此以后是除非component的属性只是在component里面用到,对应HTML都不会用到,那么这种可以是private,比如各种service(httpClient之类的不会出现在HTML,也不会被外部用的东西),会被HTML用到的就应该是public。
2.angular也可以实现vue的计算属性,可以通过在组建构造方法里添加这样的代码实现:
const _this = this; // proxy就是js Proxy对象 this.proxy = new Proxy(_this, { set(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver); if (result) { switch(key) { case "propName1": case "propName2": _this.computedPropNotFunc = _this.computePropFunc(); }
} return result; }});
// 然后html里绑定属性就是用proxy.propName1这种形式,而代码里设置值则是用this.proxy.propName1 = 8;这样设置值。