Angular基础知识学习(二)上

简介: Angular基础知识学习(二)上

服务


创建服务之后,我们在 StorageService.service.ts 中定义一个测试方法:


export class StorageService {
  constructor() {
  }
  test() {
    alert('调用服务方法');
  }
}
复制代码


我们重新建立一个 home 组件,来测试服务调用。


<p>home works!</p>
<button (click)="getService()">获取服务</button>
复制代码
import { Component, OnInit } from '@angular/core';
import {StorageService} from '../../services/storage.service';
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  constructor(public storage: StorageService) { }
  ngOnInit(): void {
  }
  getService() {
    this.storage.test();
  }
}
复制代码


测试:


1.jpg


数据持久化到localStroage


之前的 search 和 todoList 测试案例当页面刷新数据都会消失,接下来我们在 service 里构建数据持久化方法(实际是存放到浏览器的 localStroage 中)。


首先在 StorageService.service.ts 定义三个方法:


set(key: string, value: string[]) {
    // @ts-ignore
    localStorage.setItem(key, JSON.stringify(value));
  }
  get(key: string) {
    return JSON.parse(localStorage.getItem(key));
  }
  remove(key: string) {
    localStorage.removeItem(key);
  }
复制代码


在组件中调用服务里定义的方法:


import {Component, OnInit} from '@angular/core';
import {StorageService} from '../../services/storage.service';
@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {
  keyWord: any = '';
  keyWordsOld: any[] = [];
  product: any = '';
  products: any[] = [];
  constructor(public storage: StorageService) {
  }
  // 在初始化方法中查询localStorage中是否有数据
  ngOnInit(): void {
    // tslint:disable-next-line:prefer-const
    let serchList = this.storage.get('serchList');
    // tslint:disable-next-line:prefer-const
    let todoList = this.storage.get('todoList');
    if (serchList) {
      // @ts-ignore
      this.keyWordsOld = serchList;
    }
    if (todoList) {
      this.products = todoList;
    }
  }
  //输入内容后回车触发该方法
  keyup(e) {
    if (e.keyCode === 13){
      //首先判断搜索内容是否重复,若为新则加入
      if (this.keyWordsOld.indexOf(this.keyWord) === -1) {
        this.keyWordsOld.push(this.keyWord);
        this.storage.set('serchList', this.keyWordsOld);
      }
      this.keyWord = '';
    }
  }
  //搜索按钮绑定的方法
  search() {
    if (this.keyWordsOld.indexOf(this.keyWord) == -1) {
      this.keyWordsOld.push(this.keyWord);
      this.storage.set('serchList', this.keyWordsOld);
    }
    this.keyWord = '';
  }
  //删除按钮绑定的方法
  delete(key) {
    this.keyWordsOld.splice(key, 1);
    this.storage.set('serchList', this.keyWordsOld);
  }
  //回车事件,触发该方法
  add(e) {
    // tslint:disable-next-line:triple-equals
    if (e.keyCode == 13) {
      if (!this.equalProduct(this.products, this.product)) {
        this.products.push({
          title: this.product,
          status: 0
        });
        this.product = '';
        this.storage.set('todoList', this.products);
      } else {
        alert('数据已存在');
        this.product = '';
      }
    }
  }
  deleteWay(key) {
    this.products.splice(key, 1);
    this.storage.set('todoList', this.products);
  }
  //新增数据前与已有记录进行比对
  equalProduct(products: any[], value: any) {
    if (!value || value === '') {
      return false;
    }
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < products.length; i++) {
      // tslint:disable-next-line:triple-equals
      if (products[i].title == value) {
        return true;
      }
    }
    return false;
  }
  //change事件用来更新缓存中的内容
  change() {
    this.storage.set('todoList', this.products);
  }
}
复制代码


html 文件基本不变,测试效果:


1.jpg


注意观察下方 localStorage 中的内容,当页面刷新之后数据仍然存在。


生命周期


指令和组件的实例有一个生命周期:当 Angular 新建、更新和销毁它们时触发。 通过实现一个或多个 Angular core 库里定义的生命周期钩子接口,开发者可以介入该生命周期中的这些关键时刻。


每个接口都有唯一的一个钩子方法,它们的名字是由接口名再加上 ng 前缀构成的。比如,OnInit 接口的钩子方法叫做 ngOnInit, Angular 在创建组件后立刻调用它,:


