Angular基础教程+Demo项目 您所在的位置:网站首页 angular甘特图实例 Angular基础教程+Demo项目

Angular基础教程+Demo项目

2023-09-05 06:11| 来源: 网络整理| 查看: 265

第二节预告:生命周期函数、Rxjs、数据请求、路由 学习过程中所写的Demo_GitHub——学习Angular——浅度学习Demo 官网:https://angular.cn/(官网是最好的老师哦,追求技术的大神可以继续深入啦)

Angular前言(跳过即可,自勉而已)

一写博客,不例外的喜欢啰嗦一下,本人是广大java后端开发中的一员,但是因为工作需要不得不利用工作之余学习Angular前端,虽然我对于学习前端技术不反感,但是我更加信奉T型发展,先精后广,后端远远称不上精通,就要走广而多的路子了,就怕以后面试官问我会什么,什么都会一点,深入一些后,什么好像又不会。 不过这也没办法,生活不只是有理想远方,还有眼下的面包和生存,先把工作做好,这也是我所追求的。啰嗦结束,进入正题↓

Angular项目架构介绍

关于如何安装Angular,这个百度太多了,我来个传送门吧 特意提一下创建新项目

ng new demo --skip-install 使用这个命令创建项目的话,是不在创建的过程中下载依赖的,因为ng命令下载依赖的话会比较慢,项目创建成功后,进入项目目录下使用cnpm install 下载依赖即可

项目接口图: 在这里插入图片描述 大概这个意思吧,不常用的话,也记不住这么多,记住几个关键的就可以了。 比如:

src:根目录,存放所有开发的文件; src/app: 存放组件和模块的文件 src/assets: 存放静态资源文件 src/index.html : 入口页面 src/styles.scss :全局样式 package.json:配置依赖文件

还有下图: 在这里插入图片描述 在这里插入图片描述 结构介绍大概就是这样,组件主要是由页面(Html),样式(scss/css/less),业务逻辑(ts)组成,Angular的语法偏向于后台逻辑语法,如果有后台开发技术学习起来应该不难理解

创建一个组件并启动项目

创建组件命令:

ng g component components/header

这个意思是创建一个名叫header的组件,它在components的目录下。 在这里插入图片描述 命令执行完,如上图所示,我们可以看一下Angular最重要的概念——组件的展示效果,打开header.component.ts查看一下组件的名字叫什么?我这边是app-header 在这里插入图片描述 想要看一下这个组件的展示效果,首先在组件的html中输入内容,如下

我是一个头部组件

然后清除app.component.html的全部内容(里边原来的内容是Angular自带的欢迎页面),然后在这个页面中使用组件,如下图 在这里插入图片描述 这样让我们启动项目,因为我使用的是Webstorm,所以直接使用自带的插件就可以启动了,如果快捷启动的话,可以使用命令

ng serve --open

启动Angular项目,效果如下: 在这里插入图片描述

已经展示出来我们组件的内容了,其实Angular很好理解,他的页面就是由一个个组件拼装出来的,他只会启动index.html页面,然后在这个页面中装载根组件,由根组件装载头部组件,这样一个流程

angular html简单语法介绍

Html文件

我是一个头部组件 Angular 数据绑定 {{data}} {{data1}} {{data2}} {{data3}} data4}}--> data5}}--> Angular 属性绑定 Angular 简单数学运算 1+2={{1+2}} Angular 数组循环 {{item}} {{item.name}},{{item.age}}--{{key}} {{item.name}} {{content}} 图片展示 条件判断——ngif,ngswitch ngif 展示: 我是true false ngswitch 展示: 我是1 我是2 --其实我是个不得已的选择--(~_~) class、style展示,[ngClass]/[ngStyle] ngClass 展示: 你在我心中是最美诶! 你在我心中是最美诶! ngStyle 展示: 我是ngStyle-blue 我是ngStyle-yellow 管道 大小写转换管道——lowercase、uppercase {{upper}}转换成小写--{{upper | lowercase}} {{lower}}转换成大写--{{lower | uppercase}} 时间管道——date:'yyyy-MM-dd HH:mm:ss' {{date | date:'yyyy-MM-dd HH:mm:ss'}} 小数管道——参数格式为{最少整数位数}.{最少小数位数}-{最多小数位数},当小数位数少于规定的{最少小数位数 }时,会自动补0,当小数位数多于规定的{最多小数位数}时,会四舍五入 {{num | number:'2.3-4'}} 事件 自定义事件提示 双向数据绑定——MVVM,只针对Form {{keywords}} 改变值 获取值-打印在控制台

TS文件

