开始学习 Angular 。下面是对于官方教程之中自认为难点或者重点的梳理。 在文章的最后是在项目之中所遇到的问题和解决方法,持续更新~
快速上手
- Components are the fundamental building blocks of Angular applications.所以在 Angular 之中,承担功能的基本单位就是 Components。
- 使用 Angular CLI 创建好项目之后,会默认创建一个 Angular 组件,是
app-root
, 也叫做根组件。
应用的“外壳”
这一章主要是讲如何修改页面的显示内容和样式。
在 src/app
这个文件夹下面有实现 AppComponent 的三个文件:
- app.component.ts : 组件的类代码,使用 TypeScript 写成
- app.component.html : 组件的模板,是使用 HTML 写成
- app.component.css : 组件的私有 CSS 样式
双花括号语法
`` 在 Angular 之中是插值绑定语法,其意为将组件的 title 属性的值绑定在 HTML 的某些标记之中。如下面的代码,就是把值绑定到 <h1> 标签之中
<h1></h1>
CSS
在这章教程的CSS之中,可看出其提供的CSS一般包含:
- color
- font-family : 字体
- font- size: 字号
一般都是给某些限定的字体,比如
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
但是想要在这些标签之外默认字体设置怎么办?用下面的:
/* everywhere else */
* {
font-family: Arial, Helvetica, sans-serif;
}
*
就代表了默认的选项。
总结
这一章之后,学会了:
- 使用 Angular CLI 创建初始应用结构
- 使用 Angular 组件显示数据
- 使用 来插值。
1. 英雄编辑器
在命令行之中使用 ng generate component heroes
来新建组件, 名为 heroes。
新建组件之后,可以看到其新建四个文件,除了上面提到的三个,还有一个以spec.ts
结尾的测试文件,用于测试。
下面是heroes.component.ts
之中的部分代码:
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
CLI 自动生成了三个元数据属性:
- selector - 组件的选择器
- templateUrl - 组件模板文件的位置
- styleUrls - 组件私有 CSS 样式表文件的位置
其中 app-heroes
用来在父组件的模板之中匹配 HTML 元素的名称。也就是说,是用来在其他文件,例如在 app.component.html
之中插入的调用名称。
ngOnInit()
是一个生命周期钩子,在创建完组件之后就会调用,以完成复杂的初始化过程。
且一定要将这个 class export, 不然其他的地方没法使用。
使用 UppercasePipe 格式化
在 Angular 之中,可以使用 Pipe 表达式来将其格式化。相当于是 pipe 符号左边的数据经过 Pipe 处理之后再流出管道。例如
` <h2> Details</h2>`
就可以看作是 hero.name
经过 uppercase
之后其值变为大写再流出。
双向绑定
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name">
</label>
</div>
此处使用ngModel
可以实现数据的双向绑定,但是不可以直接使用。原因是这个属于 FormsModule
下面的模块需要在 app.module.ts
之中注册。
首先是:
import {FormsModule} from '@angular/forms';
然后在下面的ngModule
里面在进行引入:
@NgModule({
declarations: [
AppComponent,
HeroesComponent
],
imports: [
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
注意其中已经 imports 了这个 Module
2. 显示英雄列表
*ngFor 列出所有英雄
在<li> 标签之中使用 *ngFor 来列出所有英雄,其作用范围也是 <li> 标签。
<h2>My Heroes</h2>>
<ul class="heroes">
<li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero==selectedHero">
<span class="badge"></span>
</li>
</ul>
注意此处的 <ul class="heroes">
是为了下面的CSS 绑定做铺垫,而 [class.selected]="hero==selectedHero"
的作用我们之后再讲。
千万不要忘记 ngFor 的星号
为什么一定要带星号?
看看下面代码有什么特别的?
<div *ngIf="hero"></div>
<div *ngFor="let hero of heroes"></div>
上面指令名称有前缀星号(*),星号是一个语法糖,简化了 ngIf
和 ngFor
二者的读写,在模板引擎里最后还是会转换成 <template>
模式。
以下是 ngIf
语法糖与 <template>
的写法:
<!-- Examples (A) and (B) are the same -->
<!-- (A) *ngIf paragraph -->
<p *ngIf="condition">
Our heroes are true!
</p>
<!-- (B) [ngIf] with template -->
<template [ngIf]="condition">
<p>
Our heroes are true!
</p>
</template>
只要不傻肯定用第一种写法。值得注意的是从A扩展到B,先将段落及其内容移到 <template>
标签里面,属性绑定部分作为 <template>
标签的指令。
接下来看看 *ngFor
是如何转换:
<!-- Examples (A) and (B) are the same -->
<!-- (A) *ngFor div -->
<div *ngFor="let hero of heroes"></div>
<!-- (B) ngFor with template -->
<template ngFor let-hero [ngForOf]="heroes">
<div></div>
</template>
基本上和 ngIf
如出一辙;额外的细微是多了 ngForOf
属性绑定和 hero
本地模板变量。
主从结构
当用户在主列表点击一个英雄时,该组件在页面底部显示所选英雄的详情。上面代码之中的(click)="onSelect(hero)"
就是一个事件绑定语法的例子。click 外面的圆括号会让 Angular 监听这个 <li> 元素的 click 事件,当用户点击 <li> 时, Angular 就会执行表达式 onSelect(hero)
使用 *ngIf 隐藏空白的详情
一段代码块,如果不想让其产生作用,那么就使用<div>将其包裹起来,同时在标签内部使用 <div *ngIf>来作为条件判断。
使用样式绑定
前面我们所提到的那段代码,[class.selected]="hero==selectedHero"
,其作用就是在我们的 HTML 之中将 CSS 之中已有的样式绑定上去。
其含义为将 CSS 之中的 “heroes.selected”(因为class是heroes) 绑定到hero和selectedHero 相同的Hero上面去,也就是点谁谁变。
小结
个人小结:
在学习到这里的过程中,我个人认为,Angular 的纽带其实是模板,也就是HTML文件。模板通过绑定,可以连接到 Components 之中的方法, 可以使用 *ngIf 或者是*ngFor 等等来进行条件筛选。Component更多的是提供逻辑模块或者是变量运算。样式的话 CSS 也是通过在模板页面进行引用来获得的。
官方小结:
- 可以选择一个英雄,并查看英雄的详情。
- 使用*ngFor 显示一个列表
- 使用 *ngIf 包含或者排除一段HTML
- 使用 class 绑定来切换 CSS 的样式类
3. 主从组件
这一节主要是讲如何将上一节之中提到过的 html 根据不同的功能分开,也就是将app-hero
和 app-hero-details
放在不同的模块之中。这样做有:
- 可以单独修改 HeroesComponent 或者 HeroDetailComponent ,而不需要对其他组件进行变动。
- 可以在其他地方复用 HeroDetailComponent 。
生成Component
ng generate component hero-detail
同样,会生成一个 ts 文件,一个 HTML 文件,一个专属的 CSS 文件,还有一个测试文件。与此同时,其会将 HeroDetailComponent 添加到 src/app/app.module.ts
之中的 @NgModule 的 declarations 之中。
模板分割
将 HeroesComponent 的模板底部的 HTML 代码粘贴到生成的 HeroDetailComponent 之中。
由于在新的 Component 之中暂时没有 selectedHero 属性,所以要将其改成 Hero 。
hero-detail-component.html
<div *ngIf="hero">
<h2> Details</h2>
<div><span>id: </span></div>
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
</label>
</div>
</div>
添加 @Input() hero 属性
因为要让我们的 HeroDetailComponent 被外部的 HeroesDetail 所使用,所以我们要在其中添加好 @Input() 的属性。同时因为上面已经将模板之中的所有 selectedHero 改成了 hero , 所以我们还要在 ts 文件之中将 hero添加进去。
hero-detail.component.ts
import { Component, OnInit,Input } from '@angular/core';
import {Hero} from '../hero';
@Component({
selector: 'app-hero-detail',
templateUrl: './hero-detail.component.html',
styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {
@Input() hero:Hero;
constructor() { }
ngOnInit() {
}
}
注意这里面我们说了要有 Input() 属性,所以在第一行的 @angular/core
之中要多加一个 Input 。下面的 @Input() hero:Hero;
即为将 hero 属性用 @Input 来修饰。
修改 HeroesComponent 的模板
父子关系之中,要将父类的模板修改,使之可以使用子类。
在模板的最下面加入一行:
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
其中的 [hero]="selectedHero"
是一种单向绑定语法。即从 HeroesComponent 的 selectedHero 属性绑定到目标元素的 hero 属性,并且映射到 HeroDetailComponent 的 hero 属性。
小结
- 创立了一个独立的,可复用的 HeroDetailsComponent 组件
- 使用属性绑定将父组件 HeroesComponent 控制子组件 HeroDetailComponent
- 使用 @Input 装饰器使 hero 可以在外部被 HeroesComponent 绑定。
4.服务
个人对于 ts 之中 class 写法的看法
ts 之中我们经常需要去写 export 的 class 去给其他类使用。在 ts 之中我认为分为四部分:
- 变量初始化: 比如初始化变量 hero, 初始化对象等等
- constructor: 用来对类进行实例化,只会调用一次
- ngonInit : 用来对类进行初始化。
- function : 再就是去写很多的功能,所有功能都在这个部分被定义。
为什么需要服务
一般而言,我们都会将整个Web Application 分成几个部分,部分之间通过引用和注释来相互调用,这样方便代码的修改。之前的教程之中讲到了将 component 变成父子结构,在父子结构之中进行相互调用。这样对于修改或者扩张,都可以保证最小程度的进行改动。
在Web Application 之中,我们肯定是需要进行数据的存取的。数据存取是前端和服务器之间进行的操作,由于网络有延迟,所以一般都要使用异步操作。前端先暂时响应着页面,同时等待服务器传来的数据。一般来说,我们都会使用一个单独的 Service 组件进行操作。
传统分层也是如此,展示页面—Controller 负责逻辑— Service 负责和数据库之间进行连接传输。因此这一节主要内容是Service的创建和调用。
修改HeroesComponent
要在 HeroesComponent 的 constructor 之中加入一个属性 private 的 Service 。这里只是需要 Private 属性就足够,但是下面的 messageService 注入我们必须使用 public 属性,原因之后会提。
constructor(private heroService: HeroService) { }
这段话完成了两个事情:一个是声明了一个私有 heroService 属性,一个是将其标记为一个 HeroService 的注入点。
添加 getHeroes()
稍后这段代码会改为需要Observation的格式。但是现在暂时还是从内存之中得到值。
getHeroes(): void {
this.heroes = this.heroService.getHeroes();
}
然后在 ngOnInit() 之中调用。
插一句话:上面我们分析了在一个class之中有两个东西,一个是 constructor, 一个是 ngOnInit() 。 Angular 只能控制其中的 ngOnInit() ,也不知道这个是不是在教程之中强烈推荐将 getHeroes() 放到 ngOnInit() 之中使用而不是放在 constructor() 的原因,哈哈哈哈哈。所以最好在 constructor() 之中只做依赖注入操作。
可观察 (Observable) 的数据
前面的
this.heroes=this.heroService.getHeroes();
是同步获取数据的方式。但是在现实生活之中,所有的数据获取都是异步的,异步的话可以返回回调函数(callback),承诺(Promise)和可观察对象(Observable)。
在我们这节之中将会使用 Observable , 因为其最终会使用Angular 的 HttpClient.get 方法来获得数据,而 HttpClient.get() 所返回的对象就是 Observable 。
可观察对象版本的 HeroService
Observable 是 RxJS 库之中的一个关键类。
这节之中使用 RxJS 的 of() 函数来模拟从服务器返回数据。
hero.service.ts
import { Observable, of } from 'rxjs';
......
getHeroes():Hero[]{
return HEROES;
}
这种情况下 of(HEROES) 会返回一个 Observable<Hero[]> ,其会发出单个值,这个值就是模拟这些英雄的数组。
在 heroes.component.ts
之中将 getHeroes() 换成以下代码:
getHeroes(): void {
this.heroService.getHeroes()
.subscribe(hero1es => this.heroes = hero1es);
}
上面的 subscribe() 之中的 heroes => this.heroes = heroes
意味将接收进来的值设为 hero1es , 然后将这个 hero1es 赋值给一开始架设的 heroes 变量。
显示消息
首先创建一个 MessageComponent
ng generate component messages
然后将其先添加到 app.component.html 之中,方式和之前
app.component.html
<h1></h1>
<app-heroes></app-heroes>
<app-messages></app-messages>
再创建一个 MessageService
ng generate service message
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class MessageService {
messages: string[] = [];
add(message: string) {
this.messages.push(message);
}
clear() {
this.messages = [];
}
}
其中定义了一个 messages 作为缓存,两个方法: add() 用于添加一条消息 和 clear() 用于清空 messages 缓存。之外再使用export 将这些全都暴露出去。
将其注入到 HeroService 之中
将 HeroService 之中 import 这个 MessageService ,之后在 constructor 之中加入
constructor(private messageService: MessageService) { }
现在我们的 HeroService 之中注入了 MessageService ,是一个典型的 ” 服务中的服务“ 场景。
从 HeroService 之中显示消息
将 MessagesComponent 之中加入 MessageService , 之后在其 constructor 之中加入:
constructor(public messageService: MessageService) {}
**此处的 messageService 是 public **
原因?是因为要在其模板 HTML 之中直接加入 messageService 的属性,所以这种直接在模板之中使用的情况必须是 public 。
5. 路由
本节的主要目标是将之前由 onSelect() 定义获取的变量,使用链接的形式进行存取。即将每一个 HeroDetailComponent 使用对应的 id 进行读取
添加 AppRoutingModule
在 Angular 之中,最好使用一个独立的顶级模块之中加载和配置路由器,只是专注于路由功能。导入使用 AppModule 。
使用CLI 生成路由
ng generate module app-routing --flat --module=app
- ` –flat` 将这个文件放到了 src/app 之中,而不是单独目录之中。因为有的情况可能并不止一张路由表,不只在顶级模块之中有定义,所以要在此处指明
--module=app
的作用是告知 CLI 将其注册到 AppModule 的 imports 数组之中。
在 AppRoutingModule 之中添加 RouterModule
import { RouterModule, Routes } from '@angular/router';
@NgModule({
exports: [ RouterModule ]
})
此处将文件成为一个路由表的所需引用已经导入好了,之后将 RouterModule 导出,这样可以使路由器的相关指令在 AppModule 的组件之中使用。
添加路由定义
在路由表之中配置哪个 URL 去往哪个 Component。
典型的一条路由表有两个属性:
- path:用于匹配URL
- component:当导航到此路由时,应该创建哪个组件
import { HeroesComponent } from './heroes/heroes.component';
const routes: Routes = [
{ path: 'heroes', component: HeroesComponent }
];
上面这一段意味着将 localhost:4200/heroes 导航到 HeroesComponent 组件之上。
RouterModule.forRoot()
用于初始化路由器,并且开始监听浏览器之中的地址变化。
将 RouterModule添加到 imports 之中,并且参数位置填上 routes。
imports: [ RouterModule.forRoot(routes) ],
这个方法之所以叫 forRoot(), 是要在应用的 root 层面去配置这个router。这个方法会提供路由所需的初始化,并且基于当前浏览器的URL 进行第一次导航。
添加路由出口(RouterOutlet)
将 AppComponent 之中的
添加路由链接(routerLink)
不可能让用户每次都在地址栏之中使用 URL 进行抓取导航。所以要在页面之上设置一个链接,让其可以链接到某个 component 。
官方教程:在 app.component.html 之中添加
<nav>
<a routerLink="/heroes">heroes</a>
</nav>
-
<nav>
:HTML导航栏 (<nav>
) 描绘一个含有多个超链接的区域,这个区域包含转到其他页面,或者页面内部其他部分的链接列表.使用说明:
添加仪表盘视图
弄一个仪表盘视图,看着好看一点。
ng generate component dashboard
随堂讨论部分:
- 此时的 *ngFor 还没有任何的链接绑定,只是鼠标挪上去会变成小手,点击无作用
- 链接被 dashboard.component.css 之中的样式格式化成了一些色块。
注意此处的 slice 用于将返回的 heroes 筛选第2到第5片之后放到页面上。
添加仪表盘路由与默认路由
在已经添加好仪表盘路由的基础上,默认路由可以这样设计:
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
pathMatch 有什么作用呢?其有两种模式,一种是 full , 一种是 prefix 。 full 的话必须要匹配完整的 URL 才可以,就比如 path:test
,其意为只有 localhost:4200/test
这个网址才能跳转到 redirectTo
的页面,但是localhost:4200/test/1
就不可以。如果将 pathMatch 这个属性设置为 prefix ,其就意味着例如 ` localhost:4200/test,或者
localhost:4200/test/1这样的页面都可以匹配到
/dashboard`这个路由。
导航到英雄详情
在接下来的设计之中,应该可以做到:
- 在 dashboard 之中点击某个链接来导航到某个英雄
- 在英雄列表之中点击某个链接来导航到某个英雄
- 通过一个”深链接“ URL 粘贴到浏览器的地址栏来指定要显示的英雄
所以要将 HeroDetailComponent 从 HeroesComponent 之中解放出来,换成使用链接方式的访问。
添加英雄详情访问
首先将带有 id 的导航信息放到路由之中
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
...
{ path: 'detail/:id', component: HeroDetailComponent },
注意这个地方的冒号是占位符,表示某个特定英雄的 id。
在这个之后,所有的路由表已经就绪了,下面可以对照一下和自己的是否相同。
const routes: Routes = [
{ path: 'heroes', component: HeroesComponent },
{ path: 'dashboard', component: DashboardComponent },
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{path:'detail/:id',component:HeroDetailComponent},
{path:'test',redirectTo:'/dashboard',pathMatch:'prefix'}
];
注意上面这个最后一条只是我为了测试 prefix 属性使用的,本身并无用处。
DashboardComponent 之中的英雄链接
所以回头看,之前的 <router-outlet>
之中实际是看其 URL 进行导航。由于在之前的路由表之中已经有了 { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
所以在一开始的时候其 URL 就会自动跳转到 dashboard
, 而 dashboard
又对应着 dashboardComponent ,所以默认就会自动变为 URL:http://localhost:4200/dashboard
,在 <router-outlet>
部分也会变成 dashboard 的样式。
下面是将链接插入所有的 dashboard 项之中:
<a *ngFor="let hero of heroes" class="col-1-4"
routerLink="/detail/">
<div class="module hero">
<h4></h4>
</div>
</a>
同样的,对 heroesComponent 之中也做同样的操作。
<ul class="heroes">
<li *ngFor="let hero of heroes">
<a routerLink="/detail/">
<span class="badge"></span>
</a>
</li>
</ul>
支持路由的 HeroDetailComponent
要将其改成:
- 获取创建本组件的路由
- 从这个路由之中获得 id
- 通过 HeroService 从服务器之中获取到具有这个 id 的英雄数据。
为了实现上面的三个功能,其需要先导入语句:
import { ActivatedRoute } from '@angular/router';
import { Location } from '@angular/common';
import { HeroService } from '../hero.service';
...
constructor(
private route: ActivatedRoute,
private heroService: HeroService,
private location: Location
) {}
- ActivatedRoute 用来提取路由之中的参数
- Location 用来保存点击的路径,可以实现返回上一个链接等操作
- heroService 是我们自己写的使用 Observation 来返回 hero 数据的方式。
从路由之中提取id
ngOnInit():void {
this.getHero();
}
getHero():void{
const id=+this.route.snapshot.paramMap.get('id');
console.log("The id wiht + is "+id);
this.heroService.getHero(id).subscribe(hero=>this.hero=hero);
}
route.snapshot 是路由信息的静态快照,而 paramMap.get() 就是从URL 之中提取 id的方法。
路由参数总是字符串,而JavaScript 的 (+) 操作符会把字符串转换成数字,英雄的 id
就是数字类型。
添加 HeroService.getHero()
在 HeroService 之中添加下面的 getHero() 方法
getHero(id: number): Observable<Hero> {
// TODO: send the message _after_ fetching the hero
this.messageService.add(`HeroService: fetched hero id=${id}`);
return of(HEROES.find(hero => hero.id === id));
}
- id 接收的是参数
- messageService 之中 add 的信息是使用反引号 ` 来括起来的,就是为了嵌入 id
使用回退
<button (click)="goBack()">go back</button>
goBack(): void {
this.location.back();
}
现在可以使用 back 按钮来直接回退了。
官方小结
- 添加了路由器,用于各个不同组件之间导航
- 使用
<a>
和一个<router-outlet>
将 AppComponent 变成了一个只是导航使用的壳 - 将一个紧耦合的主从视图变成了带路由的详情视图
- 在多个组件之间共享了 HeroService 服务
6. HTTP
!== is strictly comparing variables on both sides for their VALUE and TYPE. The result will be true if either VALUE or TYPE is inconsistent. While != is more “tolerant”, that it is going to return true only if VALUE are different from the two sides of comparison.
7.在使用Angular之中遇到的疑问和解释
1.为什么所有 method 之中使用 class 的变量需要加上 this?
我认为是这样的:
在很多函数之中,我们都会有传入值,比如
outside:String;
onSubmit(parameter1,parameter2)
{
//Error:because forget "this"
outside="Just for test"
}
上面这段代码之中,outside 因为前面没有加上 this 做限定词,所以报错。
个人认为,原因在于不加 this 的话,编译器会从函数的 parameter 之中寻找是否有这个变量,如果没有的话,就会直接报错。
而如果想要使用其所属的 class 之中的变量,则需要在前面加上 this 予以限定。
2. 为什么 Service 需要放在 constructor 之中,而不是放在 ngOnInit() ?
Service 与其他东西不同点在于:
Service 一般都有 @Injectable
这个属性
@Injectable({
providedIn: 'root'
})
那么在这个 component 之中,下面是 constructor() 部分的代码:
constructor(private heroService: HeroService) { }
这个参数同时做了两件事:1. 声明了一个私有
heroService
属性,2. 把它标记为一个HeroService
的注入点。当 Angular 创建
HeroesComponent
时,依赖注入系统就会把这个heroService
参数设置为HeroService
的单例对象。
3. =>
到底是干什么用的?
我们经常可以看到:
this.someService.someMethod(this.someValue).subscribe(
response=>{
//Doing some functions here
}
)
发现对于 Observable ,总是有一个 subscribe 和一个 response 。而且 response 后面总是跟着 =>
。网上也没找到很多资料,就我个人在实际操作之中的理解,其意义就是在得到 response 之后执行后面大括号之中的代码,而且大括号之中的代码可以直接使用 response。
4. [ ]
在 Angular之中是什么意思?
在 Angular 之中,会看到在 img 的标签之中的 src 是以 [src] 形式出现的。其他地方很少见这种操作。那么为什么要加入 [ ]
这个呢?
原因是 [src] 是相对于 img 标签的输入,对于控件的输入,要使用 [ ]
括起来,这里面亲测如果不括起来的话,会直接将后面的字符串作为src来代入,例如 src="image"
,其不会将 component 之中的 image 变量传入,只会将 ”image“ 这个字符串作为链接,然后访问例如localhost:8888/image
这样的网页,并且给你抛出一个 404
5.<mat-table>
之中的设置
在使用<mat-table>
的过程之中,发现始终提示cannot find column called 'id'
,自认为所有的数据和参数都按照官方示例设置正确了,google 一看,发现是因为其中的属性 matColumnDef
之中的设置不对。这个地方应该和在 ts 文件之中设置的相同。这里要更加注意。
6.如何在Angular之中获取网址的参数?
首先在 constructor 之中使用
constructor(private route:ActivatedRoute)
在这个之后可以在 noOnInit() 之中使用下面的方法来获得链接之中的ID:
this.id = this.route.snapshot.paramMap.get("id");
这里面的 get("id")
不是随便写的,是因为在 app-routing.module.ts
之中有定义:
{ path: 'detail/:id', component: SomeComponent },
三者结合,就可以从网址之中拿到所要的数据了。
7.HQL
HQL和 Angular 实际并不相关,但是都是在本次做项目之中使用到的东西,在这里做一个简单的总结。
HQL(Hibernate Query Languge),是一种面向对象的查询语言,在其中和SQL的 table 和 column 不同,主要概念是 class, object 和 attribute。其语法如下:
[select/update/delete……] from Entity [where……] [group by……] [having……] [order by……]