构建项目
| |
| npm install -g @angular/cli |
| |
| ng new angular01 |
| |
| |
| |
| cd angular01 |
| |
| npm install |
| |
| ng serve -o |
目录结构
| node_modules 第三方依赖包存放目录 |
| e2e 端到端的测试目录 用来做自动测试的 |
| src 应用源代码目录 |
| .angular-cli.json Angular命令行工具的配置文件。后期可能会去修改它,引一些其他的第三方的包 比如jquery等 |
| karma.conf.js karma是单元测试的执行器,karma.conf.js是karma的配置文件 |
| package.json 这是一个标准的npm工具的配置文件,这个文件里面列出了该应用程序所使用的第三方依赖包。实际上我们在新建项目的时候,等了半天就是在下载第三方依赖包。下载完成后会放在node_modules这个目录中,后期我们可能会修改这个文件。 |
| protractor.conf.js 也是一个做自动化测试的配置文件 |
| README.md 说明文件 |
| tslint.json 是tslint的配置文件,用来定义TypeScript代码质量检查的规则,不用管它 |
| app目录 包含应用的组件和模块,我们要写的代码都在这个目录 |
| assets目录 资源目录,存储静态资源的 比如图片 |
| environments目录 环境配置。Angular是支持多环境开发的,我们可以在不同的环境下(开发环境,测试环境,生产环境)共用一套代码,主要用来配置环境的 |
| index.html 整个应用的根html,程序启动就是访问这个页面 |
| main.ts 整个项目的入口点,Angular通过这个文件来启动项目 |
| polyfills.ts 主要是用来导入一些必要库,为了让Angular能正常运行在老版本下 |
| styles.css 主要是放一些全局的样式 |
| tsconfig.app.json TypeScript编译器的配置,添加第三方依赖的时候会修改这个文件 |
| tsconfig.spec.json 不用管 |
| test.ts 也是自动化测试用的 |
| typings.d.ts 不用管 |
| src\app\app.component.html |
| src\app\app.component.less |
| src\app\app.component.ts |
| src\app\app.module.ts |
| |
| import { NgModule } from '@angular/core'; |
| |
| import { BrowserModule } from '@angular/platform-browser'; |
| |
| import { AppRoutingModule } from './app-routing.module'; |
| |
| import { AppComponent } from './app.component'; |
| @NgModule({ |
| declarations: [ |
| AppComponent |
| ], |
| imports: [ |
| BrowserModule, |
| AppRoutingModule |
| ], |
| providers: [], |
| bootstrap: [AppComponent] |
| }) |
| export class AppModule { } |
| |
| import { Component } from '@angular/core'; |
| @Component({ |
| selector: 'app-root', |
| templateUrl: './app.component.html', |
| styleUrls: ['./app.component.less'] |
| }) |
| export class AppComponent { |
| title = 'angular01'; |
| } |
新建子组件
- 初始化项目:删除app.component.html中的默认代码
| <style> |
| </style> |
| |
| <div> |
| 这是根组件 |
| </div> |
| |
| <router-outlet></router-outlet> |
| |
| ng g |
| |
| ng g component components/news |
| |
| |
| |
| import { NewsComponent } from './components/news/news.component'; |
| @NgModule({ |
| declarations: [ |
| NewsComponent |
| ] |
| }) |
| |
| |
| @Component({ |
| selector: 'app-news', |
| templateUrl: './news.component.html', |
| styleUrls: ['./news.component.less'] |
| }) |
| |
| |
| <app-news></app-news> |
模板合成
| |
| export class NewsComponent implements OnInit { |
| |
| |
| public title: string="我是一个新闻组件"; |
| |
| |
| public userinfo: Object ={ |
| name:"张山", |
| age:20 |
| }; |
| |
| |
| constructor() { |
| this.title="这是改变后的值"; |
| } |
| } |
| |
| |
| <span>{{title}}</span> |
| <span>{{userinfo}}</span> |
| // news.component.ts中 |
| export class NewsComponent implements OnInit { |
| |
| public baidu: string="www.baidu.com"; |
| } |
| |
| // news.component.html中 |
| <h2>属性绑定</h2> |
| <p title="这是title">baidu_0</p> |
| <p [title]="baidu">baidu_1</p><br> |
| <a [href]="baidu">baidu_2</a><br> |
| // news.component.ts中 |
| export class NewsComponent implements OnInit { |
| |
| // html绑定 |
| public content: string="<h2>这是一段文本!!</h2>" |
| public content2:string=` |
| <span>title</span> |
| <p>p2</p> |
| ` |
| } |
| |
| // news.component.html中 |
| <h2>绑定html</h2> |
| <p>{{content}}</p> |
| <p [innerHTML]="content"></p> |
| <p [innerHTML]="content2"></p> |
| <h2>简单运算</h2> |
| <p>333+555={{333+555}}</p> |
| export class NewsComponent implements OnInit { |
| // 数组循环 |
| public arr=["ass", "dsdsa", "asdf"]; |
| public list: string[]=["asdfasd", "asdfasd", "asdfasdf", "adsfasd"]; |
| public items:Array<string>=["asd", "asdf", "1324"]; |
| public userList:object[]=[{username:"user", password: "123456"},{username: "user2", password: "1234567"}] |
| } |
| |
| <h2>数据循环</h2> |
| <ul> |
| <li *ngFor="let item of arr"> |
| {{item}} |
| </li> |
| </ul> |
| <p>-------</p> |
| <ul> |
| <li *ngFor="let item of list"> |
| {{item}} |
| </li> |
| </ul> |
| <p>-------</p> |
| <ul> |
| <li *ngFor="let item of items"> |
| {{item}} |
| </li> |
| </ul> |
| <p>-------</p> |
| <ul></ul> |
| <li *ngFor="let item of userList"> |
| {{item.username}} |
| </li> |
组件合成
- 新建子组件home,以下操作在home组件中完成
- 引入图片
| |
| public picUrl:string="https://tse4-mm.cn.bing.net/th/id/OIP-C.uPx-FbZ4nf2U05kCoJ7_1QHaE8?w=299&h=197&c=7&r=0&o=5&dpr=1.24&pid=1.7"; |
| |
| |
| <span><img src="assets/images/OIP-C.jpg"></span><br> |
| <p>引入图片方式二</p> |
| <img [src]="picUrl"> |
| |
| public list: any[]=[ |
| {"title":'新闻一'},{"title":'新闻二'},{"title":'新闻三'} |
| ] |
| |
| |
| <ul> |
| <li *ngFor="let item of list; let key=index"> |
| {{key}}----{{item.title}} |
| </li> |
| </ul> |
| public flag:boolean=false; |
| |
| |
| <div *ngIf="flag"> |
| <img src="assets/images/OIP-C.jpg"> |
| </div> |
| <div *ngIf="!flag"> |
| <img [src]="picUrl"> |
| </div> |
| |
| public orderStatus:number=1; |
| |
| |
| <span [ngSwitch]="orderStatus"> |
| <p *ngSwitchCase="1">已经支付</p> |
| <p *ngSwitchCase="2">未支付</p> |
| <p *ngSwitchCase="3">已收货</p> |
| <p *ngSwitchCase="4">为收货</p> |
| </span> |
| |
| public flag:boolean=false; |
| |
| |
| .red{ |
| color: red; |
| } |
| .blue{ |
| color: blue; |
| } |
| .yellow{ |
| color: yellow; |
| } |
| |
| |
| <!-- 类名class1为true表示使用该样式 --> |
| <div [ngClass]="{'class1':true, 'class2':false}"></div> |
| <!-- flag为home.component.ts中定义的boolean类型 --> |
| <div [ngClass]="{'class3':flag, 'class4':!flag}"></div> |
| <ul> |
| <li *ngFor="let item of list; let key=index;" [ngClass]="{'red': key==1, 'blue': key==2}"> |
| {{key}}----{{item.title}} |
| </li> |
| </ul> |
| |
| public attr: string='red'; |
| |
| .red{ |
| color: red; |
| } |
| |
| <p [ngStyle]="{'color':'red'}">这是一段文本</p> |
| <p [ngStyle]="{'color':attr}">这是一段文本2</p> |
| |
| public today: any=new Date(); |
| |
| <span>未转换 -> </span>{{today}} |
| <br> |
| <span>转换后 -> </span>{{today | date:'yyyy-mm-dd HH-mm-ss'}} |
| |
| |
| run(){ |
| alert("hello!!"); |
| } |
| |
| getData(){ |
| alert(this.picUrl); |
| } |
| |
| public title: string="asdf"; |
| |
| setData(){ |
| this.title="sadfasdf" |
| } |
| |
| |
| runEvent(e){ |
| var dom: any = e.target; |
| dom.style.color='red'; |
| dom.style.height='200px'; |
| } |
| <button (click)="run()">点击1</button> |
| <br> |
| |
| <button (click)="getData()">点击1</button> |
| <br> |
| |
| data:{{title}} |
| <button (click)="setData()">点击2</button> |
| <br> |
| <br> |
| <button (click)="runEvent($event)">点击获取事件对象</button> |
| |
| keyDown(e){ |
| if(e.keyCode==13){ |
| console.log("按了回车") |
| }else{ |
| console.log(e.target.value) |
| } |
| } |
| |
| keyUp(e){ |
| if(e.keyCode==13){ |
| console.log(e.target.value) |
| console.log("按了回车") |
| } |
| } |
| |
| |
| 键盘按下<input type="text" (keydown)="keyDown($event)"/> |
| 键盘松开<input type="text" (keyup)="keyUp($event)"> |
| Error: src/app/components/home/home.component.ts:50:11 - error TS7006: Parameter 'e' implicitly has an 'any' type. |
| |
| 50 keyDown(e){ |
| |
| import { FormsModule } from '@angular/forms'; |
| @NgModule({ |
| imports: [ |
| FormsModule |
| ], |
| }) |
| |
| |
| public keywords: any; |
| |
| |
| <input type="text" [(ngModel)]='keywords'/> |
| <br>{{keywords}} |
| Property 'keywords' does not exist on type 'HomeComponent'. |
| |
| 76 <br>} |
表单双向绑定
| export class FormComponent implements OnInit { |
| |
| public people: any = { |
| username: '', |
| sex: '1', |
| cityList: ['shanghai', 'beijing', 'chongqing'], |
| city: 'shanghai', |
| hobby: [ |
| {title: 'lanqiu', checked: false},{title: 'cang', checked: false},{title: 'tiao', checked: false} |
| ], |
| mark: '' |
| } |
| } |
| <p>文本框双向绑定</p> |
| <input type="text" [(ngModel)]="people.username"> |
| <br>{{people.username}} |
| <p>单选框双向绑定</p> |
| <input type="radio" value="1" [(ngModel)]="people.sex"> |
| <input type="radio" value="2" [(ngModel)]="people.sex"><br> |
| <br>{{people.sex}} |
| <p>下拉列表双向绑定</p> |
| <select [(ngModel)]="people.city"> |
| <option *ngFor="let item of people.cityList" [value]="item">{{item}}</option> |
| </select> |
| <br>{{people.city}} |
| <p>多选框双向数据绑定</p> |
| <span *ngFor="let item of people.hobby, let key=index"> |
| <input type="checkbox" id="check+'key'" [(ngModel)]="item.checked">{{item.title}}--{{item.checked}} |
| </span> |
| <br> |
| <p>文本域双向数据绑定</p> |
| <textarea [(ngModel)]="people.mark"></textarea> |
| <br>{{people.mark}} |
搜索框历史功能
| <div class="search"> |
| |
| <input type="text" [(ngModel)]="keyword" placeholder="Search"> |
| |
| <button type="button" (click)="doSearch()">search</button> |
| <br> |
| <div class="historyList"> |
| |
| <li *ngFor="let item of historyList; let key=index;"> |
| {{item}}<span (click)="deleteHistory(key)" class="del">X</span> |
| </li> |
| </div> |
| </div> |
| |
| public keyword: string; |
| |
| public historyList: any[] = []; |
| |
| doSearch(){ |
| if(this.historyList.indexOf(this.keyword)==-1){ |
| this.historyList.push(this.keyword); |
| } |
| this.keyword=''; |
| } |
| |
| deleteHistory(key){ |
| |
| this.historyList.splice(key, 1); |
| } |
事项清单
| <div class="todolist"> |
| |
| <input type="text" placeholder="Search" [(ngModel)]="keyword" (keyup)="doAdd($event)"> |
| <hr> |
| <div class="historyList"> |
| <p>待办事项</p> |
| <div class="history"></div> |
| |
| <div class="his" *ngFor="let item of todolist; let key=index;" [hidden]="item.status==1"> |
| |
| <input type="checkbox" [(ngModel)]="item.status" class="inp"> |
| {{item.title}} |
| <span class="del" (click)="delete(key)">x</span> |
| </div> |
| </div> |
| </div> |
| <div class="todos"> |
| <p>已完成事项</p> |
| <div class="todo2"> |
| |
| <div class="todo" *ngFor="let item of todolist; let key=index;" [hidden]="item.status==0"> |
| |
| <input type="checkbox" [(ngModel)]="item.status" class="inp"> |
| {{item.title}} |
| <span class="del" (click)="delete2(key)">x</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| export class TodolistComponent implements OnInit { |
| |
| public keyword: string; |
| |
| public todolist: any[] = [{title: 'vuejs', status: 0}]; |
| |
| doAdd(e){ |
| if(e.keyCode==13){ |
| this.todolist.push({title: this.keyword, status: 0}); |
| this.keyword=''; |
| } |
| } |
| |
| delete(key){ |
| this.todolist.splice(key,1); |
| } |
| |
| delete2(key){ |
| this.todolist.splice(key,1); |
| } |
| } |
angular服务
- angular是基于组件化的开发,一个组件不能调用另一个组件中方法,这时需要把公共的方法或数据放到angular服务中,这样所有的组件都可以调用服务中的方法和数据,类型于vuex
- 使用步骤1(不推荐):
| |
| ng g service services/storage |
| |
| import { StorageService } from './service/storage.service'; |
| @NgModule({ |
| providers: [StorageService], |
| }) |
| |
| export class StorageService { |
| get(){ |
| console.log("这是一个公共方法!"); |
| } |
| } |
| |
| import { StorageService } from '../../service/storage.service'; |
| var storage = new StorageService; |
| export class SearchComponent implements OnInit { |
| constructor() { |
| |
| console.log(storage) |
| } |
| } |
| |
| ng g service services/storage |
| |
| import { StorageService } from './service/storage.service'; |
| @NgModule({ |
| providers: [StorageService], |
| }) |
| |
| export class StorageService { |
| get(){ |
| console.log("这是一个公共方法!"); |
| } |
| } |
| |
| import { StorageService } from '../../service/storage.service'; |
| export class SearchComponent implements OnInit { |
| constructor( public storage: StorageService) { |
| let s= this.storage.test(); |
| console.log(s); |
| } |
| } |
案例:服务中编写公共方法
| export class StorageService { |
| |
| set(key: string, value: any){ |
| localStorage.setItem(key, JSON.stringify(value)); |
| } |
| |
| get(key: string){ |
| return localStorage.getItem(key); |
| } |
| |
| remove(key: string){ |
| localStorage.removeItem(key); |
| } |
| } |
- 在search.component.ts中使用
- 在ts组件中ngOnInit方法会在每次刷新时触发
| import { StorageService } from '../../service/storage.service'; |
| |
| export class SearchComponent implements OnInit { |
| ngOnInit(): void { |
| console.log("刷新页面时会触发该周期函数") |
| |
| var searchlist: any= this.storage.get('searchlist'); |
| if(searchlist){ |
| this.historyList=searchlist; |
| console.log("获取成功") |
| } |
| |
| |
| |
| } |
| |
| doSearch(){ |
| if(this.historyList.indexOf(this.keyword)==-1){ |
| this.historyList.push(this.keyword); |
| |
| this.storage.set('searchlist', this.historyList); |
| console.log("添加成功") |
| } |
| this.keyword=''; |
| } |
| } |
dom节点操作
| |
| <div id="box">这是一个盒子!</div> |
| |
| |
| ngOnInit(): void { |
| let box: any= document.getElementById('box'); |
| console.log("dom" + box.innerHTML); |
| box.style.color="blue"; |
| } |
| |
| <div id="box2" *ngIf="flag">这是一个盒子!</div> |
| |
| |
| ngAfterViewInit(): void { |
| let box2: any= document.getElementById('box2'); |
| console.log("dom" + box2.innerHTML); |
| box2.style.color="red"; |
| } |
| |
| <div #box3 *ngIf="flag" >这是一个盒子!</div> |
| |
| |
| import { ViewChild } from '@angular/core'; |
| export class DomComponent implements OnInit { |
| public flag: boolean = true; |
| |
| |
| @ViewChild('box3') box3: any; |
| |
| ngAfterViewInit(): void { |
| |
| console.log("box3" + this.box3.nativeElement); |
| this.box3.nativeElement.style.color="red"; |
| } |
| } |
| |
| |
| <app-form #form></app-form> |
| |
| |
| import { ViewChild } from '@angular/core'; |
| export class DomComponent implements OnInit { |
| |
| @ViewChild('form') form: any; |
| |
| ngAfterViewInit(): void { |
| |
| console.log("form -> " + this.form.run()); |
| } |
| } |
实现一个侧边栏
| |
| <div id="content"> |
| 内容区<br> |
| <button (click)="showAside()">弹出侧边栏</button> |
| <button (click)="hiddenAside()">隐藏侧边栏</button> |
| </div> |
| <div id="aside"> |
| 侧边栏 |
| </div> |
| |
| |
| body{ |
| width: 100%; |
| overflow-x: hidden; |
| } |
| |
| |
| export class TransitionComponent implements OnInit { |
| showAside(){ |
| var asideDom = document.getElementById('aside'); |
| asideDom.style.transform = "translate(0,0)"; |
| } |
| hiddenAside(){ |
| var asideDom = document.getElementById('aside'); |
| asideDom.style.transform = "translate(100%,0)"; |
| } |
| } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体
2022-09-22 使用栈实现综合计算器
2022-09-22 栈
2022-09-22 约瑟夫问题(二)
2022-09-22 约瑟夫问题(一)
2022-09-22 双向链表
2022-09-22 单链表(三)
2022-09-22 单链表(二)