第一个 Angular 项目 - 静态页面

第一个 Angular 项目 - 静态页面

之前的笔记:

  • [Angular 基础] - Angular 渲染过程 & 组件的创建

  • [Angular 基础] - 数据绑定(databinding)

  • [Angular 基础] - 指令(directives)

这是在学完了上面这三个内容后能够完成的项目,目前因为还没有学到数据在不同组件之前的传输,因此只会有一个 UI 的渲染,而不会涉及到事件的实现

业务需求

wireframe 如下:

在这里插入图片描述

简单的说起来就是当前页面需要包含一个 Header,一个部分列举出所有的食谱(recipe),另外一个部分则列举出对应食谱的购物清单(shopping list)

虚线边框框起来的则是我认为的组件构成,将其转化成 Venn Diagram 则如下:

在这里插入图片描述

ingridentrecipe 为 Model,也就是 MVVM 中一直没讨论的部分(之前一直讨论的都是 VM 层和 V 层之间的互动)

根据需求也就可以开始下一步的实现了

创建项目

主要通过 bash 实现:

❯ ng new recipe-book --no-strict --standalone false --routing falsecd recipe-book
# 在 angular.json 中配置对应的 bootstrap CSS 文件,第一篇笔记中有提npm i bootstrap@3
❯ ng g c header --skip-tests
❯ ng g c recipes --skip-tests
❯ ng g c recipes/recipe-list --skip-tests
❯ ng g c recipes/recipe-list/recipe-item --skip-tests
❯ ng g c shopping-list --skip-tests
❯ ng g c shopping-list/shopping-edit --skip-tests# 这是当前目录的结构
❯ tree src/app/
src/app/
├── app.component.css
├── app.component.html
├── app.component.spec.ts
├── app.component.ts
├── app.module.ts
├── header
│   ├── header.component.css
│   ├── header.component.html
│   └── header.component.ts
├── recipes
│   ├── recipe-detail
│   │   ├── recipe-detail.component.css
│   │   ├── recipe-detail.component.html
│   │   └── recipe-detail.component.ts
│   ├── recipe-list
│   │   ├── recipe-item
│   │   │   ├── recipe-item.component.css
│   │   │   ├── recipe-item.component.html
│   │   │   └── recipe-item.component.ts
│   │   ├── recipe-list.component.css
│   │   ├── recipe-list.component.html
│   │   └── recipe-list.component.ts
│   ├── recipes.component.css
│   ├── recipes.component.html
│   └── recipes.component.ts
└── shopping-list├── shopping-edit│   ├── shopping-edit.component.css│   ├── shopping-edit.component.html│   └── shopping-edit.component.ts├── shopping-list.component.css├── shopping-list.component.html└── shopping-list.component.ts8 directories, 26 files

component 的创建主要则是根据上面提到的业务需求进行实现,目前还没有创建对应 Model 对应的文件

实现功能

这里会用 bootstrap 内置的 class 实施不少功能,而 bootstrap 的部分不会细谈,主要还是针对 Angular 的学习

添加骨架

修改的部分为这里的 V 层:

src/app/
├── app.component.html

修改内容如下:

<app-header></app-header>
<div class="container"><div class="row"><div class="col-md-12"><app-recipes></app-recipes><app-shopping-list></app-shopping-list></div></div>
</div>

这里主要提供的是一个结构,并且展示三大组件:header, recipe 和 shopping list

header

修改的部分为这里的 V 层:

src/app/
├── header
│   ├── header.component.html

实现如下:

<nav class="navbar navbar-default"><div class="container-fluid"><div class="navbar-header"><a href="#" class="navbar-brand">Recipe Book</a></div><div class="collapse navbar-collapse"><ul class="nav navbar-nav"><li><a href="#">Recipes</a></li><li><a href="#">Shopping List</a></li></ul><ul class="nav navbar-nav navbar-right"><li class="dropdown"><ahref="#"class="dropdown-toggle"data-toggle="dropdown"role="button"aria-haspopup="true"aria-expanded="false">Manage <span class="caret"></span></a><ul class="dropdown-menu"><li><a href="#">Save Data</a></li><li><a href="#">Fetch Data</a></li></ul></li></ul></div></div>
</nav>

这里全都是 bootstrap 就不多赘述了,实现后效果如下:

在这里插入图片描述

recipe

recipe 部分的结构通过上面的文件结构也能看出来了,简化一下如下:

├── recipes
│   ├── recipe-detail
│   ├── recipe-list
│   │   ├── recipe-item
│   ├── recipe.model.ts # 即将创建的 model
recipes V 层