import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.scss'] }) export class HeaderComponent implements OnInit { // 定义属性、也叫数据 data = '我是一个无情的属性'; // 上边这个属性不可以使用var或者let来定义,它完整的定义方式是 public data1: any = '我是一个无情的属性-完整定义'; // 也就是说默认的是any类型,就是任何类型的意思,当然也可以在定义的时候指定确定的类型,比如string,number等, // 当然我这个下边两个就不写类型了,因为这里边有了TSLint配置,可以自动从上下文推断出类型,你写类型反而认为你的代码多余 public data2 = '我是一个无情的String类型'; data3 = 110; // 以上可以看到,除了类型修饰符以外,还有一个范围权限修饰符,如public,除了这个还有private、protected // public:就是公共数据的意思,可以被其他模块引入使用; // private: 私有数据,只能被本组件使用,当然包括这个组件的页面引用 // protected: 受保护数据,只可以被本组件或子模块所使用,也就是继承这个组件的组件可以使用 private data4 = '我是private 修饰的数据'; protected data5 = '我是protected 修饰的数据'; data6 = '属性绑定'; arr = [ '数组1', '数组2' ]; public arr1: Array = [ {name: '张三', age: 12}, {name: '李四', age: 15} ]; // 嵌套循环 public arr2: Array = [ {name: '品牌', content: ['格力', '小米', '阿里']}, {name: '价格', content: [11, 12, 13]} ]; img = 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3140171551,1885365254&fm=26&gp=0.jpg'; flag = true; choose = 0; col = 'yellow'; upper = 'HELLO'; lower = 'hello'; date = new Date(); num = 100.12345; keywords; constructor() { } ngOnInit(): void { } show1(): void { alert('自定义事件提示'); } down(e): void{ console.log(e.key); if (e.keyCode === 82){ e.target.style.color = 'red'; } } getKeywords(): string{ console.log(this.keywords); return this.keywords; } setKeywords(): void{ this.keywords = '这是改变后的值'; } }

css样式文件

.red{ color:red; } .max{ font-size: 20px; }

上边只是简单的介绍了一些Angular的语法,比如属性绑定,数据绑定,循环、判断、事件、双向数据绑定等,虽然很简单,但是已经包括了大部分基础语法了,建议自己练习一遍,要不可能出现眼高手低的情况

根据上边的内容,写一个简单的MVVM的Demo吧

html文件

Form 双向数据绑定表单Demo 姓 名: 性 别: 男 女 城 市: {{ci}} 爱 好: {{item.name}} ;; 备 注: 获取Form数据 {{payload | json}}

TS文件

import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-form-mvvm', templateUrl: './form-mvvm.component.html', styleUrls: ['./form-mvvm.component.scss'] }) export class FormMVVMComponent implements OnInit { public payload: any = { userName: '', sex: '1', cities: [ '石家庄', '秦皇岛', '北京' ], citys: '1', hobbies: [ { name: '打篮球', checked: false }, { name: '打足球', checked: false }, { name: '游泳', checked: false } ], remark: '' }; constructor() { } ngOnInit(): void { } getPayload(): void { console.log(this.payload); } }

CSS文件

