四时宝库

程序员的知识宝库

Angular和BootStrap的一个简单demo

Angular和BootStrap的一个简单demo

根据Angular5高级编程这本书第二章搭建的demo

参考博客:https://blog.csdn.net/crper/article/details/64443239

代码地址:https://github.com/Harry-ZH-Wang/AngularDemo


1. 添加bootstrap包

首先ng new 项目名称创建一个Angular工程,步骤和正常创建步骤相同,然后导入BootStrap包

如果不清楚怎么构建可以看:https://www.jianshu.com/p/65e603da0828

在package.json文件中添加BootStrap CSS 的包 : "bootstrap": "4.0.0-alpha.4"

"dependencies": {
    "@angular/animations": "~7.2.0",
    "@angular/common": "~7.2.0",
    "@angular/compiler": "~7.2.0",
    "@angular/core": "~7.2.0",
    "@angular/forms": "~7.2.0",
    "@angular/platform-browser": "~7.2.0",
    "@angular/platform-browser-dynamic": "~7.2.0",
    "@angular/router": "~7.2.0",
    "core-js": "^2.5.4",
    "rxjs": "~6.3.3",
    "tslib": "^1.9.0",
    "zone.js": "~0.8.26",
    "bootstrap": "4.0.0-alpha.4"
  }

cmd cd 到建立的项目的目录下面,执行nmp install下载bootstrap的包。

2. 添加css样式

在angular.json文件中添加bootstrap的css样式,angularJsDemo为项目名

"styles": [
              "src/styles.css",
              "../angularJsDemo/node_modules/bootstrap/dist/css/bootstrap.css"
            ]

测试下bootstrap导入是否成功,我们修改下src下面的index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>AngularJsDemo</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body class="m-a-1">
  <h3 class="bg-primary p-a-1">测试列表</h3>
  <div class="m-t-1 m-b-1">
    <input class="form-control" />
    <button class="btn btn-primary m-t-1">Add</button>
  </div>
  <table class="table table-bordered table-striped">
    <thead>
      <tr>
        <td>标题</td>
        <td>描述</td>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>第一行</td>
        <td>no</td>
      </tr>
      <tr>
        <td>第二行</td>
        <td>no</td>
      </tr>
      <tr>
        <td>第三行</td>
        <td>no</td>
      </tr>
    </tbody>
  </table>
</body>
</html>

启动一下,bootStrap的样式生效


这里只是做了个静态页面的展示,只是为了测试,下面按照书中的代码示例,添加Angular的功能

3. HTML页面添加Angular功能

通过cli建立的demo,在app目录下其实已经生成了一套配置的文件代码,这里为了自己体验下逻辑,就自己仿照着配置下


首先body 内容去掉,添加<demo-app>Angular 入口</demo-app> 标签,这里demo-app标签不是html标签,是自己随便写的一个,后续作为单页面APP的入口

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>AngularJsDemo</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body class="m-a-1">
  <app-demo>Angular 入口</app-demo>
</body>
</html>

这里直接用TypeScript,它是javaScript的一个超集,除了自己的语法,也支持原生态的javaScript语法。在src/app 目录下新建一个demo文件夹,存放我们自己的TS文件,这里在demo文件夹下新建helloTS.ts,这里可以直接写JavaScript,不过既然玩新东西,那肯定要用TypeScript。

helloTs.ts文件

// 在创建JavaScript模块时,export 语句用于从模块中导出函数、对象或原始值,以便其他程序可以通过 import 语句使用它们
/**
 * 这里的类做原始数据来源
 */
export class HelloModel {
  user;
  items;

  /**
   * 在一个类中只能有一个名为 “constructor” 的特殊方法。
   * 一个类中出现多次构造函数 (constructor)方法将会抛出一个 SyntaxError 错误。
   * 在一个构造方法中可以使用super关键字来调用一个父类的构造方法。
   * 如果没有显式指定构造方法,则会添加默认的 constructor 方法。
   * 如果不指定一个构造函数(constructor)方法, 则使用一个默认的构造函数(constructor)。
   */
  constructor() {
    this.user = 'Admin';
    this.items = [new HelloItem('第一行', false),
                  new HelloItem('第二行', false),
                  new HelloItem('第三行', false)];
  }
}

/**
 * 数据对像类
 */
export class HelloItem {
  action;
  done;
  constructor(action, done) {
    this.action = action;
    this.done = done;
  }
}

这一步是构造一个页面展示的数据,实际情况数据来源应该是服务器来的,这里的demo,就前端构造一个数据对像列表,非必须。

3.1 创建模板

在angular中,向用户展示数据是通过模板来实现的,{{}} 这表示数据绑定

helloComponent.html 文件

<!-- Angular demo 模板类 -->
<!--{{}}是angular的数据绑定取值,这里getUser()是自己写的函数-->
<h3 class="bg-primary p-a-1">{{getName()}}的测试列表</h3>

