初涉angular的总结

初涉angular之自定义指令

1.自定义指令
import {Directive, ElementRef, HostListener} from "@angular/core";

@Directive({
 selector: '[nu-input]'
})
export class InputTrimDirective {
 constructor(public elementRef: ElementRef) {
 }
 @HostListener('keyup', ['$event.target'])
 keyupFun(evt) {
   if (evt.value) {
     this.elementRef.nativeElement.value = evt.value.trim();
   }
 }
}

在app.module声明指令,在app.module的declarations中声明才能生效

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {AppComponent} from './app.component';
import {InputTrimDirective} from "./direcitve/input-trim.directive";

@NgModule({
 declarations: [
   AppComponent,
   InputTrimDirective 
 ],
 imports: [
   BrowserModule,
   FormsModule,
 ],
 bootstrap: [AppComponent]
})
export class AppModule {
}

通过inport从core库中导入Directive,HostListener,ElementRef,Input .....的引入。

Directive

用于@Directive装饰器功能,用于定义这个class是一个指令,通过@Directive修饰这样就拥有了指令的功能,我们在元组中声明selector属性值为[input-trim],方括号的写法表示是一个属性指令 还有以下几种写法:

element-name: 使用元素名称选择
.class: 使用类名选择
[attribute]: 使用属性选择
[attribute=value]:使用属性和值选择
:not(sub_selector):只有当元素与sub_selector不匹配时才选择
selector1,selector2:选择择selector1或selector2 这里我们采用属性的方式指定选择器。
这里采用的是属性的方式指定选择器,
@Directive({
selector: '[nu-input]'
})

模板中使用,直接写 nu-input

HostListener

HostListener 是属性装饰器,用来为宿主元素添加事件监,类似于我们原生JavaScript的addEventListener。 这里我们监听了keyup事件(还可以定义原生JavaScript中的其他事件),当表单中有输入的时候我们就会调用方法,传递了一个$event对象进去,后面紧跟我们触法keyup事件的方法体
ElementRef(注意:需要在构造函数中注入进去)

用于获取获取DOM节点相关的属性
这里我们当我们在页面表单输入的时候,会调用keyupFun方法,首先判断是否有值输入,有的情况下,我们通过传递进来的evt获取表单的value值,在调用trim()方法去除空格,赋值给elementRef.nativeElement.value渲染到页面

import { Input, ElementRef, OnInit, Directive } from '@angular/core';
@Directive({
  selector: '[nu-input]',
  exportAs: 'nuInput',
  host: {
    '[class.nu-input]': 'true'
  }
})
export class NuInput implements OnInit {
  /**
   * 通过size设置input大小,默认为small, 支持big
   */
  @Input() size: String = 'small';
  constructor(private _elementRef: ElementRef) {
  }
  ngOnInit() {
    (this._elementRef.nativeElement as HTMLElement).classList.add('nu-input-' + this.size);
  }
}
扩展Host

这里如果我们不采用HostListener属性装饰器来监听事件,我们可以在指令的 metadata 信息中,设定宿主元素的事件监听信息,

// 自定义class类名
 host: {
    '[class.nu-input]': 'true'
  }
// 自定义'role-data'属性
 host: {
    'role-data': 'hello world'
 }
// 监听事件
 host: {
    '(keyup)': 'keyupFun($event.target)'
 }
exportAs

官方解释是说,exportAs: string:定义一个名字,用于在模板中把该指令赋值给一个变量。给的例子如下

@Directive({
     selector:  'child-dir',
     exportAs:  'child'  
})
 class  ChildDir  { }
 @Component({
  selector:  'main',
  template:  `<child-dir #c="child"></child-dir>`
  })
 class  MainComponent  {
 }
别人的解释
// 这是NuToolTipDirective元件中的部分内容
@Directive({
    selector: '[nu-tooltip]',
    exportAs: 'nuTooltip',
    host: {
        '[class.nu-tooltip-open]': 'isOpen'
    }
})
export class NuToolTipDirective implements AfterViewInit, OnChanges, OnInit, OnDestroy {
     * @ignore 是否显示tooltip
     */
    isOpen = false;
......
// 在模板中使用
// #tooltip1="nuTooltip"中,nuTooltip就是NuToolTipDirective的exportAs所定义的name,
// 代表了NuToolTip这个指令本身,button中定义#tooltip1指代nuTooltip
// isOpen是元件指令中定义的Boolen值,在模板中tooltip1.isOpen调用
<button nu-button nu-tooltip #tooltip1="nuTooltip"></button><span>{{tooltip1.isOpen}}</span>
//未指代,不能获取isOpen
<button nu-button nu-tooltip #tooltip2></button><span>{{tooltip2.isOpen}}</span>

初涉angular之组件通讯

1.子component调用父component的方法或属性值
@Input
效果图

通过按钮获得hobby name,显示在list下方。
1.home.component.html

<div class="home-list">
  <table>
    <tr>
      <td>编号</td>
      <td>爱好</td>
      <td>幸福指数</td>
      <td>操作</td>
    </tr>
    <tr *ngFor="let item of hobby; let i = index;">
      <td>{{i}}</td>
      <td>{{item.name}}</td>
      <td>{{item.fzs}}</td>
      <!--getDate()获取hobby name-->
      <td><button (click)="getDate(item.name)">选择</button></td>
    </tr>
  </table>
  <p>我选择的是:</p>
  <!--调用子组件-->
  <app-hobby [hobbyGetName]="hobbyName"></app-hobby>
</div>

2.home.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  public hobbyName: string; //传给子组件的值
  public hobby = [
    {name: 'code', fzs: '100'},
    {name: 'sing', fzs: '200'},
    {name: 'play', fzs: '1000'},
    {name: 'sleep', fzs: '500'}
    ];
  constructor() { }

