摘要:我們的應(yīng)用由一個或者多個模塊組成,并且必須要有一個根模塊,我們通常命名為,每個模塊都會有一個叫的裝飾器函數(shù),它接收一個用來描述模塊屬性的元數(shù)據(jù)對象,我們在這個對象屬性上配置我們應(yīng)用所需的組件路由指令管道服務(wù)等。
前言
相信大家在逛技術(shù)論壇或者技術(shù)博客的時候,都會發(fā)現(xiàn)有些寫的很好的文章我們想保存下來以便可以重復(fù)翻閱和查看,在一些相對大的站點,比如SegmentFault或者掘金都會提供類似收藏這樣的功能來幫我們做這個保存的工作,我們以后可以回來重復(fù)查看,但是我們平時瀏覽的站點肯定不止一個,并且有時候一些個人的技術(shù)博客并沒有這樣的功能,我們就只能存瀏覽器書簽這樣做了,這樣我們平時保存下來的一些文章就會比較分散,沒有一個統(tǒng)一的地方來幫我們管理,如果有這樣一個應(yīng)用,我們只要輸入某篇我們想保存的文章的URL地址就可以幫我們生成這篇文章的正文內(nèi)容,并且可以支持標(biāo)簽的分類和搜索等功能就好了,就是基于這個需求和我平時個人的使用經(jīng)驗開發(fā)出了這個應(yīng)用。大家可以進這個地址先體驗一下,賬號是test,密碼123456。該應(yīng)用采用Angular4開發(fā),koa2提供數(shù)據(jù)接口,因為我是Angular的初學(xué)者,邊看官方文檔邊把這個應(yīng)用做了出來的,也遇到了一些問題,下面我大概說一下開發(fā)的過程和遇到的一些問題的解決方案。技術(shù)方案選型如下
Angular 前端框架
Angular Cli 前端打包構(gòu)建
koa2 提供數(shù)據(jù)接口
MongoDB 提供數(shù)據(jù)儲存
phantom 和 node-readability 提供對文章正文的提取
一、項目的初始化Angular是一個正式發(fā)布于16年九月的一個前端框架(其實Angular的定位是一個平臺了),它和vue、react不太一樣的是,Angular不只是針對視圖層的一個庫,它提供的是一個完整的解決方案和生態(tài),它本身內(nèi)置了組件化方案、模塊化方案、測試、表單驗證、路由、國際化和HTTP服務(wù)等,這些東西我們開發(fā)者不用再去糾結(jié)怎么選擇,直接按官方的建議說明走就好了,選擇困難癥患者肯定很喜歡這樣的,但相對的它也就沒有vue和react那么靈活了,這個怎么看待得根據(jù)我們每個人的項目需求來選擇。既然Angular它本身是這么完整的了,它肯定也有CLI工具,那就是Angular CLI,Angular CLI是一個命令行界面工具,它可以創(chuàng)建項目、添加文件以及執(zhí)行一大堆開發(fā)任務(wù),比如測試、打包和發(fā)布。我們可以先執(zhí)行以下命令全局安裝Angular CLI
npm install -g @angular/cli
然后執(zhí)行ng new [ProjectName]就可以初始化一個項目了。
二、模塊化與組件化Angular 應(yīng)用是模塊化的,并且 Angular 有自己的模塊系統(tǒng),它被稱為NgModules。我們的應(yīng)用由一個或者多個模塊組成,并且必須要有一個根模塊,我們通常命名為AppModule,每個模塊都會有一個叫@NgModule的裝飾器函數(shù),它接收一個用來描述模塊屬性的元數(shù)據(jù)對象,我們在這個對象屬性上配置我們應(yīng)用所需的組件、路由、指令、管道、服務(wù)等。然后Angular會引導(dǎo)根模塊來啟動應(yīng)用,有如下代碼
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; import { AppModule } from "./app/app.module"; platformBrowserDynamic().bootstrapModule(AppModule);
Angular應(yīng)用還是組件化的,組件負責(zé)控制屏幕上的一小塊區(qū)域,稱之為視圖,每個組件也有一個叫@Component的裝飾器函數(shù),它也接收一個元數(shù)據(jù)對象,我們可以在該對象屬性上配置組件的模板文件,和組件模板的樣式文件等,看如下代碼
@Component({ selector: "app-root", templateUrl: "./app.component.html", styleUrls: ["./app.component.scss"] })
這樣我們就可以組合不同的組件拼裝起我們整個應(yīng)用了。整體架構(gòu)圖如下
Angular的路由是通過一個叫RouterModule的模塊來配置的,RouterModule在@angular/router這個包里面,所以路由配置模塊RouterModule需要先從@angular/router這個包導(dǎo)出來,然后調(diào)用RouterModule的forRoot方法給他傳進去一個數(shù)組配置對象就好了,需要注意的是我們還要有一個路由來匹配我們所有路由都不配置的情況,它的path應(yīng)該寫成兩個星號
import { Routes, RouterModule } from "@angular/router"; const routes: Routes = [ { path: "index", component: IndexComponent }, { path: "**", redirectTo: "index", pathMatch: "full" } ]) @NgModule({ imports: [RouterModule.forRoot(routes)] ... })
路由配置好后把它的返回值添加到AppModule的imports數(shù)組里面就好了。然后在我們的根組件appComponent的模板里面添加
目錄的劃分我是根據(jù)個人的開發(fā)習(xí)慣來做的,我們的業(yè)務(wù)邏輯的開發(fā)大多在app文件夾下進行,我一般會在app文件夾下新建一個pages文件來做頁面級別組件的存放,然后會分別新建directive、pip、service、animation、interceptor文件夾來存放我們應(yīng)用的指令、管道、服務(wù)、動畫、攔截器,因為這個應(yīng)用我沒有用一些第三方的UI組件庫,一些通用的組件都是自己封裝的,所以還需要一個component文件夾來存放整個應(yīng)用所需的一些通用UI組件,這樣我們整個應(yīng)用的劃分就很清晰了。最后的目錄說明大致如下
app ├── animations // 動畫 │?? └── global-router-animation.ts ├── app-routing.module.ts // 路由的配置文件 ├── app.component.html // 根組件的模板文件 ├── app.component.scss // 根組件的樣式文件 ├── app.component.spec.ts // 根組件的測試文件 ├── app.component.ts // 根組件 ├── app.module.ts // 根模塊 ├── component // 通用的UI組件 ├── button │?? └── dropdown ├── directives // 指令 │?? └── markdown-editor ├── interceptor // 攔截器 │?? └── global-response-interceptor.ts ├── page // 頁面級別的組件 │?? ├── add-link-note │?? ├── add-note │?? ├── classification │?? ├── edit-note │?? ├── index │?? ├── search │?? ├── tag │?? └── view-note └─ services // 服務(wù) ├── loading-bar ├── msg ├── note └── tag五、跨域問題
跨域問題幾乎是現(xiàn)代前端項目都會遇到的了,在vue,react等項目項目中我們可以通過webpack-dev-server的代理配置來解決,Angular CLI創(chuàng)建出來的項目底層也是通過webpack來進行應(yīng)用的打包編譯的,但是Angular CLI把webpack的配置給包裝隱藏起來了,我們可以通過執(zhí)行命令ng eject來暴露出webpack的配置文件,但就為了配置跨域問題就把webpack的配置暴露出來其實沒有必要。我們可以這樣做,先在項目的根目錄地下新建一個proxy.config.json配置文件,在該文件里面寫下如下代碼,告訴Angular,應(yīng)用里面所有以api開頭的HTTP請求都轉(zhuǎn)發(fā)到localhost的3002端口。
{ "/api":{ "target":"http://localhost:3002" } }
寫完該配置文件后我們還需要在package.json的start命令里面加上這個配置
"start" : "ng serve --proxy-config proxy.config.json"
然后執(zhí)行npm run start重啟服務(wù),這樣我們的跨域問題就很簡單的解決了。
六、未解決的問題前面有說過這個應(yīng)用沒有使用一些第三方的UI組件庫,項目中用到的一些UI組件是我自己封裝的,其中有一個LoadingBar組件和message消息提示組件,它的調(diào)用方式應(yīng)該是通過服務(wù)的形式來調(diào)用的,類似如下代碼
this.loadingBar.start() this.msg.info("這是消息提示")
但是在Angular里面服務(wù)本身是不帶模板的,只有組件才有模板,所以這樣的組件應(yīng)該是要通過服務(wù)去動態(tài)的加載一個帶模板的組件,但是我沒有找到相關(guān)的實現(xiàn)方案,去看了一下ng-zorro的源碼沒看懂?,這里希望有大神賜教。最后我的實現(xiàn)是通過最不優(yōu)雅的一種方案,直接在服務(wù)里面是操作DOM了。比如我的LoadingBar服務(wù)
import { Injectable } from "@angular/core"; @Injectable() export class LoadingBarService { constructor() { } public $Loading = { start: function(){ const myLoadingBar = document.querySelector(".my-loading-bar"); if (myLoadingBar !== null && myLoadingBar instanceof HTMLElement) { let LoadingBarDivWidth = 0; this.timer = setInterval(() => { LoadingBarDivWidth++; myLoadingBar.style.width = LoadingBarDivWidth + "vw"; if (LoadingBarDivWidth >= 100) { clearInterval(this.timer); } }, 25); } else { const LoadingBarDiv = document.createElement("div"); LoadingBarDiv.className = "my-loading-bar"; const bodyEl = document.querySelector("body"); bodyEl.appendChild(LoadingBarDiv); let LoadingBarDivWidth = 0; this.timer = setInterval(() => { LoadingBarDivWidth++; LoadingBarDiv.style.width = LoadingBarDivWidth + "vw"; if (LoadingBarDivWidth >= 100) { clearInterval(this.timer); } }, 25); } }, finish: function(){ const myLoadingBar = document.querySelector(".my-loading-bar"); if (myLoadingBar !== null && myLoadingBar instanceof HTMLElement) { clearInterval(this.timer); myLoadingBar.style.width = 0 + "vw"; } } }; }七、打包
在我們整個應(yīng)用開發(fā)完成后我們需要build出靜態(tài)文件交由node來部署,這里有幾個需要注意一下。在CLI生成的項目的編譯配置命令里面是沒有開啟加--prod配置的,需要我們手動去加上命令開啟,加上--prod之后打包出來的資源就不會再有resource map了,這樣文件體積會小很多,如果Angular Cli用的是1.3.0以上的版本還可以加上--build-optimizer(搖樹優(yōu)化),文件體積會更加小,在我做這個項目時用的版本還是1.2.7。最后build的命令配置如下
"build" : "ng build --prod --build-optimizer"八、總結(jié)
本文只是一個Angular新手做的第一個項目的流水總結(jié),并沒有說到什么新意有深度的東西。Angular是一個很好的框架,上手門檻沒有大多數(shù)人想象的那么高,只要你JavaScript基礎(chǔ)扎實,對ES6的語法有基本的了解就可以去學(xué)習(xí),相信會給到你不一樣的開發(fā)體驗。最后奉上項目的基本信息
體驗地址 https://weiweinote.cn/index
GitHub源碼地址 https://github.com/linguowei/micro-note
其實該應(yīng)用如果大家有自己的個人服務(wù)器的話完全可以部署給自己使用,如果沒有也可以部署到國外的一些免費服務(wù)提供商比如heroku上。好啦,如果大家對該項目有什么問題和建議歡迎留言一起討論。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/19088.html
摘要:具體來說,包管理器就是可以通過命令行,幫助你把外部庫和插件放到你的項目里面并在之后進行版本升級,這樣就不用手工復(fù)制和更新庫。現(xiàn)在有的包管理器主要是和。 一、基礎(chǔ) 1、學(xué)習(xí)HTML基礎(chǔ) HTML給你的網(wǎng)頁賦予了結(jié)構(gòu)。它就像是人的骨架那樣讓你保持站立。首先你需要去學(xué)習(xí)語法以及它必須提供的一切。你的學(xué)習(xí)應(yīng)該聚焦在下面這些東西上: 學(xué)習(xí)HTML基礎(chǔ),了解如何編寫語義HTML 理解如何把網(wǎng)頁分...
摘要:具體來說,包管理器就是可以通過命令行,幫助你把外部庫和插件放到你的項目里面并在之后進行版本升級,這樣就不用手工復(fù)制和更新庫?,F(xiàn)在有的包管理器主要是和。 一、基礎(chǔ) 1、學(xué)習(xí)HTML基礎(chǔ) HTML給你的網(wǎng)頁賦予了結(jié)構(gòu)。它就像是人的骨架那樣讓你保持站立。首先你需要去學(xué)習(xí)語法以及它必須提供的一切。你的學(xué)習(xí)應(yīng)該聚焦在下面這些東西上: 學(xué)習(xí)HTML基礎(chǔ),了解如何編寫語義HTML 理解如何把網(wǎng)頁分...
摘要:你們說能不能就用的開發(fā)模式來實現(xiàn)客戶端啊這樣版版版就都有了。有道云筆記可能就是最貼近我們想法的產(chǎn)品,有客戶端,有版。這個項目由發(fā)起和維護。 最近一個多月一直在用 AngularJS 做公司的一個項目(還沒有做完),我之前主要是用 PHP 開發(fā)服務(wù)端的,AngularJS 也是現(xiàn)學(xué)現(xiàn)賣,整個過程還是比較有意義的,覺得很有必要寫篇文章記錄一下。 緣起 事情是這樣的……我們團隊的產(chǎn)品是一款 ...
摘要:你們說能不能就用的開發(fā)模式來實現(xiàn)客戶端啊這樣版版版就都有了。有道云筆記可能就是最貼近我們想法的產(chǎn)品,有客戶端,有版。這個項目由發(fā)起和維護。 最近一個多月一直在用 AngularJS 做公司的一個項目(還沒有做完),我之前主要是用 PHP 開發(fā)服務(wù)端的,AngularJS 也是現(xiàn)學(xué)現(xiàn)賣,整個過程還是比較有意義的,覺得很有必要寫篇文章記錄一下。 緣起 事情是這樣的……我們團隊的產(chǎn)品是一款 ...
閱讀 1772·2021-10-11 10:59
閱讀 2416·2021-09-30 09:53
閱讀 1780·2021-09-22 15:28
閱讀 2804·2019-08-29 15:29
閱讀 1568·2019-08-29 13:53
閱讀 3217·2019-08-29 12:34
閱讀 2865·2019-08-26 10:16
閱讀 2673·2019-08-23 15:16