zoukankan      html  css  js  c++  java
  • web全栈第三讲:Angular单页面应用

    Angular布局模板

    bootstrap是通用的css库,angular发布了自己的css库——angular material design。

    angular material design官网是https://material.angular.io 。

    国内的ant design of anular,官网是https://ng.ant.design 。

    Angular:面向组件的设计模式

    为什么用Angular?

    由谷歌团队打造,升级比较快,社区活跃。

    • 单向绑定

    • 双向绑定

    • 单页面应用

    • 路由

    • 网络请求,前端框架的一大重点是网络请求。

    • 基于组件

      面向组件设计模式:

      view html :view html视图模板。

      class:code代码、typescript、data&methods数据和方法。

      metadata:information decorator信息装饰器(指令)

    动手实验——创建Angular6工程

    首先确认Angular官网https://angular.io/ 。

    然后安装node.js,从官网https://nodejs.org/en/download/ 下载安装。

    npm install -g @angular/cli
    

    哎,在这卡住了,进度条不动。

    昨天晚上折腾了1个多小时最终搞定angular运行环境。

    1. 创建工程,首先创建工程目录,然后进入这个目录。

      cd D:\npm-library\angular-project
      
    2. 输入创建工程指令:

      ng new my-app
      
      • 然后会跳出几个问题让你选择,老师的界面里面没有选择问题,估计是版本的差异。

        下面的问题是问是否需要更严格的类型检查和捆绑导入,这项设置能帮你提前发现错误。更多信息请去网站上查看,我选了y。

         Do you want to enforce stricter type checking and stricter bundle budgets in the workspace?
          This setting helps improve maintainability and catch bugs ahead of time.
          For more information, see https://angular.io/strict  (y/n)
        
      • 下面的问题是问你是否添加Angular路由,我选了y。

        Would you like to add Angular routing? (y/n)
        
      • 下面的选项让你选择一个模板,我选了CSS。

        ? Which stylesheet format would you like to use? (Use arrow keys)
        > CSS
          SCSS   [ https://sass-lang.com/documentation/syntax#scss                ]
          Sass   [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]
          Less   [ http://lesscss.org                                             ]
          Stylus [ https://stylus-lang.com                                        ]
        

        耐心等待工程创建完毕。我这里发现一句提示“ Packages installed successfully.”意思是工程创建完毕,但是下面还有一句提示“'git' 不是内部或外部命令,也不是可运行的程序
        或批处理文件。”,根据提示我推测是创建工程时需要用到git,但是我的系统里没有安装git,那么现在需要安装git。

        按照老师教的方法,去bing.com搜索“official site”(在必应国际版中搜官方网站,没有广告,保证搜索到的是真正的官网。这里我吐槽一下某度,广告太多,搜到的经常不是官网)。

        去git官网下载git工具,网址是https://git-scm.com/downloads。我的是win10系统,下载的是64-bit git for windows setup,文件大小是46.3MB。

        安装完成git后,不要忘了添加git的环境变量,我在path变量里添加了一项内容:

        C:\Program Files\Git\bin
        

        关闭powershell,重新用管理员身份运行一个powershell,这是为了让刚刚添加的环境变量生效,输入命令“git”测试一项git是否可以正常调用。

        测试无误后,再把刚刚的my-app删掉再重建项目。留神是否还有报错信息。

    3. 运行工程

      老师运行工程前花了不少时间讲指令创建的复杂工程与可视化界面创建工程与vue创建工程的利弊。意思是说指令创建的复杂工程在真正做项目时效率反而更高,学习的时候不妨尝试指令创建项目。

      工程创建完毕后,进入刚才的工程目录:

      cd .\my-app\
      

      运行工程:

      ng serve --open
      

      运行时会有一个问题让你选择:

      ? Would you like to share anonymous usage data about this project with the Angular Team at
      Google under Google’s Privacy Policy at https://policies.google.com/privacy? For more
      details and how to change this setting, see http://angular.io/analytics. (Y/N)
      

      意思是问你是否愿意匿名分享有关该项目的一些数据给Angular 团队,有关详细信息可以去网站查看。我推荐选N。

      回车以后系统会对项目进行编译,编译完成会提示:

      Compiled successfully.
      

      老师在课堂上说了很多编译的优点,在编译的过程中系统会分析检查代码,发现错误会报错,编译的过程是排错的过程,即将原来typescript的代码编译成JavaScript的代码。这个对开发效率是一种大大的提升。

      之后会自动打开该项目的网页内容,网页内容如下:

    注意:这个画面和老师的画面不一样,还是因为Angular版本不同的问题。

    1. 接下来关闭powershell窗口和网页,用vscode打开刚才的工程目录。

    1. 接下来打开src目录,仔细观察里面的文件,其中是main.ts是工程入口,文件内容如下:

      import { enableProdMode } from '@angular/core';
      import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
      
      import { AppModule } from './app/app.module';
      import { environment } from './environments/environment';
      
      if (environment.production) {
        enableProdMode();
      }
      
      platformBrowserDynamic().bootstrapModule(AppModule)
        .catch(err => console.error(err));
      

      其中.bootstrapModule是启动模块的意思,它的参数是AppModule。

      web应用由模块(module)组成;模块由组件(component)组成;

      组件由Template、Class、Metadata三部分组成。

    Template:View、HTML,即网页、显示的内容。

    Class:Code、TypeScript、Data & Methods,即代码、数据、方法。

    Metadata:Information Decorator,即Angular定义的特殊内容,如装饰器等。

    • 去app目录下查看,可以找到对应的文件:app.module.ts(模块),查看app.module.ts文件内容:

      import { BrowserModule } from '@angular/platform-browser';
      import { NgModule } from '@angular/core';
      
      import { AppRoutingModule } from './app-routing.module';
      import { AppComponent } from './app.component';
      
      @NgModule({
        declarations: [
          AppComponent
        ],
        imports: [
          BrowserModule,
          AppRoutingModule
        ],
        providers: [],
        bootstrap: [AppComponent]
      })
      export class AppModule { }
      
    • 查看app.component.ts(组件)文件内容:

      import { Component } from '@angular/core';
      
      @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
      })
      export class AppComponent {
        title = 'my-app';
      }
      

      注意看其中的templateUrl: './app.component.html'指向的是网页文件。

    • 查看app.component.html这个文件。对比该文件和http://localhost:4200/显示的内容,可以找到,myapp显示的内容全是在该文件中定义。

    • 修改app.component.ts文件中的title为“我的第一个Angular应用程序'”,再查看网页内容已更新如下图:

    • 可以看到title已经变成了我们修改的内容“我的第一个Angular应用程序”,但是后面的“app is running!”是怎么回事呢?

    • 复制“app is running!”,再去app.component.html文件中查找,可以看到<span>{{ title }} app is running!</span>,这里控制了标题输出的内容。将其修改为<span>欢迎使用{{ title }}</span>,再查看网页内容已更新如下图:

    • 通过上述的修改测试,我们可以了解到web应用修改可以立即生效,因为后端服务一直在运行,所以我们修改的代码和网页内容会立即刷新、生效。

    • 现在app开发流行代码(.ts文件)、结构(.html文件)、样式(.css)分离。

      可以看到项目目录下有一个app.component.css,样式在这里写。

      尝试修改该文件内容为:

      span {
      color:red;
      }
      

      可以看到网页字体立马变成红色了:

    • 以上案例还说明的了一个单向数据绑定概念。在复杂页面维护时很方便。

    • 打开app.component.html,找到{{,删除一个{,再看网页内容会一片白,没有显示。

      按ctrl+shift+i,打开console标签,可以看到报错内容,根据报错内容可以排查bug。

    • 框架解决的问题是让简单、重复劳动用电脑来完成,可以让程序员专注于解决业务逻辑。

    以上是angular工程的基本框架,接下来尝试创建新的组件。

    1. 创建组件

      • 创建组件首先注意路径,一定要在当前工程路径下创建component。创建组件命令:

        ng g c productlist
        

        以上是简写,全写命令是ng generate component productlist,创建商品列表。

        创建结果如下:

        CREATE src/app/productlist/productlist.component.html (26 bytes)
        CREATE src/app/productlist/productlist.component.spec.ts (661 bytes)
        CREATE src/app/productlist/productlist.component.ts (295 bytes)
        CREATE src/app/productlist/productlist.component.css (0 bytes)
        UPDATE src/app/app.module.ts (495 bytes)
        

        接下来继续创建“productcreate”、“orderlist”、“ordercreate”

        ng g c productcreate
        ng g c orderlist
        ng g c ordercreate
        

        以上一起创建了4个组件,这里创建完组件后,在工程中会产生相应的变化,接下来用vscode打开工程目录my-app,可以看到在工程目录下多了4个子目录,名字分别是:productlist、productcreate、orderlist、ordercreate。子目录下分别有4个文件,后缀名是.css、.html、.spec.ts、.ts文件。

        重新编译,打开项目后发现网页没变化,是因为组件还没加入页面。

    2. 引入路由概念,前端概念2大重点——路由、网络请求。

      • 查看app.module.ts,添加路由:

        import { RouterModule , Routes} from '@angular/router';
        
        const routes: Routes = [
          {
            path: 'productlist',
            component: ProductlistComponent
          },
          {
            path: 'productcreate',
            component: ProductcreateComponent
          },
          {
            path: 'ordetlist',
            component: OrderlistComponent
          },
          {
            path: 'ordercreate',
            component: OrdercreateComponent
          },
        ];
        
      • 注意@NgModule({下面的 declarations标签已经有五条记录,declarations是宣告的意思。下面的import要添加组件导入才能生效。

          imports: [
            BrowserModule,
            AppRoutingModule,
            RouterModule.forRoot(routes)
          ],
        
      • 接下来再查看页面,发现仍然没有任何变化,这是因为新创建的4个组件的html文件内容尚未写入任何内容。接下来修改app.component.html文件,添加进入新增组件的导航栏。

        <nav>
          <div style="text-align:center">
            <a routerLink="/productlist"> 商品列表 </a>
            <a routerLink="/productcreate"> 创建商品 </a>
            <a routerLink="/orderlist"> 订单列表 </a>
            <a routerLink="/ordercreate"> 创建订单 </a>
          </div>
        </nav>
        

        再查看页面发现已经有导航栏,点击以后注意看上面网页地址部分会发生变化,但页面没有变化。

    • 接下来梳理网页加载顺序:

      首先是indexhtml,它的<body>内部只有<app-root></app-root>,再去app.component.ts文件中可以找到以下内容:

      @Component({
        selector: 'app-root',
        templateUrl: './app.component.html',
        styleUrls: ['./app.component.css']
      })
      

      在这可以看到root显示的页面指向了app.component.html和对应的.css文件。

      再看app.module.ts文件中:

        imports: [
          BrowserModule,
          AppRoutingModule,
          RouterModule.forRoot(routes)
        ],
      

      routes会根据下面的表映射到对应的网页:

      const routes: Routes = [
        {
          path: 'productlist',
          component: ProductlistComponent
        },
        {
          path: 'productcreate',
          component: ProductcreateComponent
        },
        {
          path: 'ordetlist',
          component: OrderlistComponent
        },
        {
          path: 'ordercreate',
          component: OrdercreateComponent
        },
      ];
      

      再看其中一个组件“productlist”中html文件的内容

      <p>productlist works!</p>
      
    • 经过上述梳理,了解路由跳转过程,再尝试刷新网页,点击导航栏可以看到有了变化。

    • 现在尝试装修页面,通过终端指令引入bootstrap,进入工程路径,输入工程指令:

      npm install bootstrap --save
      

      这里又遇到坑,很多报错和安装失败,估计又是因为墙的原因,解决方法还是使用cnpm指令,意思是用淘宝的软件仓库,不用官方的软件仓库。

      建议按下列指令顺序执行安装bootstrap:

      cnpm i jquery --save
      cnpm i popper.js --save
      cnpm install bootstrap --save
      

      注意安装过程,留神有没有报错信息,当看到下面这样的画面表示bootstrap安装正确无误。

    • 安装完成后回到当前工程注意看整个工程目录,里面有一个styles.css文件,这个文件和app目录是同级目录的,意思是该文件定义的全局的样式,即整个app的样式。

    • 编辑styles.css,导入bootstrap包。

      @import "~bootstrap/dist/css/bootstrap.min.css";
      
    • 编辑app.component.html文件,修改导航栏的样式。首先从bootstrap官网查找Documentation(文档),侧边栏点击Components(组件),选择一个适合的样式,点击该样式右边的copy(复制)按钮,将其paste(粘贴)到文件中,注释其内容,复制样板。

      <nav class="nav">
        <a class="nav-link" routerLink="/productlist"> 商品列表 </a>
        <a class="nav-link" routerLink="/productcreate"> 创建商品 </a>
        <a class="nav-link" routerLink="/orderlist"> 订单列表 </a>
        <a class="nav-link" routerLink="/ordercreate"> 创建订单 </a>
      </nav>
      

      nav class = "nav",这里的nav是从bootstrap中引入的nav,下面的class="nav-link"也是同理。

    • 现在导航栏已经美化完成,回忆一下上节课做的card,我们可以把它复制过来放到productlist里面。之后再点击商品列表会弹出3个card。注意缩放页面时card的数量会自动调整,这就是现在流行的响应式布局,自动适应用户的屏幕。

    1. 构建数据:

      数据分静态数据和动态数据,静态数据指固定不变的数据,动态数据指从文件或服务器中动态获取的数据。

      • 首先在app目录下new一个文件,文件名是product.ts,编辑它的内容,定义product类:

        export class product {
        
            title!: String;
            detail!: String;
            image_url!: String;
            price!: Number;
        }
        
      • 其次创建模拟数据文件mock-product.ts,编辑它的内容,写入数据:

        import {product} from "./product";
        
        export const PROUDUCTS : product[] = [
            {
            title: "投影仪",
            detail: "坚果 (JmGo) J7",
            image_url: "https://img11.360buyimg.com/n7/jfs/t1/125904/1/19039/83867/5fb4e6eaE23e725b2/59aaf9823d75043e.jpg",
            price: 2999
            },
            {
            title: "投影仪",
            detail: "坚果 (JmGo) J7",
            image_url: "https://img11.360buyimg.com/n7/jfs/t1/125904/1/19039/83867/5fb4e6eaE23e725b2/59aaf9823d75043e.jpg",
            price: 2999
            },
            {
            title: "投影仪",
            detail: "坚果 (JmGo) J7",
            image_url: "https://img11.360buyimg.com/n7/jfs/t1/125904/1/19039/83867/5fb4e6eaE23e725b2/59aaf9823d75043e.jpg",
            price: 2999
            },
        ];
        
      • 编辑productlist.component.html文件,修改内容如下:

        <!DOCTYPE html>
        <html lang="en">
        
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Document</title>
            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
                integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
            <style>
                body {
                    margin-top: 0.5em;
                    margin-left: 1.5em;
                    background-color: #f4f4f4;
                }
        
                .mycard {
                    margin-right: 1em;
                    margin-bottom: 0.5em;
                }
            </style>
        </head>
        
        <body>
            <div class="container">
                <div class="row">
                    <div class="card mycard" style=" 14rem;" *ngFor="let product of products">
                        <img class="card-img-top" src="{{ product.image_url}}" alt="card-img-cap">
                        <div class="card-body">
                            <h5 class="card-title">{{ product.title }}</h5>
                            <p class="card-text">{{ product.detail }}</p>
                            <p class="card-text">{{ product.price }}</p>
                            <a href="#" class="btn btn-primary">加入购物车</a>
                        </div>
                    </div>
                </div>
            </div>
        </body>
        
        </html>
        

        注意*ngFor="let product of products",意思是从products数组中循环取元素,其中的{{product.title}}是变量,从数组元素中取值得来。

      • 接下来可以尝试美化细节,如加入购物车按钮调整为红色,即将其代码改为btn-danger,再刷新页面可以看到购物车按钮颜色已经变成红色。再尝试修改价格的标签颜色以及添加前后的文字内容,细节的标签颜色。

        <body>
            <div class="container">
                <div class="row">
                    <div class="card mycard" style=" 14rem;" *ngFor="let product of products">
                        <img class="card-img-top" src="{{ product.image_url}}" alt="card-img-cap">
                        <div class="card-body">
                            <h5 class="card-title">{{ product.title }}</h5>
                            <p class="text-muted">{{ product.detail }}</p>
                            <p class="text-danger">价格:{{ product.price }}元</p>
                            <a href="#" class="btn btn-danger">加入购物车</a>
                        </div>
                    </div>
                </div>
            </div>
        </body>
        
      • 再尝试对mock-products.ts文件添加数据,重复复制3条记录,现在products数组中有6条数据,再次刷新网页检查是否有6个card。可以确认网页中已有6个card。这就是动态数据。

      最终页面效果:

  • 相关阅读:
    [译]在Python中如何使用额enumerate 和 zip 来迭代两个列表和它们的index?
    [译]如何去除Git的unstaged的文件提示“old mode 100755 new mode 100644”?
    [译]在SQL查询中如何映射(替换)查询的结果?
    [总结]《敏捷软件开发: 原则、模式与实践》一次编程实践
    [书摘]《敏捷软件开发: 原则、模式与实践》第一部分:敏捷开发
    [译]Python
    [问题解决]Python locale error: unsupported locale setting
    [持续补充]开发过程中常见bug查找思路
    [译]如何比较同一分支上的不同commit的代码区别?
    [整理]如何切换到远程分支
  • 原文地址:https://www.cnblogs.com/fz17/p/14065521.html
Copyright © 2011-2022 走看看