这个文件就是 recipes.component.html 这个文件,实现比较简单,只是导入 recipe-list 和当前选中的 recipe-detail:

<div class="row"><div class="col-md-5"><app-recipe-list></app-recipe-list></div><div class="col-md-7"><app-recipe-detail></app-recipe-detail></div>
</div>

这个会让 recipe-list 和 recipe-detail 出现在同一行

接下来就可以处理细节了

recipe model

这里主要就是定义了 recipe 应该有的数据,实现如下:

export class Recipe {constructor(public name: string,public description: string,public imagePath: string) {}
}

这代表着 Recipe 对象会有名字、描述和图片三个属性

recipe list VM 层

VM 层目前的逻辑也比较简单,它只需要存储一个 recipes 的数组,让 V 层可以渲染即可,代码如下:

import { Component } from '@angular/core';
import { Recipe } from '../recipe.model';@Component({selector: 'app-recipe-list',templateUrl: './recipe-list.component.html',styleUrl: './recipe-list.component.css',
})
export class RecipeListComponent {recipes: Recipe[] = [{name: 'Recipe 1',description: 'Description 1',imagePath: 'http://picsum.photos/200/200',},{name: 'Recipe 2',description: 'Description 2',imagePath: 'http://picsum.photos/200/200',},];
}

这里没用 new Recipe() 创建也不会报错,本质上来说 TS 的类型检查是检查数据是否对的上,而不是真的会检查 a instanceof A,而是做 a 有 name, a 有 description, a 有 imagePath -> a 是 A ✅ 这样一个检查

⚠️:picsum.photos 是我在 placeimg.com 上找到的代替网站。placeimg.com 于去年年中正式关站了(🕯️)

recipe list V 层

这一层要做的也比较简单,主要就是跑一个 ngFor 去渲染当前 list 中包含的数据,并且正确的渲染 recipe.name, recipe.descriptionrecipe.imagePath 即可,这里主要用到的还是 string interpolation 和 property binding

实现代码如下:

<div class="row"><div class="col-xs-12"><button class="btn btn-success">New Recipe</button></div>
</div>
<div class="row"><div class="col-xs-12"><a href="#" class="list-group-item clearfix" *ngFor="let recipe of recipes"><div class="pull-left"><h4 class="list-group-item-heading">{{ recipe.name }}</h4><p class="list-group-item-text">{{ recipe.description }}</p></div><span class="pull-right"><img[src]="recipe.imagePath"[alt]="recipe.name"class="image-responsive"style="max-height: 50px"/></span></a></div><app-recipe-item></app-recipe-item>
</div>

完成后的效果:

在这里插入图片描述

⚠️:这里的 ngFor + 输出所有的数据在 ngFor 是因为还没有实现跨组件交流,否则直接在 ngFor 中渲染 app-recipe-item,并传递对应对象即可

recipe detail V 层

同样因为跨组件交流还没实现,目前只会渲染一个静态且不会动的 V 层:

<div class="row"><div class="col-sx-12"><img [src]="" [alt]="" class="img-responsive" style="max-height: 300px" /></div>
</div>
<div class="row"><div class="col-xs-12"><h1>Recipe Name</h1></div>
</div>
<div class="row"><div class="col-xs-12"><div class="btn-group"><button type="button" class="btn btn-primary dropdown-toggle">Manage Recipe <span class="caret"></span></button><ul class="dropdown-menu"><li><a href="#">To Shopping List</a></li><li><a href="#">Edit Recipe</a></li><li><a href="#">Delete Recipe</a></li></ul></div></div>
</div><div class="row"><div class="col-sx-12">Description</div>
</div><div class="row"><div class="col-sx-12">Ingredients</div>
</div>

完成后效果:

在这里插入图片描述

至此 recipe 部分结束

shopping-list

shopping-list 的实现和 recipe 差不多,也是创建 model,随后填充 VM 层

ingredient model

这个 model 在的目录不太一样:

src/app/
├── shared
│   └── ingredient.model.ts

个人的话,大概便好创建一个新的 src/app/model 用来存放所有的 model 吧,不过这种有点看个人便好/项目规定了。实现如下:

export class Ingredient {constructor(public name: string, public amount: number) {}
}
shopping-list VM 层

这个和 recipe VM 层差不多,添加 Ingredient[] 即可