h1{ text-align: center; } form{ border:5px solid #6d6a6a; } .center{ text-align: center; } .left{ text-align: left; } 一,Anuglar中Service(服务)

Service在Angular中是服务的概念,因为Angular中组件之间是不能互相调用方法的,所以对于一些公共方法,我们需要存放在一个地方,这时候就出现了服务的概念,就是将一些公共的方法存放到Service,这样其他组件就可以调用了 下面我们通过一个Demo来看一下服务的简单使用方法: 组件 Html

todoList 这个组件主要讲解service、localStorage以及灵活ngModule的运行 在Angular中,组件之间方法不可以互相引用(父子组件可以传值通讯),但是组件可以引用其他service(服务)的方法,创建service的命令 ng g service services/dataStorage 以下,简单写了一个针对于service案例的简单逻辑,将数据的值存储在localStorage中,还利用了ngModule实现了列表数据的动态刷新 添加事项 待办事件 {{it.title}}-----× 已办事件 {{it.title}}-----×

TS

import { Component, OnInit } from '@angular/core'; import {DataStorageService} from '../../services/data-storage.service'; @Component({ selector: 'app-service', templateUrl: './service.component.html', styleUrls: ['./service.component.scss'] }) export class ServiceComponent implements OnInit { public item: any; public items: any[] = []; constructor(public storage: DataStorageService) { } ngOnInit(): void { // tslint:disable-next-line:prefer-const let lists: any = this.storage.get('items'); if (lists){ this.items = lists; } } public pushItems(e): void{ if (e !== null && e.keyCode !== 13){ return; } this.items.push({ title: this.item, checked: false }); this.item = ''; this.storage.set('items', this.items); } clickCheck(key): void{ console.log(this.items[key]); this.items[key].checked = !this.items[key].checked; this.storage.set('items', this.items); } removeItems(key): void{ this.items.splice(key, 1); this.storage.set('items', this.items); } }

CSS

h1{ text-align: center; } .center{ margin-left: 40%; hr{ margin-left: -120%; } }

Service 服务 TS业务逻辑

import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class DataStorageService { constructor() { } set(key: string, value: any): void{ localStorage.setItem(key, JSON.stringify(value)); } get(key: string): any{ return JSON.parse(localStorage.getItem(key)); } remove(key: string): void{ localStorage.removeItem(key); } }

我们需要将服务引入配置到app.module.ts中

// 这个是Angular根模块,告诉Angular如何组装应用 // BrowserModule 是浏览器解析模块 import { BrowserModule } from '@angular/platform-browser'; // NgModule 核心模块 import { NgModule } from '@angular/core'; // 路由模块 import { AppRoutingModule } from './app-routing.module'; // 双向数据绑定 form import {FormsModule} from '@angular/forms'; // 根组件 import { AppComponent } from './app.component'; import { HeaderComponent } from './components/header/header.component'; import { FormMVVMComponent } from './components/form-mvvm/form-mvvm.component'; import { LogicComponent } from './components/logic/logic.component'; import { ServiceComponent } from './components/service/service.component'; // 引入服务 import {DataStorageService} from './services/data-storage.service'; // @NgModule装饰器,@NgModule接受一个元数据对象,告诉Angular如何编译和启动应用 @NgModule({ // 配置当前项目运行的组件 declarations: [ AppComponent, HeaderComponent, FormMVVMComponent, LogicComponent, ServiceComponent ], // 配置当前项目运行依赖的其他模块 imports: [ BrowserModule, AppRoutingModule, FormsModule ], // 配置当前项目所需要的服务 providers: [DataStorageService], // 指定应用的主视图(根组件),通过引导AppModule来启动应用, bootstrap: [AppComponent] }) // 对外暴露的模块,不过根模块不需要配置 export class AppModule { }

可以看到在providers中配置了刚刚创建的服务,这样服务就创建好了,这个Demo也可以启动起来试一下

二、父子组件之间互相通讯

上面有提到两个组件是不能通讯,一般通讯都是通过服务service进行的,但是有一种情况除外,那就是父子组件,他们是可以互相通讯的。 父子组件:其实就一个在一个组件的html中内嵌了其他的组件,他们构成父子关系 下面通过一个Demo案例来看一下父子组件的传值过程:

子组件: HTMl页面

我是子组件 显示父组件数据 调用父组件方法 通过Output向父组件传播数据

TS逻辑文件

import { Component, OnInit, ViewChild, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-login-child', templateUrl: './login-child.component.html', styleUrls: ['./login-child.component.scss'] }) export class LoginChildComponent implements OnInit { // 获取dom元素 @ViewChild('myChild') myChild: any; @ViewChild('parent') parent: any; @ViewChild('parentMethod') parentMethod: any; dataChild: any = '我是子组件的数据'; // 获取父组件的值和方法 @Input() dataParent: any; @Input() methodParent: any; // 定义事件驱动 @Output() outer: any = new EventEmitter(); constructor() { } ngOnInit(): void { } run(): void{ this.myChild.nativeElement.innerHTML = '触发了子组件的run()方法!'; } showDataParent(): void{ this.parent.nativeElement.innerHTML = this.dataParent; } callMethodParent(): void{ this.parentMethod.nativeElement.innerHTML = this.methodParent(); } transferParent(): void{ this.outer.emit('通过@Output传播过来的子组件数据'); } }

CSS

h1{ text-align: center; }

父组件: HTML文件

logic works! This is ngOnInit--1 This is ngOnInit--2 This is ViewChild--001 触发子组件方法 显示子组件数据

TS文件:

import { Component, OnInit, AfterViewInit, ViewChild } from '@angular/core'; @Component({ selector: 'app-logic', templateUrl: './logic.component.html', styleUrls: ['./logic.component.scss'] }) export class LogicComponent implements OnInit { public flag = true; // 通过@ViewChild 获取dom节点 @ViewChild('myChild') myChild: any; @ViewChild('child') child: any; // 获取子组件元素 @ViewChild('childComponent') childComponent: any; // 子组件通过@Output传播过来的数据 outputTran: any; dataParent: any = '我是父组件的数据'; constructor() { } // 组件和指令初始化完成,并不是正在的页面加载完成 ngOnInit(): void { // 可获取dom节点 const div1: any = document.getElementById('div1'); console.log(div1.innerHTML); // 设置了Angular指令,js原生获取不到dom节点 /*const div2: any = document.getElementById('div2'); console.log(div2.innerHTML);*/ } // 视图加载成功以后触发的方法,dom加载完成,一般将对dom操作放到这个生命周期函数中 // tslint:disable-next-line:use-lifecycle-interface ngAfterViewInit(): void{ const div2: any = document.getElementById('div2'); console.log(div2.innerHTML); // 设置元素样式 this.myChild.nativeElement.style.fontSize = '100px'; } // 调用子组件方法 getChildComponent(): void{ this.childComponent.run(); } methodParent(): any{ return '调用了父组件的方法'; } // 获取子组件数据 showDataChild(): void{ this.child.nativeElement.innerHTML = this.childComponent.dataChild; } // 显示子组件Output传播过来的数据 setOutputTran(e): void{ this.outputTran = e; } }

案例大概就是上边这样的,上边不只有父子组件的通讯方法,还有@ViewChild的使用,下面简单讲一下父子传值的方法

父组件调用子组件方法/数据:

这个是有两种方法的,分别是@ViewChild以及@Output,这其中@ViewChild使用起来更加方便,下面分别介绍 **@ViewChild:**这个方法相对于@Output来说最大的区别是主动的关系,它是主动调用子组件的,而@Output更像是一种被动接受子组件的数据及方法,而且@ViewChild最主要的作用是获取dom节点,但是当它获取的是子组件的dom节点时即可调用子组件的数据和方法。使用方法也比较简单,就是在dom节点处预先定义它的ID,然后通过装饰器@ViewChild去绑定它,如下

This is ViewChild--001 // TS // 通过@ViewChild 获取dom节点 @ViewChild('myChild') myChild: any;

如上,关于如何使用dom节点、如何调用子组件方法、数据,上边demo已经有简单的案例,就不重复写了

@Output:@Output需要配合事件驱动EventEmitter来使用,它是向父组件去推送广播信息,由父组件接受,也就是使用这种方法主动方其实是子组件(个人描述),这个相对复杂一些,所以使用起来肯定选择简单的多一些,这里简单介绍 子组件传播:

// 引入相关包 import { Component, OnInit, ViewChild, Input, Output, EventEmitter } from '@angular/core'; // 定义事件驱动 @Output() outer: any = new EventEmitter(); // 传输数据 transferParent(): void{ this.outer.emit('通过@Output传播过来的子组件数据'); }

父组件接收:

// 显示子组件Output传播过来的数据 setOutputTran(e): void{ this.outputTran = e; }

将HTML和TS写到了一起,不过相信也不难看懂,就没有分开,这里需要注意的是,(outer)="setOutputTran($event)"中的 outer一定要和子组件的属性名保持一致,否则是不行的,然后触发了子组件的transferParent()方法才会传递过来值到父组件的方法中,$event达标的就是那个值

子组件调用父组件方法/数据:

这里就简单了,只有一种方法,那就是@Input()方法,父组件在引用子组件的使用传入数据和方法,子组件通过@Input()来接受,根据情况进行使用,简单的使用如下 子组件:

// 引入@Input import { Component, OnInit, ViewChild, Input } from '@angular/core'; // 获取父组件的值和方法 @Input() dataParent: any; @Input() methodParent: any;

父组件:

这些简单的调用都是在上边写的Demo中截取的,如果想要了解更加深入,建议也建立一个demo练习一下,理解还是很不一样的,最好多参考几篇博客,毕竟一个人的理解是有限的,有可能出现漏掉比较关键的知识点。

结语

这篇就暂时写到这里,就不写太长了,不是太好阅读,这篇博客是我利用周一到周五晚上九点到十二点的时间写的,这段时间接触下来感觉Angular毕竟是一个封装比较全面的前端框架,如果是一个后端只是希望可以达到简单使用的层次的话(就像我),还是比较简单的。所以我打算利用两篇博客来完成Angular总结介绍,明天周六日两天,足够写完Angular第二节博客,有兴趣的请关注! 第二节预告:生命周期函数、Rxjs、数据请求、路由 学习过程中所写的Demo_GitHub——学习Angular——浅度学习Demo 官网:https://angular.cn/(官网是最好的老师哦,追求技术的大神可以继续深入啦)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有