3.2 创建组件

Angular组件负责为模块提供所需数据合逻辑

helloComponent.ts文件

import { Component } from '@angular/core';
import { HelloModel} from './helloTs';

/**
 * @Component 标记为一个装饰器(组件)
 * selector: 'demo-app' 指定一个CSS选择器,匹配该组件要应用的HTML元素,这里就是我们刚刚自定义的元素
 * templateUrl: 'helloComponent.html' 模板的路径,这里写的相对路径 也可以写绝对路径 app/demo/helloComponent.html
 */
@Component({
  selector: 'app-demo',
  templateUrl: 'helloComponent.html'
})

/**
 * 实例化一个对象
 */
export class AppHelloComponent {
  model = new HelloModel();
    getName() {
    return this.model.user;
  }
}

3.3 定义装饰器

通过@NgModule定义的属性来提供配置信息

helloModules.ts文件

import { BrowserModule } from '@angular/platform-browser';
// 每个模块的定义必须有这个才能生效,ng2的开发模式就是类似一个树,从根节点无限发散
import { NgModule } from '@angular/core';
// 表单模块,比如你要在组件内用到一些表单元素或者数据绑定,不然会报错
import { FormsModule } from '@angular/forms';
// 自己定义的组件
import {AppHelloComponent} from './helloComponent';

@NgModule({
  declarations: [ // 指令和组件
    AppHelloComponent
  ],
  imports: [ // 比如你要引用那些模块的功能就要引入
    BrowserModule,
    FormsModule
  ],
  providers: [], // 服务
  bootstrap: [AppHelloComponent] // 启动的模块,一个app一般只有一个启动模块!
})
export class AppModule { }

3.4 配置main.ts引到文件

main.ts文件

//  引入生产模式,控制关闭开发模式的,函数控制
import { enableProdMode } from '@angular/core';
// app启动模块,必须引入
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

// import { AppModule } from './app/app.module';
// 根模块,程序启动根页面
import { AppModule} from './app/demo/helloModules';
// 环境配置文件,可以写入接口路径什么的。。dev,prod各一份
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

// platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err));
// bootstrapModule是PlatformRef的一个方法,这个方法中实现了Module的初始化、Component的初始化等,是Angular的启动函数,此方法是基于浏览器,如果是移动例如Ionic框架,引到方法不一样
platformBrowserDynamic().bootstrapModule(AppModule).catch(err => console.error(err));

配置完成了,启动测试下


4. 继续完善demo
4.1继续完善demo,通过Angular内置的结构指令加载List

三个常用的内置结构型指令: NgIf、NgFor和NgSwitch

中文手册地址:https://angular.cn/guide/structural-directives

首先添加一个getItems()方法获得之前构造的List

helloComponent.ts 文件

import { Component } from '@angular/core';
import { HelloModel} from './helloTs';

/**
 * @Component 标记为一个装饰器(组件)
 * selector: 'demo-app' 指定一个CSS选择器,匹配该组件要应用的HTML元素,这里就是我们刚刚自定义的元素
 * templateUrl: 'helloComponent.html' 模板的路径,这里写的相对路径 也可以写绝对路径 app/demo/helloComponent.html
 */
@Component({
  selector: 'app-demo',
  templateUrl: 'helloComponent.html'
})

/**
 * 实例化一个对象
 */
export class AppHelloComponent {
  model = new HelloModel();
  getName() {
    return this.model.user;
  }
  getItems() {
    return this.model.items;
  }
}

使用内置的结构指令*ngFor循环列表 * 号不能省略

helloComponent.html 文件

<!-- Angular demo 模板类 -->
<!--{{}}是angular的数据绑定取值,这里getUser()是自己写的函数-->
<h3 class="bg-primary p-a-1">{{getName()}}的测试列表</h3>
<table class="table table-bordered table-striped">
  <thead>
    <tr>
      <td>No</td>
      <td>标题</td>
      <td>描述</td>
    </tr>
  </thead>
  <tbody>
    <!--nfFor ngSwitch 为Angular的内置结构指令,*不能省略,index为数组的索引,0开始-->
    <tr *ngFor="let item of getItems(); let i = index">
      <td>{{i + 1}}</td>
      <td>{{item.action}}</td>
      <td [ngSwitch] = "item.done">
        <span *ngSwitchCase="true">已办</span>
        <span *ngSwitchCase="false">代办</span>
      </td>
    </tr>
  </tbody>
</table>

到这来就完成了数据的单向绑定,也就是展示的步骤


4.2 创建数据双向绑定

这来使用ngModel 来实现双向绑定,ngModel有三种写法,ngModel、[ngModel]和[(ngModel)]

[ngModel]为单向绑定,操作不会改变原有的值,[(ngModel)]为双向绑定,会改变原有值