export class PeekABoo implements OnInit {
  constructor(private logger: LoggerService) { }
  // implement OnInit's `ngOnInit` method
  ngOnInit() { this.logIt(`OnInit`); }
  logIt(msg: string) {
    this.logger.log(`#${nextId++} ${msg}`);
  }
}
复制代码


生命周期的顺序:


1.jpg


这里我们重点学习  ngOnInit() 和 ngAfterViewInit()这两个方法。


首先新建 home 组件,其 html 内容为:


<h2>这里一个home组件---DOM操作演示</h2>
<div id="box">
  这是一个div标签
</div>
<br>
<div id="box2" *ngIf="flag" >
  这是第二个div标签
</div>
复制代码


home.component.ts 文件内容为:


export class HomeComponent implements OnInit {
  flag = true;
  constructor() { }
  /*生命周期函数*/
  ngOnInit(): void {
    /*//组件和指令初始化完成,并不是真正的dom加载完成*/
    let oBox = document.getElementById('box');
    console.log(oBox.innerHTML);
    oBox.style.color = 'red';
    // 此处获取不到dom节点,所以最好不要在ngOnInit方法中获取dom节点
    /*let oBox2: any = document.getElementById('box2');
    console.log(oBox2.innerHTML);
    oBox2.style.color = 'blue';*/
  }
  // 视图加载完成后触发的方法,dom加载完成
  // tslint:disable-next-line: use-lifecycle-interface
  ngAfterViewInit(): void {
    let oBox2 = document.getElementById('box2');
    console.log(oBox2.innerHTML);
    oBox2.style.color = 'blue';
  }
}
复制代码


通过操作 dom 节点来区分 ngOnInit 和 ngAfterViewInit 方法,前者用来初始化指令/组件,后者是当 Angular 初始化完组件视图及其子视图之后调用。所以后者才知道 box2 是否渲染完毕,然后才能获取到该 dom 节点并加以修改。


页面运行效果如下:


1.jpg


父子组件之间通信传值


新建四个组件:news,home,header,footer。其中 home 和 header 是父子组件关

系,news 和 footer 是父子组件关系 。


父组件通过@Input给子组件传值


1、home.component.html 用来传递变量和方法,也可以将 home 组件中所有信息传递过去。


<app-header [msg]="msg" [title]="title" [run]="run" [home]="this"></app-header>
<br>
<hr>
<br>
<h2>我是home组件</h2>
复制代码


2、home.component.ts


export class HomeComponent implements OnInit {
  msg: any = '我是home组件的msg';
  title: any = 'home组件的title';
  constructor() { }
  ngOnInit(): void {
  }
  run() {
    return '执行home组件的run方法';
  }
}
复制代码


3、header.component.html


<h2>我是header组件</h2>
<br>
<p>{{title}}-----{{msg}}</p>
<br>
<button (click)="getParentWay()">执行home组件的方法</button>
复制代码


4、header.component.ts,子组件中需要引入 Input,用来接收父组件传过来的数据。


import { Component, OnInit, Input } from '@angular/core';
@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
  @Input() msg: any;
  @Input() title: any;
  @Input() run: any;
  /*//获取home组件所有内容*/
  @Input() home: any;
  constructor() { }
  ngOnInit(): void {
  }
  getParentWay() {
    // alert(this.run());
    alert(this.home.run());
  }
}
复制代码


5、网页运行效果如下:


1.jpg


6、小结


父组件给子组件传值,即子组件获取父组件的属性和方法,大致分为以下几步:


  1. 父组件页面嵌套子组件页面,将属性和方法存放在子组件声明中;
  2. 子组件引入 Input 模块;
  3. 子组件通过@Input 获取子组件声明中存放的属性和方法;


子组件通过ViewChild给父组件传值


1、news.component.html,


<app-footer #footerComponent></app-footer>
<br>
<hr>
<br>
<h2>我是news组件</h2>
<button (click)="getChildData()">获取子组件的数据</button>
<br>
<br>
<br>
<button (click)="getChildWay()">执行子组件的方法</button>
复制代码


2、news.component.ts