import { Component } from '@angular/core';
import { Ingredient } from '../shared/ingredient.model';@Component({selector: 'app-shopping-list',templateUrl: './shopping-list.component.html',styleUrl: './shopping-list.component.css',
})
export class ShoppingListComponent {ingredients: Ingredient[] = [new Ingredient('Apples', 5),new Ingredient('Tomatoes', 10),];
}
shopping-list V 层

这里的实现也和上面 recipe list 的实现对应:

<div class="row"><div class="col-xs-10"><app-shopping-edit></app-shopping-edit><hr /><ul class="list-group"><aclass="list-group-item"style="cursor: pointer"*ngFor="let ingredient of ingredients">{{ ingredient.name }} ({{ ingredient.amount }})</a></ul></div>
</div>

实现后效果如下:

在这里插入图片描述

shopping-list edit V 层

出于同样的原因,这里只有 V 层,实现如下:

<div class="row"><div class="col-xs-12"><form><div class="row"><div class="col-sm-5 form-group"><label for="name">Name</label><input type="text" id="name" class="form-control" /></div><div class="col-sm-2 form-group"><label for="amount">Amount</label><input type="number" id="amount" class="form-control" /></div></div><div class="row"><div class="col-xs-12"><div class="btn-toolbar"><button class="btn btn-success mr-2" type="submit">Add</button><button class="btn btn-danger mr-2" type="button">Delete</button><button class="btn btn-primary" type="button">Edit</button></div></div></div></form></div>
</div>

最终结果:

在这里插入图片描述

下个章节开始数据传输之类的,也就是让页面动起来的部分

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/673723.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【服务器部署】Docker环境的安装

基于CentOS系统的服务器环境下安装Docker环境&#xff0c;安装步骤参考官方指南&#xff1a;https://docs.docker.com/engine/install/centos/ 配置库 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-c…

Asp .Net Core 系列:Asp .Net Core 集成 Panda.DynamicWebApi

文章目录 简介Asp .Net Core 集成 Panda.DynamicWebApi配置原理什么是POCO Controller&#xff1f;POCO控制器原理ControllerFeatureProvider实现自定义判断规则IApplicationModelConventionPanda.DynamicWebApi中的实现ConfigureApiExplorer()ConfigureSelector()ConfigurePar…

ChatGPT在肾脏病学领域的专业准确性评估

ChatGPT在肾脏病学领域的专业表现评估 随着人工智能技术的飞速发展&#xff0c;ChatGPT作为一个先进的机器学习模型&#xff0c;在多个领域显示出了其对话和信息处理能力的潜力。近期发表在《美国肾脏病学会临床杂志》&#xff08;影响因子&#xff1a;9.8&#xff09;上的一项…

Linux 设置自动挂载磁盘

目录 查看硬盘信息 临时挂载&#xff08;重启后失效&#xff09; 自动挂载 查看硬盘信息 1. 先使用以下命令查看硬盘信息 sudo fdisk -l 2.根据上面查到的硬盘信息&#xff0c;查需要挂载的硬盘的uuid sudo blkid &#xff08;查全部&#xff09; 或 sudo blkid 要挂载的分…

S7-1200PLC通讯问题总结

文章目录 一、硬件1.串口通信RS232RS485RS422 2.网口通信 二、协议1.串口通信协议2.网口通信协议 三、程序编写1.S7通信PUTGET 2.开放式以太网通信 一、硬件 可分为PLC与PLC通信&#xff0c;PLC与上位机通信&#xff0c;PLC与变频器通信&#xff0c;PLC与仪器仪表通信&#xf…

兼容ARM 32位架构的edgeConnector产品为用户提供新的部署选项

Softing工业将ARM 32位兼容性集成到了edgeConnector产品中&#xff0c;以满足用户对ARM处理器的边缘设备日益增长的使用需求。 &#xff08;兼容ARM 32位架构的edgeConnector产品扩展了其应用部署范围&#xff09; 用户对采用ARM处理器的紧凑型边缘设备的需求正在大幅增长&…

【Iceberg学习一】什么是Iceberg?

Apache Iceberg 是一个面向大型分析数据集的开放表格格式。Iceberg 为包括 Spark、Trino、PrestoDB、Flink、Hive 和 Impala 在内的计算引擎增加了表格功能&#xff0c;使用一种高性能的表格格式&#xff0c;其工作方式就像一个 SQL 表一样。 用户体验 Iceberg 避免了不愉快的…

使用 Docker 镜像预热提升容器启动效率详解

概要 在容器化部署中,Docker 镜像的加载速度直接影响到服务的启动时间和扩展效率。本文将深入探讨 Docker 镜像预热的概念、必要性以及实现方法。通过详细的操作示例和实践建议,读者将了解如何有效地实现镜像预热,以加快容器启动速度,提高服务的响应能力。 Docker 镜像预热…