简单说就是当你想从html的 input 组件去改动.ts对应的变量,,反之更动.ts的变量html对应的值也会改变,这时候就要使用双向绑定的功能

helloComponent.html文件

<!-- Angular demo 模板类 -->
<!--{{}}是angular的数据绑定取值,这里getUser()是自己写的函数-->
<h3 class="bg-primary p-a-1">{{getName()}}的测试列表</h3>
<table class="table table-bordered table-striped">
  <thead>
    <tr>
      <td>No</td>
      <td>标题</td>
      <td>描述</td>
      <td>操作</td>
    </tr>
  </thead>
  <tbody>
    <!--nfFor ngSwitch 为Angular的内置结构指令,*不能省略,index为数组的索引,0开始-->
    <tr *ngFor="let item of getItems(); let i = index">
      <td>{{i + 1}}</td>
      <td>{{item.action}}</td>
      <td [ngSwitch] = "item.done">
        <span *ngSwitchCase="true">已办</span>
        <span *ngSwitchCase="false">代办</span>
      </td>
      <td>
        <input type="checkbox" [(ngModel)] = "item.done" />
      </td>
    </tr>
  </tbody>
</table>

勾选checkbox后可以发现代办变为了已办


4.3 lambda表达式

这来可以通过一些语法糖来做些数据过滤,例如通过lambda函数来做数据过滤,这个时候勾选了后的数据会消失

helloComponent.ts 文件

import { Component } from '@angular/core';
import {HelloItem, HelloModel} from './helloTs';

/**
 * @Component 标记为一个装饰器(组件)
 * selector: 'demo-app' 指定一个CSS选择器,匹配该组件要应用的HTML元素,这里就是我们刚刚自定义的元素
 * templateUrl: 'helloComponent.html' 模板的路径,这里写的相对路径 也可以写绝对路径 app/demo/helloComponent.html
 */
@Component({
  selector: 'app-demo',
  templateUrl: 'helloComponent.html'
})

/**
 * 实例化一个对象
 */
export class AppHelloComponent {
  model = new HelloModel();
  getName() {
    return this.model.user;
  }
  getItems() {
    // filter 从数组项中选择一个子集,=>为lambda表达式(参数1, 参数2, …, 参数N) => { 函数声明 },这段代码等同于 function(item){return !item.done}
    return this.model.items.filter(item => !item.done);
  }
}

上面做了删除的事件,这里再做个添加的事件

helloComponent.ts 文件

<!-- Angular demo 模板类 -->
<!--{{}}是angular的数据绑定取值,这里getUser()是自己写的函数-->
<h3 class="bg-primary p-a-1">{{getName()}}的测试列表</h3>
<div class="m-t-1 m-b-1">
  <!-- #textValue为取值的 -->
  <input class="form-control" #textValue />
  <button class="btn btn-primary m-t-1" (click)="addInfo(textValue.value)">Add</button>
</div>
<table class="table table-bordered table-striped">
  <thead>
    <tr>
      <td>No</td>
      <td>标题</td>
      <td>描述</td>
      <td>操作</td>
    </tr>
  </thead>
  <tbody>
    <!--nfFor ngSwitch 为Angular的内置结构指令,*不能省略,index为数组的索引,0开始-->
    <tr *ngFor="let item of getItems(); let i = index">
      <td>{{i + 1}}</td>
      <td>{{item.action}}</td>
      <td [ngSwitch] = "item.done">
        <span *ngSwitchCase="true">已办</span>
        <span *ngSwitchCase="false">代办</span>
      </td>
      <td>
        <input type="checkbox" [(ngModel)] = "item.done" />
      </td>
    </tr>
  </tbody>
</table>

helloComponent.ts

import { Component } from '@angular/core';
import {HelloItem, HelloModel} from './helloTs';

/**
 * @Component 标记为一个装饰器(组件)
 * selector: 'demo-app' 指定一个CSS选择器,匹配该组件要应用的HTML元素,这里就是我们刚刚自定义的元素
 * templateUrl: 'helloComponent.html' 模板的路径,这里写的相对路径 也可以写绝对路径 app/demo/helloComponent.html
 */
@Component({
  selector: 'app-demo',
  templateUrl: 'helloComponent.html'
})

/**
 * 实例化一个对象
 */
export class AppHelloComponent {
  model = new HelloModel();
  getName() {
    return this.model.user;
  }
  getItems() {
    // filter 从数组项中选择一个子集,=>为lambda表达式(参数1, 参数2, …, 参数N) => { 函数声明 },这段代码等同于 function(item){return !item.done}
    return this.model.items.filter(item => !item.done);
  }
  addInfo(info) {
    if (info !== '') {
      this.model.items.push(new HelloItem(info, false));
    }
  }
}


这里就完成了一个简单的前端demo,做个备注

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接