2个淘宝可以做情侣网站么,做那种网站受欢迎,网站设计制作案例,安徽建站贵吗[Angular 基础] - Angular 渲染过程 组件的创建
之前的笔记为了推进度写的太笼统了#xff08;只有功能没有其他#xff09;#xff0c;当时学的时候知道是什么东西#xff0c;但是学完后重新复习发现有些内容就记不清了#xff0c;所以重新用自己的语言总结一下
…[Angular 基础] - Angular 渲染过程 组件的创建
之前的笔记为了推进度写的太笼统了只有功能没有其他当时学的时候知道是什么东西但是学完后重新复习发现有些内容就记不清了所以重新用自己的语言总结一下
安装 angular-cli 的指令为
# 如果不确定是否有安装过可以先卸载
npm uninstall -g angular-cli angular/cli
# 重新安装 CLI
npm install -g angular/cliAngular 项目启动挂载过程
不涉及到 webpack/vite 编译只是简单的加载过程
首先看一下 angular 项目的架构
❯ tree --gitignore
.
├── README.md
├── angular.json
├── package-lock.json
├── package.json
├── src
│ ├── app
│ │ ├── app.component.css
│ │ ├── app.component.html
│ │ ├── app.component.spec.ts
│ │ ├── app.component.ts
│ │ └── app.module.ts
│ ├── assets
│ ├── favicon.ico
│ ├── index.html
│ ├── main.ts
│ └── styles.css
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json4 directories, 16 files其中 src 外面的代码都是配置代码一般来说没有什么变更的需要目前我能想到的变动的情况只有添加额外的 CSS 库需要变动 angular.json
src 里面则是实现的代码这里面 index.html 的作用就是一个锚点也就是组件在没有渲染时的初始界面内容如下
!DOCTYPE html
html langenheadmeta charsetutf-8 /titleMyFirstApp/titlebase href/ /meta nameviewport contentwidthdevice-width, initial-scale1 /link relicon typeimage/x-icon hreffavicon.ico //headbodyapp-root/app-root/body
/html这与没有被 JS 重写的 HTML 一致 下面的 script 也是在编译的时候添加到 HTML 网页中具体的配置依旧在 angular.json 中
{// 省略其他options: {outputPath: dist/my-first-app,index: src/index.html,browser: src/main.ts,polyfills: [zone.js],tsConfig: tsconfig.app.json,assets: [src/favicon.ico, src/assets],styles: [node_modules/bootstrap/dist/css/bootstrap.min.css,src/styles.css],scripts: []}
}这里 main.ts 就是项目中 JS 文件的入口其中主要的作用就是挂在对应的组件
import { platformBrowserDynamic } from angular/platform-browser-dynamic;// 这个作用类似于 React 中的 App /
import { AppModule } from ./app/app.module;// 这个作用类似于 ReactDOM.render(App /, el);
platformBrowserDynamic().bootstrapModule(AppModule).catch((err) console.error(err));而 AppModule 就是一个 Angular 的组件
组件
首先过一下什么是 Angular 组件(component)抛开具体的实现单纯从概念上来说React, Angular 和 Vue 的组件都是一样的 模块化的代码 可复用的最小代码块 对数据进行处理 最简单的例子就是通过 AJAX 获取数据后渲染给用户看 对用户交互进行反应 这点也可以和上一点进行联动如用户提供了数据之后组件会对数据进行处理并且处理过的数据重新渲染在 UI 上
核心概念虽然是一致的不过具体的实现如使用的模板——React 使用 JSXAngular 使用 HTML template、生命周期、组件内传递数据的方式等则会有所不同。
组件的组成
首先看一下 Angular 项目的 src 结构
❯ tree src
src
├── app
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ └── app.module.ts
├── assets
├── favicon.ico
├── index.html
├── main.ts
└── styles.css3 directories, 9 files这个项目是通过 ng new my-first-app --no-strict --standalone false --routing false 运行的也就是 angular cli 提供的模板文件。这里 app 就是一个组件其中包含了 5 个文件。
其中最重要的两个核心文件为 ___.component.ts 和 ___.module.ts而对大多数的组件来说最核心的是前者的实现大部分的 ___.module.ts 可能并不太会主动去修改。
下面也会解释为什么 css 和 html 并不一定是核心文件的原因
css
当前 CSS 文件是空的
❯ cat src/app/app.component.css
目前的实现来说每个 component 中都可以有对应的 CSS 文件这个对应的 CSS 文件的 作用域(scope) 是当前的组件。
如添加了一个 .header 的 CSS
.header {background-color: #f2f2f2;padding: 20px;text-align: center;
}页面上的显示则是 可以看到样式并不是直接作用于 .header 上而是作用于 .header[_ngcontent-ng-c317606715]后者则是随机生成的 Angular 元素的 属性(attribute,目前观测来看同一个组件都会分享同一个)这样可以有效防止命名冲突的问题
这个 CSS 文件是通过 Component 这个 decorator 导入的使用的属性为 styleUrls接受的参数是一个数组
Component({styleUrls: [./my-component.component.css]
})在要写的 CSS 比较多的情况下一般是会创建一个单独的 ___.component.css 文件但是在 CSS 样式比较短的情况下则可以省略文件直接在 decorator 中添加 styles 即可如
Component({styles: [h1 {color: blue;}button {background-color: green;color: white;}]
})之前看的教程说 styles 和 styleUrls 二者只能存在一个不过现在试了一下如果二者不冲突的话是都会接受的而且当前组件如果没有 CSS 的需求也可以不用放 CSS。
html
这是对应组件的 HTML template内容如下
div styletext-align: centerh1 classheaderWelcome to {{ title }}!/h1imgwidth300altAngular Logosrcdata:image/svgxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg/
/div
h2Here are some links to help you start:/h2
ullih2a target_blank relnoopener hrefhttps://angular.io/tutorialTour of Heroes/a/h2/lilih2a target_blank relnoopener hrefhttps://angular.io/cliCLI Documentation/a/h2/lilih2a target_blank relnoopener hrefhttps://blog.angular.io/Angular blog/a/h2/li
/ul其本身存在的意义就是生成一个对应的 HTML 模板通过 module 导入到对应的 HTML 元素中。以目前的例子来说这个 HTML 模板就是重置 index.html 中的 app-root 元素
每个模板也可以通过 Angular 提供的其他指令与数据的处理层进行交互并完成数据的动态渲染这一趴可以理解成传统的 View 层
一般 HTML Template 通过 Component 中的 templateUrl进行导入
Component({templateUrl: ./my-component.component.html
})在创建的 HTML 元素比较少的情况下也不需要单独创建一个 HTML 模板文件而是使用 template 创建对应的元素即可
Component({template: divh1Hello, {{ name }}!/h1/div
})⚠️尽管和 CSS 文件一样可以用两种方式进行创建但是每个 Component 必须要有一个 template 和 templateUrl。之前看的教程说template 和 templateUrl 只能二选一我试着跑了一下目前的版本是会优先选择 templateUrl 中的内容而不会报错
spec
测试文件目前不打算涉及因此跳过
ts
这个可以理解成 ViewModel 层它主要的作用就是 创建一个组件类 处理元数据(metadata) 这个 metada 指的是创建组件所需要的元数据也就是 Component 这个装饰器所需要的数据 处理逻辑 即处理 HTML Template 中需要渲染的数据并直接与其交互
一个案例代码为
import { Component } from angular/core;Component({selector: app-root,templateUrl: ./app.component.html,styleUrls: [./app.component.css],
})
export class AppComponent {title Hello World;constructor() {}sayHello() {alert(this.title);}
}这里的 Component 是一个 TS decorator说白了也是一个语法糖大致的极简实现如下
class Component {constructor(config) {this.selector config.selector;this.template config.template;this.render();}// 这样就不需要重复实现这个功能了render() {console.log(${this.template} is mounted to ${this.selector});}
}class SomeComponent extends Component {constructor(config) {super(config);}
}const myComponent new SomeComponent({selector: my-component,template: h1Hello, world!/h1,
});这样的调用为
❯ node ang.js
h1Hello, world!/h1 is mounted to my-component我试了一下 TS 的实现
type ComponentProps {selector: string;template: string;
};function Component(config: ComponentProps) {return function T extends new (...args: any[]) any(constructor: T) {return class extends constructor {selector config.selector;template config.template;constructor(...args: any[]) {super(...args);this.render();}render() {console.log(${this.template} is mounted to ${this.selector});}};};
}Component({selector: app-server,template: ./server.component.html,
})
class ServerComponent {}const serverComponent new ServerComponent();不过 TS Playground 上有显示报错就是了不知道不在 TS Playground 能不能跑起来
module
这个文件用来处理当前组件与其他组件的交互并最终返回一个 NgModule 供其他的模块使用
一个案例代码为
import { NgModule } from angular/core;
import { BrowserModule } from angular/platform-browser;import { AppComponent } from ./app.component;NgModule({// Angular 只会渲染 bootstrap 中包含的组件declarations: [AppComponent],// 这里负责导入本模块中 components 要用的模块// 如与表单交互的 FormsModuleimports: [BrowserModule],// service现在暂时用不到用到了再补providers: [],// 这里是导出的组件// React 中只能导出一个组件Angular 则是一个数组bootstrap: [AppComponent],
})
export class AppModule {}⚠️main.ts 中使用的就是这个 AppModule
我个人的理解就是以乐高作对比component就像一个个乐高积木拼成功的一个完成品(比如说 、、 这种)就是一个 NgModuleNgModule 又可以组成更大的 NgModule比如说乐高的城市主题就会包括消防车、飞机、警局等模块。
因此对于大多数项目——也就是中小型项目来说一个应用里面存在一个 app.module.ts 就足够了
新建组件
创建组件有两种方式使用 angular-cli 和 手动创建
手动创建 手动创建一个新的文件夹包含 __component.html 和 __.component.ts 即可 结构如下 ❯ tree src/app/
src/app/
├── app.component.css
├── app.component.html
├── app.component.spec.ts
├── app.component.ts
├── app.module.ts
└── serverï├── server.component.html└── server.component.tsserver 下面的就是新的组件一般命名规范就是这样的 其中 server.component.html 的内容为对应实现的模板 h1Hello from Server/h1server.component.ts 将对应的 HTML Template 挂载到对应的 div 上——这里在这之前需要在 app.component.html 中创建对应的 HTML 元素即 app-server/app-server。server.component.ts 中的代码如下 import { Component } from angular/core;Component({selector: app-server,templateUrl: ./server.component.html,
})
export class ServerComponent {}更新 App.module.ts 中的 declarations 前文提过Angular 只会使用 declarations 中提到的组件因此不更新 declarations无法正确渲染 // 导入让 TS 可以找到 entry
import { ServerComponent } from ./server/server.component;NgModule({// 提供信息给 Angulardeclarations: [AppComponent, ServerComponent],// ...其余不变...
})这个时候 server.component.ts 和 server.component.html 中的内容就可以正确渲染了: 使用 cli
这里使用指令即可
# generate 和 component 分别可以使用 g 和 c 来代替
# component 为 cli 支持创建的类型除此之外还有 directive、service、class 等
# servers 为对应组件的名称想要修改也可以用 folder/component 这样的结构
❯ ng generate component servers
CREATE src/app/servers/servers.component.css (0 bytes)
CREATE src/app/servers/servers.component.html (22 bytes)
CREATE src/app/servers/servers.component.spec.ts (608 bytes)
CREATE src/app/servers/servers.component.ts (203 bytes)
UPDATE src/app/app.module.ts (458 bytes)此时的项目结构为主
❯ tree src/app/
src/app/
├── app.component.css
├── app.component.html
├── app.component.spec.ts
├── app.component.ts
├── app.module.ts
├── server
│ ├── server.component.html
│ └── server.component.ts
└── servers├── servers.component.css├── servers.component.html├── servers.component.spec.ts└── servers.component.ts3 directories, 11 files正常情况下使用 cli 创建的组件会在对应的 module 中被自动添加到 declarations 中去