  ngOnInit() {
  }
  getDate(name) {
    console.log(name);
    //将获取的值给hobbyName 赋值
    this.hobbyName = name; 
  }
}

3.子组件

import {Component, Input, OnInit} from '@angular/core';

@Component({
  selector: 'app-hobby',
  templateUrl: './hobby.component.html',
  styleUrls: ['./hobby.component.css']
})
export class HobbyComponent implements OnInit {
//@Input接受父组件传过来的[值]
  @Input() hobbyGetName: string;
  constructor() { }

  ngOnInit() {
  }

}

4.显示在view中

<p>{{hobbyGetName}}</p>
2.父component调用子component的方法或属性值
@Output 父组件接收子组件的数据时,子组件暴露一个EventEmitter属性,当事件发生时,子组件利用该属性emits(向上弹射)事件。父组件绑定到这个事件属性,并在事件发生时作出回应。
效果图

hobby.component.html

<p>{{hobbyGetName}}</p>
<button (click)="Descrip()">description</button>

hobby.component.ts

import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';

@Component({
  selector: 'app-hobby',
  templateUrl: './hobby.component.html',
  styleUrls: ['./hobby.component.css']
})
export class HobbyComponent implements OnInit {
  @Input() hobbyGetName: string;
  @Output() Detail: EventEmitter<any> = new EventEmitter();
  public hobbyDetail = [
    {name: 'code', description: '小辫子飞起!'},
    {name: 'sing', description: '听歌要命!'},
    {name: 'play', description: '莫不是怕上天?'},
    {name: 'sleep', description: '君何不扶摇之上?'}
  ];
  constructor() { }

  ngOnInit() {
  }
  Descrip() {
    console.log(this.hobbyGetName);
    this.hobbyDetail.forEach((i) => {
      if (this.hobbyGetName === i.name) {
        this.Detail.emit(i.description);
      }
    });
  }
}

home.component.html

  <p>我选择的是:</p>
  <app-hobby [hobbyGetName]="hobbyName" (Detail)="hobbyDse($event)"></app-hobby>
  <p>hobby的描述: </p>
  <span>{{hobbyDescription}}</span>
</div>

home.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  public hobbyDescription: string;
  constructor() { }

  ngOnInit() {
  }
  hobbyDse(e) {
    console.log(e);
    this.hobbyDescription = e;
  }
}

3.无关联component之间的通讯

Service服务

创建一个service.ts

//命令
ng generate service  'service name'
ng generate service  home
创建成功

在组件通用资源中,分享的是静态资源。例如login component与nav-title component的title是一样的,共享login的title。so ,在login.service.ts中,

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class LoginService {
  /*共享资源为静态值*/
  //分享title值
  title = 'angular';
  constructor() { }
}

在nav-title.component.ts中,订阅服务

import {Component, OnInit} from '@angular/core';
//加入共享的 LoginService
import { LoginService } from '../../login/login.service';

@Component({
  selector: 'app-nav-title',
  templateUrl: './nav-title.component.html',
  styleUrls: ['./nav-title.component.css']
})
export class NavTitleComponent implements OnInit {
  public title: string;
  constructor(public service: LoginService ) {//订阅service
    console.log(this.service.title);
    this.title = this.service.title;//赋值给nav-title的title
  }
  ngOnInit() {
  }
}

初涉angular之路由

回忆一下Vue的路由

//在template模块中直接路由,类似a标签
 <router-link :to="/prodution">......</router-link>
//在方法中条用路由
this.$router.push({path: '/login'});

在router的index.js中,

//引入依赖模块
import Vue from 'vue'
import Router from 'vue-router'
//引入页面
import login from '@/page/login/login'
Vue.use(Router)

const  router = new Router({
  routes: [
    {
      path: '/',
      name: 'Index',
      component: Index
    },{
      path:'/login',
      name:'login',
      component:login
    }
  ]
})

在angular中,路由与Vue相似,但是存在很大的不同
1.在cli创建时,会提示是否需要路由。


创建命令

输入y,之后会在app.modules.ts引入import { AppRoutingModule } from './app-routing.module'
2.在app-routing.module.ts中,

//模块依赖引入
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
//components
import {LoginComponent} from './login/login/login.component';
import {HomeComponent} from './home/home/home.component';

//routes
const routes: Routes = [
//定义路由跳转
  {path: '', component: LoginComponent},
  {path: 'home', component: HomeComponent}
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

3.在component中,

 <a href="#" routerLink="/user">User</a>

4.在方法中,

import {Component, OnInit, NgZone} from '@angular/core';//路由依赖
import { Router } from '@angular/router';//路由依赖
import { LoginService } from '../login.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  public username: string;
  public password: string;

  constructor(
    public service: LoginService,
    public ngZone: NgZone,//订阅
    public router: Router,//订阅
  ) {
     console.log(this.service.title);
  }

  ngOnInit() {
  }
  loginIn() {
    if (this.username == '123' && this.password == '123') {
      //成功后,跳转home主页
      this.ngZone.run(() => this.router.navigate(['home'])).then();
    }
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容