使用influxdb+Grafana+nmon2influxdb+nmon实时监控vps性能

Grafana可以用来实时查看linux系统的各种性能数据。 1、安装环境&#xff1a; centos 7influxdb1.7.6grafana-4.6.3-1nmon2influxdb-2.1.7nmon-16m 2、安装influxdb&#xff1a; 下载rpm包&#xff1a; influxdb官网&#xff1a;https://docs.influxdata.com/influxdb/v2.0…

Debezium发布历史115

原文地址&#xff1a; https://debezium.io/blog/2021/11/30/debezium-1.8-beta1-released/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. Debezium 1.8.0.Beta1 Released November 30, 2021 by Gunnar Morlin…

【Git版本控制 01】基本操作

目录 一、初始配置 二、添加文件 三、查看日志 四、修改文件 五、版本回退 六、撤销修改 七、删除文件 一、初始配置 Git版本控制器&#xff1a;记录每次的修改以及版本迭代的一个管理系统。 # 初始化本地仓库&#xff1a;git init(base) [rootlocalhost gitcode]# gi…

NLP_语言模型的雏形 N-Gram 模型

文章目录 N-Gram 模型1.将给定的文本分割成连续的N个词的组合(N-Gram)2.统计每个N-Gram在文本中出现的次数&#xff0c;也就是词频3.为了得到一个词在给定上下文中出现的概率&#xff0c;我们可以利用条件概率公式计算。具体来讲&#xff0c;就是计算给定前N-1个词时&#xff0…

ChatPromptTemplate和AI Message的用法

ChatPromptTemplate的用法 用法1&#xff1a; from langchain.chains import LLMChain from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_community.tools.tavily_search import TavilySear…

STM32 微控制器应用领域

STM32 微控制器在多个领域有广泛应用&#xff0c;具体如下&#xff1a; 工业自动化&#xff1a;STM32 在工厂自动化、机器人控制、传感器接口和数据采集等方面具有出色的性能和可靠性&#xff0c;有助于实现高效的工业自动化系统。消费电子&#xff1a;STM32 适用于智能手机、…

阿里 EasyExcel 表头国际化

实体类字段使用EasyExcel提供的注解ExcelProperty&#xff0c;value 值写成占位符形式 &#xff0c;匹配 i18n 文件里面的编码。 如&#xff1a; /*** 仓库名称*/ ExcelProperty("{warehouse.record.warehouseName}") private String warehouseName;占位符解析器 A…

《电子芯片的夜晚》

《电子芯片的夜晚》 在这个寂静的城市中&#xff0c;有一位名叫小明的程序员。他不同寻常&#xff0c;因为他有一项神奇的技能——他能够让电子芯片们说出自己的故事。 一天&#xff0c;小明收到了一块别具灵性的电子芯片&#xff0c;传说这块芯片能够在夜晚让设备们复活&…

笔记---dp---数字三角形模型

所谓数字三角形模型&#xff0c;即是从数字三角形这一题衍生出来的 题目为经典题目&#xff0c;不再赘述&#xff0c;此笔记根据AcWing算法提高课来进行对数字三角形模型衍生例题的记录 题目关系如下&#xff08;见AcWing里的AcSaber&#xff09;&#xff1a; AcWing.1015.摘…

哪些软件可以提供更好的协同办公体验?

协同办公软件的选择取决于您的具体需求&#xff0c;包括团队规模、工作流程、预算以及所需的特定功能。根据搜索结果&#xff0c;这里有一些被推荐的协同办公软件&#xff0c;它们在不同的领域提供了良好的协同体验&#xff1a; 一、文档协同&#xff1a; 1.Pixso&#xff1a;这…

微信小程序(三十八)滚动容器

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.滚动触底事件 2.下拉刷新事件 源码&#xff1a; index.wxml <view class"Area"> <!-- scroll-y 垂直滚动refresher-enabled 允许刷新bindrefresherrefresh 绑定刷新作用函数bindscrollto…

单片机无线发射的原理剖析

目录 一、EV1527编码格式 二、OOK&ASK的简单了解 三、433MHZ 四、单片机的地址ID 五、基于STC15W104单片机实现无线通信 无线发射主要运用到了三个知识点&#xff1a;EV1527格式&#xff1b;OOk&#xff1b;433MHZ。下面我们来分别阐述&#xff1a; EV1527是数据的编…