You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import{Injectable}from'@angular/core';import{Todo}from'./todo';
@Injectable()exportclassTodoService{// Placeholder for todo'stodos: Todo[]=[];/** Used to generate unique ID's */nextId=0;constructor(){}// Simulate POST /todosaddTodo(todo: Todo): TodoService{todo.id=Date.now();this.todos.push(todo);returnthis;}// Simulate DELETE /todos/:iddeleteTodoById(id: number): TodoService{this.todos=this.todos.filter(todo=>todo.id!==id);returnthis;}// Simulate POST /todos/deletedeleteAllTodo(): TodoService{this.todos=this.todos.filter(todo=>!todo.done);returnthis;}// Simulate PUT /todos/:idupdateTodoById(id: number,values: Object={}): Todo{consttodo=this.getTodoById(id);if(!todo){returnnull;}Object.assign(todo,values);returntodo;}// Simulate GET /todosgetAllTodos(): Todo[]{returnthis.todos;}// Simulate GET /todos/donegetAllDoneTodos(): Todo[]{returnthis.todos.filter(todo=>todo.done);}// Simulate GET /todos/:idgetTodoById(id: number): Todo{returnthis.todos.filter(todo=>todo.id===id).pop();}// Toggle todo donetoggleTodoDone(todo: Todo){constupdatedTodo=this.updateTodoById(todo.id,{done: !todo.done});returnupdatedTodo;}}
<divclass="view" *ngIf="!todo.edit"><inputclass="toggle" type="checkbox" [checked]="todo.done" (click)="toggleDoneTodo(todo)"><buttonclass="destroy" (click)="destroyTodo(todo)"></button></div><inputclass="edit" *ngIf="todo.edit" appAfterViewFocus[value]="todo.value" #edit(blur)="cancelEditingTodo(todo)" placeholder="What do you need to write?" (keyup.enter)="editedTodo(todo, edit)">
/** * add todo * @memberof TodoAppComponent */addTodo(): void{if(!this.newTodo){returnalert('What do you need to write?');}this.todoService.addTodo(newTodo({value: this.newTodo}));this.newTodo='';}/** * destroy todo * @memberof TodoAppComponent */destroyTodo(todo: Todo): void{this.todoService.deleteTodoById(todo.id);}/** * destroy done todo * @memberof TodoAppComponent */destroyAllTodo(): void{if(!this.clearCount){return;}if(!confirm('Do you need to delete the selected one?')){return;}this.todoService.deleteAllTodo();}/** * toggle todo done * @memberof TodoAppComponent */toggleDoneTodo(todo: Todo): void{this.todoService.toggleTodoDone(todo);}/** * toggle all todo done * @memberof TodoAppComponent */toggleAllTodoDone(event: boolean): void{this.todos.forEach(item=>item.done=event);}/** * editing todo * @memberof TodoAppComponent */editingTodo(todo: Todo): void{if(!todo.done){todo.edit=true;}}/** * cancel editing todo * @memberof TodoAppComponent */cancelEditingTodo(todo: Todo): void{todo.edit=false;}/** * edited todo * @memberof TodoAppComponent */editedTodo(todo: Todo,input: HTMLInputElement): void{todo.value=input.value;todo.edit=false;}/** * get todos * @memberof TodoAppComponent */gettodos(): Todo[]{returnthis.todoService.getAllTodos();}/** * get todos all done be get todos * @memberof TodoAppComponent */getallDone(): boolean {consttodos=this.todos;returntodos.length&&todos.filter(item=>item.done).length===todos.length;}/** * get todos all not done number * @memberof TodoAppComponent */gettodoCount(): number {returnthis.todos.filter(item=>!item.done).length;}/** * get todos all done number * @memberof TodoAppComponent */getclearCount(): number {returnthis.todos.filter(item=>item.done).length;}
五一假期过后,Angular6发布正式版,相关联的UI组件库Material 和 脚手架CLI,也一并发布6。
升级核心依赖:
工作中已经完成一个Angular6项目,这里来写一个简单的Angular6教程。
古语云:君子谋而后动,三思而后行。我们做一个功能,先规划功能细节。
先看个效果图:
在本文中,我们将构建一个Angular6 Todo web应用程序,允许用户:
这是一个演示应用程序,我们将一步步从零构建它们。
这里所有的代码都是公开的,所以你可以使用这些代码。
这是一个在线编辑器预览
让我们开始吧!
快速开始
这里看官网文档 快速开始。详细安装指南,这里不在一一介绍。
修改一下
package.json
这样可以直接使用
npm start
启动开发服务器并且自动打开默认浏览器并访问http://localhost:4200/
。生成我们的Todo应用程序
现在我们有了
Angular-CLI
,我们可以使用它来生成Todo应用程序:生成我们的Todo应用程序
这里是生成项目的文档
说明:生成一个
angular-todolist
项目,css预处理器用scss。生成文件
满足我们的Todo应用程序的需要,我们需要:
我们所有相关应用都放在todoApp组件,在app组件里面使用todoApp组件。
这里是生成文件的文档
生成组件
这样在app文件夹里面就出现todo-app文件夹
生成服务
注意:默认生成的文件都是以
app
为开始路径,我们需要放在todo-app
里,所以是todo-app/todo
生成类
注意:生成组件是
c
,生成类是cl
。生成指令
我们现在的
todo-app
文件夹里结构应该是:创建Todo类
因为我们使用TypeScript,我们可以使用一个类来表示Todo项目。
让我们打开
src/app/todo.ts
并将其内容替换为:我们需要设计数据结构,每个Todo项有三个属性:
构造函数逻辑允许我们在实例化过程中指定属性值:
我们可以测试一下,
Angular-CLI
提供单元测试和e2e测试,默认生成类文件不会带测试文件,我们需要手动创建一个todo.spec.ts
文件。为了验证我们的代码是否按预期工作,我们现在可以运行单元测试:
npm test
这将执行业力来运行所有单元测试。如果单元测试失败,可以联系我。
现在我们有了一个Todo类,让我们创建一个Todo服务来为我们管理所有的Todo项。
创建Todo服务
TodoService将负责管理我们的Todo项目。
在以后的文章中,我们将看到如何与
REST API
通信,但是现在我们将把所有数据存储在内存存储中。现在,我们可以将todo管理逻辑添加到
src/app/todo.services.ts
中的TodoService中我们已经完成必备的服务,实际的实现细节的方法不是本文的目的所必需的。这是主要表达意思, 我们的业务逻辑集中在服务。
确保我们的逻辑是预期,我们将单元测试添加到
src/app/todo.service.spec
中。Angular-cli已为我们生成测试模板,我们只需要关心如何实现测试:
检查我们的业务逻辑是否有效,我们运行单元测试:
npm test
好了,现在我们有一个可以通过测试的TodoService,是时候实现应用程序的主要部分了。
创建TodoApp组件
组件是
Angular
最小的单元了,整个Angular
应用就是一个颗组件树构成。我们生成项目时候,angular-cli默认为我们创建了
app-root
根组件,我们现在生产的app-todo-app
,放到app.component.html
里面,删除其他html。一个组件是有3部分组建成:
模板和样式也可以内联脚本文件中指定。Angular-CLI默认创建单独的文件,所以在本文中我们将使用单独的文件。
我们先来添加组件的视图
todo-app.component.html
来简单说一下Angular模板语法:
更多的Angular模板语法,你应该阅读官方的文档模板的语法。
让我们一一介绍:
整个模板分为3个结构块:
header,main,footer
;先说输入创建一个新的待办事项:
接下来是一段显示待办事项:
在这个部分中,我们循环一个元素来显示每个待办事项:
最后我们显示待办事项的细节为每个ngFor中的待办事项:
appAfterViewFocus是angular属性型指令,在 Angular 中有三种类型的指令:
注意: 为什么要写这个指令,它作用是什么?它作用是当编辑时,input出现时候,自动获取焦点,不用用户再次去点击输入框,触发获取焦点事件,还有一个更重要的原因,如果没有焦点,失去焦点事件就无法执行,这样输入就不会被隐藏。它的写法很简单:
.nativeElement
拿到就是一个HTMLElement
, 这里是input这个dom。#edit
是angular模板引用变量;注意: 这里拿到就是input这个dom,我们可以直接操作获取它上面的属性和方法。
为什么不用双向绑定
[(ngModel)]
?什么是双向绑定: 数据模型(Module)和视图(View)之间的双向绑定。
如果使用双向绑定,我们修改以后,我们数据就直接跟着一起被修改,那么我们要操作取消操作怎么办,增加一个临时的属性来记录它,取消时候就直接回滚,确认就直接清除这个临时属性。
如果不使用双向绑定,我们先赋值给视图,视图修改以后,我们的数据还没有变,取消操作直接取消就行,确认操作,拿到dom引用,把dom的值去更新数据。
关于全选效果
我们来说最后一块统计结构:
clear-operate
模板我们已经介绍完,关于css不是我们重点,这里忽略讲解。
接下来我们该介绍
todo-app.component.ts
:首先需要引入依赖
接下来就是angular特色之一依赖注入,这里不过多介绍。
注意:providers可以在模块下,也可以在组件里,这也限定他们使用范围。模块里面注册,适用于该模块下所有的组件,服务,指令等;组件里面注册,只适用于当前组件和子组件。
每当视图中输入值的变化,更新组件实例的价值。当组件实例中的值改变,视图中输入元素中的值的变化。
接下来,我们实现我们在视图中使用的所有方法。
newTodo
属性值注意:无论是服务还是组件里,都是需要熟练使用原生数据操作方法,比如数组,对象,字符串等。这里主要使用数组相关方法,如果你对这些还不熟,请赶紧去提升一下。es6以后又新增很多方法,操作数据会更方便。angular是数据驱动,如果不会玩转操作,基本很难继续下去。
功能很小,应该不言自明todoService我们代表所有的业务逻辑。
委派业务逻辑服务是良好的编程实践,因为它能让我们集中管理和测试业务逻辑。
我们还为大家编写一个
E2E
测试用例,可以查阅e2e
文件里面文件,运行命名npm run e2e
即可。部署到GitHub页面
github给我们每个项目都运行有一个预览页面,我们叫它
github-pages
。提交代码
注意:github-pages预览地址是
你的用户名.github.io/你的项目名/
--base-href:修改html里面的
base
的href
属性,如果有路由必须要使用的。gh-pages
分支注意:就是打包以后的目录,需要特别注意一下,angular-cli6是一个多工程的脚手架,打包后生成的是
dist/angular-todolist
,我们最终需要上传是这个文件夹里面的内容,那么就需要改脚本。我在所有项目里面都会用到它
运行命令
代码提交需要去github,项目下设置里面开启
github-pages
.开启 Github-pages
GitHub Pages
gh-pages branch
save
.注意:一旦启用就不能再选择none,只能你删除项目。你删除分支,访问就会出现404。
总结
毫无疑问,Angular是一个平台。一个非常强大前端框架!
我们讨论了许多让我们回顾所学在本文中:
麻雀虽小,五脏俱全,Todo应用看起来,功能很简单,其实它里面功能可以做很多衍生,都是我们平常业务需要的,比如购物车, 全选等。
这个有个类似的变种需求功能:我也不知道叫什么名字,antd里面叫
穿梭框
。这就留个大家一个作业吧。如果你不知道如何下手,可以跟我交流。
The text was updated successfully, but these errors were encountered: