【CuteJavaScript】Angular6入门项目(2.构建项目页面和组件)

本文目录

  • 1、项目起步
  • 2、编写路由组件
  • 3、编写页面组件
    • 1.编写单一组件
    • 2.模拟数据
    • 3.编写主从组件
  • 4、编写服务
    • 1.为何须要服务
    • 2.编写服务
  • 5、引入RxJS
    • 1.关于RxJS
    • 2.引入RxJS
    • 3.改造数据获取方式
  • 6、改造组件
    • 1.添加历史记录组件
    • 2.添加和删除历史记录
  • 7、HTTP改造
    • 1.引入HTTP
    • 2.经过HTTP请求数据
    • 3.经过HTTP修改数据
    • 4.经过HTTP增长数据
    • 5.经过HTTP删除数据
    • 6.经过HTTP查找数据

本项目源码放在githubhtml

3、编写页面组件

接下来开始编写页面组件,这里咱们挑重点来写,一些布局的样式,后面能够看源码。前端

1.编写单一组件

咱们首先写一个书本信息的组件,代码以下:vue

<!-- index.component.html -->
<div class="content">
  <div class="books_box">
    <!-- 单个课本 -->
    <div class="books_item" *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
      <img class="cover" src="https://img3.doubanio.com/view/subject/m/public/s29988481.jpg">
      <div class="title"><a>像火焰像灰烬</a></div>
      <div class="author">程姬</div>
    </div>
  </div>
</div>
复制代码

知识点
*ngFor 是一个 Angular 的复写器(repeater)指令,就像angular1中的ng-forvuejs中的v-for。 它会为列表中的每项数据复写它的宿主元素。
这时候能够看到页面变成下面这个样子:
git

图片3-1

接下来咱们要把写死在HTML上面的数据,抽到JS中:github

如今先新建一个books.ts文件来定义一个Book类,并添加idurltitleauthor四个属性:bash

// src/app/books.ts
export class Book {
    id: number;
    url: string;
    title: string;
    author: string;
}
复制代码

而后回到index.component.ts文件去引入它,并定义一个books属性,使用导入进来的Book类做为类型:服务器

// index.component.ts
import { Book } from '../books';
export class IndexComponent implements OnInit {
  books: Book = {
    id: 1,
    url: 'https://img3.doubanio.com/view/subject/m/public/s29988481.jpg',
    title: '像火焰像灰烬',
    author: '程姬',
  }
}
复制代码

而后再改造前面的组件文件index.component.html:微信

<!-- index.component.html -->
<div class="books_item" *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
  <img class="cover" src="{{books.url}}" alt="{{books.id}}">
  <div class="title">
    <a>{{books.title}}</a>
  </div>
  <div class="author">{{books.author}}</div>
</div>
复制代码

接着,咱们再为每一个课本添加一个点击事件,来实现点击封面图能查看大图的效果,如今index.component.ts中定义一个getDetailImage方法,并在index.component.html中绑定该方法:app

// index.component.ts
export class IndexComponent implements OnInit {
  getDetailImage(books){
    alert(`正在查看id为${books.id}的大图!`);
  }
}
复制代码

这边方法的具体实现,不写,不是本文重点。下面是增长点击事件的绑定:ide

<!-- index.component.html -->
<img class="cover" src="{{books.url}}" alt="{{books.id}}" (click)="getDetailImage(books)">
复制代码

知识点
(click)是Angular用来绑定事件,它会让 Angular 监听这个<img> 元素的 click 事件。 当用户点击 <img> 时,Angular 就会执行表达式 getDetailImage(books)

再来,咱们引入前面学到的路由连接指令来改造HTML:

<!-- index.component.html -->
<a routerLink="/detail/{{books.id}}">{{books.title}}</a>
复制代码

这时候,咱们在点击书本的标题,发现页面跳转到URL地址为http://localhost:4200/detail/1的页面,这就说明,咱们页面的路由跳转也成功了~

改造完成后,能够看到,页面显示的仍是同样,接下来咱们先这样放着,由于咱们后面会进行数据模拟,和模拟服务器请求。

咱们就这样写好第一个单一组件,而且数据是从JS中读取的。

2.模拟数据