import {Component, OnInit, ViewChild} from '@angular/core';
@Component({
  selector: 'app-news',
  templateUrl: './news.component.html',
  styleUrls: ['./news.component.css']
})
export class NewsComponent implements OnInit {
  @ViewChild('footerComponent') footer;
  constructor() {
  }
  ngOnInit(): void {
  }
  getChildData() {
    alert(this.footer.msg);
  }
  getChildWay() {
    this.footer.run();
  }
}
复制代码


3、footer.component.html


<h2>我是footer组件</h2>
复制代码


4、footer.component.ts


import {Component, OnInit} from '@angular/core';
@Component({
  selector: 'app-footer',
  templateUrl: './footer.component.html',
  styleUrls: ['./footer.component.css']
})
export class FooterComponent implements OnInit {
  msg: any = '我是footer组件的msg';
  constructor() {
  }
  ngOnInit(): void {
  }
  run() {
    alert('执行footer组件的run方法');
  }
}
复制代码


5、网页运行效果如下:


1.jpg


6、小结


子组件给父组件传值,即父组件主动获取子组件的属性和方法,大致分为以下几步:


  1. 父组件页面嵌套子组件页面,子组件声明时需要定义一个名称来代指子组件;
  2. 父组件引入 ViewChild 模块;
  3. 父组件通过@ViewChild 获取子组件的全部内容;


目录
相关文章
|
设计模式 JavaScript 前端开发
学习Angular的编程之旅
学习Angular的编程之旅
|
前端开发 JavaScript API
Angular与Rxjs学习
Angular与Rxjs学习
160 0
Angular与Rxjs学习
|
前端开发 JavaScript 网络架构
Angular基础知识学习(三)
Angular基础知识学习(三)
158 0
Angular基础知识学习(三)
|
缓存 前端开发 JavaScript
Javascript学习-angular开发环境搭建及新建项目并运行
Javascript学习-angular开发环境搭建及新建项目并运行
118 0
|
前端开发 JavaScript 安全
Angular基础知识学习(二)下
Angular基础知识学习(二)下
132 0
Angular基础知识学习(二)下
|
JavaScript
Angular基础知识学习(一)下
Angular基础知识学习(一)下
182 0
Angular基础知识学习(一)下
|
前端开发 JavaScript 安全
Angular基础知识学习(一)上
Angular基础知识学习(一)上
182 0
Angular基础知识学习(一)上
|
4月前
|
API 开发者 UED
PrimeFaces:JSF的魔法衣橱,解锁UI设计的无限可能!
【8月更文挑战第31天】本文介绍如何结合 JSF(JavaServer Faces)和 PrimeFaces 构建美观且功能强大的现代用户界面。PrimeFaces 提供丰富的 UI 组件库,包括按钮、输入框、数据网格等,支持现代 Web 标准,简化界面开发。文章通过具体示例展示如何使用 `&lt;p:inputText&gt;` 和 `&lt;p:calendar&gt;` 等组件创建用户表单,并用 `&lt;p:dataTable&gt;` 展示数据集合,提升 JSF 应用的易用性和开发效率。
71 0
|
4月前
|
开发者 安全 SQL
JSF安全卫士:打造铜墙铁壁,抵御Web攻击的钢铁防线!
【8月更文挑战第31天】在构建Web应用时,安全性至关重要。JavaServer Faces (JSF)作为流行的Java Web框架,需防范如XSS、CSRF及SQL注入等攻击。本文详细介绍了如何在JSF应用中实施安全措施,包括严格验证用户输入、使用安全编码实践、实施内容安全策略(CSP)及使用CSRF tokens等。通过示例代码和最佳实践,帮助开发者构建更安全的应用,保护用户数据和系统资源。
62 0
|
4月前
|
开发者 C# C++
揭秘:如何轻松驾驭Uno Platform,用C#和XAML打造跨平台神器——一步步打造你的高性能WebAssembly应用!
【8月更文挑战第31天】Uno Platform 是一个跨平台应用程序框架,支持使用 C# 和 XAML 创建多平台应用,包括 Web。通过编译为 WebAssembly,Uno Platform 可实现在 Web 上运行高性能、接近原生体验的应用。本文介绍如何构建高效的 WebAssembly 应用:首先确保安装最新版本的 Visual Studio 或 VS Code 并配置 Uno Platform 开发环境;接着创建新的 Uno Platform 项目;然后通过安装工具链并使用 Uno WebAssembly CLI 编译应用;最后添加示例代码并测试应用。
146 0