天津做流产五洲网站,凡科建站平台,郓城网站建设电话,网站提交自动秒收录第一个 Angular 项目 - 静态页面
之前的笔记#xff1a; [Angular 基础] - Angular 渲染过程 组件的创建 [Angular 基础] - 数据绑定(databinding) [Angular 基础] - 指令(directives)
这是在学完了上面这三个内容后能够完成的项目#xff0c;目前因为还没有学到数…第一个 Angular 项目 - 静态页面
之前的笔记 [Angular 基础] - Angular 渲染过程 组件的创建 [Angular 基础] - 数据绑定(databinding) [Angular 基础] - 指令(directives)
这是在学完了上面这三个内容后能够完成的项目目前因为还没有学到数据在不同组件之前的传输因此只会有一个 UI 的渲染而不会涉及到事件的实现
业务需求
wireframe 如下 简单的说起来就是当前页面需要包含一个 Header一个部分列举出所有的食谱(recipe)另外一个部分则列举出对应食谱的购物清单(shopping list)
虚线边框框起来的则是我认为的组件构成将其转化成 Venn Diagram 则如下 ingrident 和 recipe 为 Model也就是 MVVM 中一直没讨论的部分(之前一直讨论的都是 VM 层和 V 层之间的互动)
根据需求也就可以开始下一步的实现了
创建项目
主要通过 bash 实现
❯ ng new recipe-book --no-strict --standalone false --routing false
❯ cd recipe-book
# 在 angular.json 中配置对应的 bootstrap CSS 文件第一篇笔记中有提
❯ npm i bootstrap3
❯ 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 filescomponent 的创建主要则是根据上面提到的业务需求进行实现目前还没有创建对应 Model 对应的文件
实现功能
这里会用 bootstrap 内置的 class 实施不少功能而 bootstrap 的部分不会细谈主要还是针对 Angular 的学习
添加骨架
修改的部分为这里的 V 层
src/app/
├── app.component.html修改内容如下
app-header/app-header
div classcontainerdiv classrowdiv classcol-md-12app-recipes/app-recipesapp-shopping-list/app-shopping-list/div/div
/div这里主要提供的是一个结构并且展示三大组件header, recipe 和 shopping list
header
修改的部分为这里的 V 层
src/app/
├── header
│ ├── header.component.html实现如下
nav classnavbar navbar-defaultdiv classcontainer-fluiddiv classnavbar-headera href# classnavbar-brandRecipe Book/a/divdiv classcollapse navbar-collapseul classnav navbar-navlia href#Recipes/a/lilia href#Shopping List/a/li/ulul classnav navbar-nav navbar-rightli classdropdownahref#classdropdown-toggledata-toggledropdownrolebuttonaria-haspopuptruearia-expandedfalseManage span classcaret/span/aul classdropdown-menulia href#Save Data/a/lilia href#Fetch Data/a/li/ul/li/ul/div/div
/nav这里全都是 bootstrap 就不多赘述了实现后效果如下 recipe
recipe 部分的结构通过上面的文件结构也能看出来了简化一下如下
├── recipes
│ ├── recipe-detail
│ ├── recipe-list
│ │ ├── recipe-item
│ ├── recipe.model.ts # 即将创建的 modelrecipes V 层
这个文件就是 recipes.component.html 这个文件实现比较简单只是导入 recipe-list 和当前选中的 recipe-detail
div classrowdiv classcol-md-5app-recipe-list/app-recipe-list/divdiv classcol-md-7app-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.description 和 recipe.imagePath 即可这里主要用到的还是 string interpolation 和 property binding
实现代码如下
div classrowdiv classcol-xs-12button classbtn btn-successNew Recipe/button/div
/div
div classrowdiv classcol-xs-12a href# classlist-group-item clearfix *ngForlet recipe of recipesdiv classpull-lefth4 classlist-group-item-heading{{ recipe.name }}/h4p classlist-group-item-text{{ recipe.description }}/p/divspan classpull-rightimg[src]recipe.imagePath[alt]recipe.nameclassimage-responsivestylemax-height: 50px//span/a/divapp-recipe-item/app-recipe-item
/div完成后的效果 ⚠️这里的 ngFor 输出所有的数据在 ngFor 是因为还没有实现跨组件交流否则直接在 ngFor 中渲染 app-recipe-item并传递对应对象即可
recipe detail V 层
同样因为跨组件交流还没实现目前只会渲染一个静态且不会动的 V 层
div classrowdiv classcol-sx-12img [src] [alt] classimg-responsive stylemax-height: 300px //div
/div
div classrowdiv classcol-xs-12h1Recipe Name/h1/div
/div
div classrowdiv classcol-xs-12div classbtn-groupbutton typebutton classbtn btn-primary dropdown-toggleManage Recipe span classcaret/span/buttonul classdropdown-menulia href#To Shopping List/a/lilia href#Edit Recipe/a/lilia href#Delete Recipe/a/li/ul/div/div
/divdiv classrowdiv classcol-sx-12Description/div
/divdiv classrowdiv classcol-sx-12Ingredients/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 classrowdiv classcol-xs-10app-shopping-edit/app-shopping-edithr /ul classlist-groupaclasslist-group-itemstylecursor: pointer*ngForlet ingredient of ingredients{{ ingredient.name }} ({{ ingredient.amount }})/a/ul/div
/div实现后效果如下 shopping-list edit V 层
出于同样的原因这里只有 V 层实现如下
div classrowdiv classcol-xs-12formdiv classrowdiv classcol-sm-5 form-grouplabel fornameName/labelinput typetext idname classform-control //divdiv classcol-sm-2 form-grouplabel foramountAmount/labelinput typenumber idamount classform-control //div/divdiv classrowdiv classcol-xs-12div classbtn-toolbarbutton classbtn btn-success mr-2 typesubmitAdd/buttonbutton classbtn btn-danger mr-2 typebuttonDelete/buttonbutton classbtn btn-primary typebuttonEdit/button/div/div/div/form/div
/div最终结果 下个章节开始数据传输之类的也就是让页面动起来的部分