这时候为了方便后面数据渲染,咱们这里须要模拟一些本地数据,咱们建立一个本地mock-books.ts文件来存放模拟的数据:

// app/mock-books.ts
import { Books } from './books';
export const BookList: Books[] = [
    {
        id: 1, 
        url: 'https://img3.doubanio.com/view/subject/m/public/s29988481.jpg',
        title: '像火焰像灰烬',
        author: '程姬',
    },
    // 省略其余9条
]
复制代码

而后在index.component.ts中导入模拟的数据,并将原有的books值修改为导入的模拟数据BookList

// index.component.ts
import { BookList } from '../mock-books';
books = BookList;
复制代码

并将本来的*ngFor中修改为这样,绑定真正的数据:

<!-- index.component.html -->
<div class="books_item" *ngFor="let item of books">
  <img class="cover" src="{{item.url}}" alt="{{item.id}}">
  <div class="title">
    <a>{{item.title}}</a>
  </div>
  <div class="author">{{item.author}}</div>
</div>
复制代码

3.编写主从组件

当咱们写完一个单一组件后,咱们会发现,若是咱们把每一个组件都写到同一个HTML文件中,这是很糟糕的事情,这样作有缺点:

  • 代码复用性差;(致使每次相同功能要从新写)
  • 代码难维护;(由于一个文件会很是长)
  • 影响性能;(打开每一个页面都要重复加载不少)

为了解决这个问题,咱们这里就要开始使用真正的组件化思惟,将通用经常使用组件抽离出来,经过参数传递来控制组件的不一样业务形态。
这即是咱们接下来要写的主从组件。

思考一下,咱们这里如今能抽成组件做为公共代码的,就是这个单个书本的内容,由于每一个书本的内容都一致,只是里面数据的差别,因而咱们再新建一个组件:

ng g component books
复制代码

并将前面index.component.html中关于课本的代码剪切到books.component.html中来,而后删除掉*ngFor的内容,并将本来本地的变量books替换成list,这个变量咱们等会会取到:

<!-- books.component.html -->
<div class="books_item">
  <img class="cover" src="{{list.url}}" alt="{{list.id}}" (click)="getDetailImage(list)">
  <div class="title">
    <a routerLink="/detail/{{list.id}}">{{list.title}}</a>
  </div>
  <div class="author">{{list.author}}</div>
</div>
复制代码

再将这个组件,引用到它的父组件中,这里是要引用到index.component.html的组件中,并将前面的*ngFor再次传入<app-books>

<div class="content">
  <div class="books_box">
    <app-books *ngFor="let item of books"></app-books>
  </div>
</div>
复制代码

接下来要作的就是获取到list变量的值,显然这个值是要从外面组件传进来的,咱们须要在books.component.ts引入前面定义的 Books类 和 @Input() 装饰器,还要添加一个带有 @Input() 装饰器list 属性,另外还要记得将getDetailImage方法也剪切过来:

// books.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { Books } from '../books';

export class BooksComponent implements OnInit {
  @Input() list: Books;
  constructor() { }
  ngOnInit() {}
  getDetailImage(books){
    alert(`正在查看id为${books.id}的大图!`);
  }
}
复制代码

@Input() 装饰器介绍具体能够查看 手册

咱们要获取的 list 属性必须是一个带有@Input()装饰器的输入属性,由于外部的 IndexComponent 组件将会绑定到它。就像这样:

<app-books *ngFor="let list of books" [list]="item"></app-books>
复制代码

知识点
[list]="item"Angular属性绑定语法。这是一种单向数据绑定。从 IndexComponentitem 属性绑定到目标元素的 list 属性,并映射到了 BooksComponentlist 属性。

作到这里,咱们已经将BooksComponent做为IndexComponent的子组件来引用了,在实际开发过程当中,这样的父子组件关系,会用的很是多。

写到这里,看看咱们项目,仍是同样正常在运行,只是如今项目中组件分工更加明确了。

如今的效果图:

图片3-2

本部份内容到这结束

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推荐 https://github.com/pingan8787/Leo_Reading/issues
JS小册 js.pingan8787.com
微信公众号 前端自习课

前端自习课
相关文章
相关标签/搜索