1.启动server:

进入switchingToNG2/switching-to-angular2目录,运行npm start,那么打开浏览器,进入红色框的链接。

迈向angularjs2系列(3):组件详解

2.进入switching-to-angular2/app/ch4/ts/todo-app目录

app.ts:

todo组件分为导入、接口定义、顶层组件、控制器、启动5个部分。

//导入
import {Component} from '@angular/core';
import {bootstrap} from '@angular/platform-browser-dynamic';

//接口定义
interface Todo {
  completed: boolean;
  label: string;
}

//顶层组件
@Component({
  selector: 'app',
  templateUrl: './app.html',
  styles: [
    `ul li {
      list-style: none;
    }
    .completed {
      text-decoration: line-through;
    }`
  ]
})
//控制器
class TodoCtrl {
  todos: Todo[] = [{
    label: 'Buy milk',
    completed: false
  }, {
    label: "Save the world",
    completed: false
  }];
  name: string = 'John';
  addTodo(label) {
    this.todos.push({
      label,
      completed: false
    })
  }
  removeTodo(idx) {
    this.todos.splice(idx, 1);
  }
  toggleCompletion(idx) {
    let todo = this.todos[idx];
    todo.completed = !todo.completed;
  }
}
//启动
bootstrap(TodoCtrl);

(1)组件样式

我们直接在组件装饰器加入styles属性。

  app/ch4/ts/todo-app/app.ts的样式代码:

@Component({
  selector: 'app',
  templateUrl: './app.html',
  styles: [
    `ul li {
      list-style: none;
    }
    .completed {
      text-decoration: line-through;
    }`
   //styles属性,值为数组。
  ]
})

(2)组件控制器

app.ts控制器代码:

//控制器
class TodoCtrl {
  todos: Todo[] = [{
    label: '呼风唤雨',
    completed: false
  }, {
    label: "保护妹妹",
    completed: false
  }];
  //todos数组。包含两个元素,每个元素的变量指定为Todo。
  name: string = '爱莎';
  //name属性
  addTodo(label) {
    this.todos.push({
      label,
      completed: false
    })
  }
  //用于添加元素
  removeTodo(idx) {
    this.todos.splice(idx, 1);
  }
  //用于移除元素
  toggleCompletion(idx) {
    let todo = this.todos[idx];
    todo.completed = !todo.completed;
  }
  //切换完成或者未完成
}

(3)模板app.html内容:

<h1>你好 {{name}}!</h1>

<p>
  添加todo:
  <input #newtodo type="text">
  <button (click)="addTodo(newtodo.value); newtodo.value = ''">Add</button>
</p>

<p>to-do清单:</p>

<ul>
  <!--遍历todos数组-->
  <li *ngFor="let todo of todos; let index = index" [class.completed]="todo.completed">
    <input type="checkbox" [checked]="todo.completed"
      (change)="toggleCompletion(index)">
    {{todo.label}}
  </li>
</ul>

 <li *ngFor="let todo of todos; let index = index" [class.completed]="todo.completed"> 这里使用了index索引。

● (change)="toggleCompletion(index)" 绑定了toggleCompletion函数到change事件上。

● [checked]="todo.completed" 绑定了控制器的todos数据的completed到checked属性上。

   [class.completed]="todo.completed" 意思是如果todo.completed为true,那么添加completed类。angular也允许绑定style和attribute的。

最后启动app的时候,要把控制器传进去。

//启动
bootstrap(TodoCtrl);

打开http://localhost:5555/dist/dev/ch4/ts/todo-app/,结果为

迈向angularjs2系列(3):组件详解

3.组件的用户交互

实现toggleCompletion方法。它是控制器里定义的,所以直接使用咯。

toggleCompletion(idx) {
  let todo = this.todos[idx];
  todo.completed = !todo.completed;
}
//切换完成或者未完成的状态

实现addToDo方法,用来添加todo元素。

addTodo(label) {
    this.todos.push({
      label,
      completed: false
    })
  }
  //用于添加元素

通过button按钮添加元素如图:

迈向angularjs2系列(3):组件详解

4.app组件的切分

先来看一下指令API的输入输出。可以把指令接受的属性看成输入。把指令触发的事件看成输出。使用第三方库的指令时最主要的关注点就是输入和输出,这些内容构成了指令的API。

如果把todo应用切分成多个独立的组件,组件之间存在交互,那么分析一下这个todo应用咯。

迈向angularjs2系列(3):组件详解

最外层的方框代表整个todo应用。内部的第一个方框有一个组件,用来新建todo项目。下面的方框用来存储所有的项目。

根据分析,我们可以定义3个组件:

●TodoApp

●InputBox

●TodoList

5.InputBox组件:关注输入和输出

app/ch4/ts/inputs-outputs/app.ts完整的代码:

//导入
import {Component, Input, Output, EventEmitter} from '@angular/core';
import {bootstrap} from '@angular/platform-browser-dynamic';

//todo接口
interface Todo {
  completed: boolean;
  label: string;
}

//InputBox组件
@Component({
  selector: 'input-box',
  template: `
    <input #todoInput [placeholder]="inputPlaceholder">
    <button (click)="emitText(todoInput.value); todoInput.value = '';">
      {{buttonLabel}}
    </button>
  `
})
class InputBox {
  @Input() inputPlaceholder: string;
  @Input() buttonLabel: string;
  @Output() inputText = new EventEmitter<string>();
  emitText(text: string) {
    this.inputText.emit(text);
  }
}
//ToDoList组件
@Component({
  selector: 'todo-list',
  template: `
    <ul>
      <li *ngFor="let todo of todos; let index = index" [class.completed]="todo.completed">
        <input type="checkbox" [checked]="todo.completed"
          (change)="toggleCompletion(index)">
        {{todo.label}}
      </li>
    </ul>
  `,
  styles: [
    `ul li {
      list-style: none;
    }
    .completed {
      text-decoration: line-through;
    }`
  ]
})
class TodoList {
  @Input() todos: Todo[];
  @Output() toggle = new EventEmitter<Todo>();
  toggleCompletion(index: number) {
    let todo = this.todos[index];
    this.toggle.emit(todo);
  }
}
//TodoApp组件
@Component({
  selector: 'todo-app',
  directives: [TodoList, InputBox],
  template: `
    <h1>Hello {{name}}!</h1>

    <p>
      Add a new todo:
      <input-box inputPlaceholder="New todo..."
        buttonLabel="Add"
        (inputText)="addTodo($event)">
      </input-box>
    </p>

    <p>Here's the list of pending todo items:</p>
    <todo-list [todos]="todos"
      (toggle)="toggleCompletion($event)">
    </todo-list>
  `
})
class TodoApp {
  todos: Todo[] = [{
    label: 'Buy milk',
    completed: false
  }, {
    label: "Save the world",
    completed: false
  }];
  name: string = 'John';
  addTodo(label: string) {
    this.todos.push({
      label,
      completed: false
    });
  }
  toggleCompletion(todo: Todo) {
    todo.completed = !todo.completed;
  }
}
//启动
bootstrap(TodoApp);
查看完整的代码

相关文章:

  • 2022-12-23
  • 2021-09-10
  • 2021-12-24
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-16
相关资源
相似解决方案