摘要:模塊庫開發(fā)實(shí)例隨著前端框架的誕生,也會(huì)隨之出現(xiàn)一些組件庫,方便日常業(yè)務(wù)開發(fā)。在瀏覽器中,渲染是將模型映射到視圖的過程。然而視圖可以是頁面中的段落表單按鈕等其他元素,這些頁面元素內(nèi)部使用來表示。
angular模塊庫開發(fā)實(shí)例
隨著前端框架的誕生,也會(huì)隨之出現(xiàn)一些組件庫,方便日常業(yè)務(wù)開發(fā)。今天就聊聊angular4組件庫開發(fā)流程。
下圖是button組件的基礎(chǔ)文件。
nk-button.component.ts為該組件的核心文件,看看代碼:
import {Component, Renderer2, ElementRef, AfterContentInit, ViewEncapsulation, Input} from "@angular/core"; @Component({ selector: "[nk-button]", templateUrl: "./nk-button.component.html", encapsulation: ViewEncapsulation.None, styleUrls: ["./nk-button.component.scss"] }) export class NkButtonComponent implements AfterContentInit { _el: HTMLElement; _prefixCls = "ky-btn"; _type: string; _size: string; _shape: string; _classList: Array= []; @Input() get nkType() { return this._type; } set nkType(value) { this._type = value; this._setClass(); } @Input() get nkSize() { return this._size; } set nkSize(value: string) { this._size = value; this._setClass(); } @Input() get nkShape() { return this._shape; } set nkShape(value: string) { this._shape = value; this._setClass(); } constructor(private _elementRef: ElementRef, private _renderer: Renderer2) { this._el = this._elementRef.nativeElement; this._renderer.addClass(this._el, this._prefixCls); } ngAfterContentInit() { } /** *設(shè)置class屬性 */ _setClass(): void { this._classList = [ this.nkType && `${this._prefixCls}-${this.nkType}`, this.nkSize && `${this._prefixCls}-${this.nkSize}`, this.nkShape && `${this._prefixCls}-${this.nkShape}` ].filter(item => { return item; }); this._classList.forEach(_className => { this._renderer.addClass(this._el, _className); }); } }
針對(duì)核心概念ElementRef、Renderer2、ViewEncapsulation做簡要說明:
ElementRef在應(yīng)用層直接操作 DOM,就會(huì)造成應(yīng)用層與渲染層之間強(qiáng)耦合,通過 ElementRef 我們就可以封裝不同平臺(tái)下視圖層中的 native 元素 (在瀏覽器環(huán)境中,native 元素通常是指 DOM 元素),最后借助于 Angular 提供的強(qiáng)大的依賴注入特性,我們就可以輕松地訪問到 native 元素。
參考鏈接
Renderer2渲染器是 Angular 為我們提供的一種內(nèi)置服務(wù),用于執(zhí)行 UI 渲染操作。在瀏覽器中,渲染是將模型映射到視圖的過程。模型的值可以是 JavaScript 中的原始數(shù)據(jù)類型、對(duì)象、數(shù)組或其它的數(shù)據(jù)對(duì)象。然而視圖可以是頁面中的段落、表單、按鈕等其他元素,這些頁面元素內(nèi)部使用DOM來表示。
參考鏈接
ViewEncapsulationViewEncapsulation 允許設(shè)置三個(gè)可選的值:
ViewEncapsulation.Emulated - 無 Shadow DOM,但是通過 Angular 提供的樣式包裝機(jī)制來封裝組件,使得組件的樣式不受外部影響。這是 Angular 的默認(rèn)設(shè)置。
ViewEncapsulation.Native - 使用原生的 Shadow DOM 特性
ViewEncapsulation.None - 無 Shadow DOM,并且也無樣式包裝
參考鏈接
button組件創(chuàng)建思路:
針對(duì)button我們只需修改其樣式,因此在這里創(chuàng)建屬性指令
提供屬性接口
根據(jù)其傳入的屬性值動(dòng)態(tài)渲染DOM
至此,最簡單的button就開發(fā)結(jié)束。
模塊打包流程 合并html、css到component文件let fs = require("fs"); let pathUtil = require("path"); let sass = require("node-sass"); let filePath = pathUtil.join(__dirname, "src", "temp_components"); let fileArray = []; function fildFile(path) { if (fs.statSync(path).isFile()) { if (/.component.ts/.test(path)) { fileArray[0] = path; } if (/.html$/.test(path)) { fileArray[1] = readFile(path) } if (/.component.scss$/.test(path)) { fileArray[2] = path; } } else if (fs.statSync(path).isDirectory()) { let paths = fs.readdirSync(path); if (fileArray.length === 3) { writeFile(fileArray); fileArray = []; } paths.forEach((p) => { fildFile(pathUtil.join(path, p)); }); } } function readFile(file) { return fs.readFileSync(file); } function writeFile(fileArray) { let file = fileArray[0]; let content = fileArray[1]; let scssPath = fileArray[2]; mergeContent(file, content, scssPath) .then(result => { if (!result) return; fs.writeFile(file, result, function (err) { if (err) console.error(err); console.log("file merge success!"); }) }); } /** * 轉(zhuǎn)換scss * @param path * @returns {Promise} */ function processScss(path) { return new Promise((resolve, reject) => { sass.render({ file: path }, (err, result) => { if (!err) { resolve(result.css.toString()) } else { reject(err); } }) }) } function mergeContent(file, content, scssPath) { let componentContent = readFile(file); let htmlRegex = /(templateUrl *:s*["|"])(.*["|"],?)/g; let scssRegex = /(styleUrls *:s*)([.*],?)/g; let newContent = ""; if (htmlRegex.test(componentContent) && scssRegex.test(componentContent)) { let contentArray = componentContent.toString().split(htmlRegex); contentArray[1] = "template:`"; contentArray[2] = content + "`,"; contentArray.forEach(con => { newContent += con; }) contentArray = newContent.toString().split(scssRegex); return new Promise((resolve, reject) => { processScss(scssPath) .then(result => { newContent = ""; contentArray[1] = "styles:[`"; contentArray[2] = result + "`],"; contentArray.forEach(con => { newContent += con; }) resolve(newContent) }, err => { reject(err); }) }); } } fildFile(filePath);ts編譯(tsconfig-aot.json)
{ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./publish/src", "baseUrl": "./", "declaration": true, "importHelpers": true, "module": "es2015", "sourceMap": false, "target": "es2015", "types": [ "node" ] }, "files": [ "./src/temp_components/ng-kylin.module.ts" ], "angularCompilerOptions": { "annotateForClosureCompiler": true, "strictMetadataEmit": true, "flatModuleOutFile": "index.js", "flatModuleId": "ng-kylin", "skipTemplateCodegen": true } }rollup打包 (rollup-config.js)
import resolve from "rollup-plugin-node-resolve" import replace from "rollup-plugin-replace" const format = process.env.ROLLUP_FORMAT || "es" let globals = { "@angular/animations": "ng.animations", "@angular/cdk": "ng.cdk", "@angular/core": "ng.core", "@angular/common": "ng.common", "@angular/compiler": "ng.compiler", "@angular/forms": "ng.forms", "@angular/platform-browser": "ng.platformBrowser", "moment": "moment", "moment/locale/zh-cn": null, "rxjs/BehaviorSubject": "Rx", "rxjs/Observable": "Rx", "rxjs/Subject": "Rx", "rxjs/Subscription": "Rx", "rxjs/observable/fromPromise": "Rx.Observable", "rxjs/observable/forkJoin": "Rx.Observable", "rxjs/observable/fromEvent": "Rx.Observable", "rxjs/observable/merge": "Rx.Observable", "rxjs/observable/of": "Rx.Observable", "rxjs/operator/auditTime": "Rx.Observable.prototype", "rxjs/operator/catch": "Rx.Observable.prototype", "rxjs/operator/debounceTime": "Rx.Observable.prototype", "rxjs/operator/distinctUntilChanged": "Rx.Observable.prototype", "rxjs/operator/do": "Rx.Observable.prototype", "rxjs/operator/filter": "Rx.Observable.prototype", "rxjs/operator/finally": "Rx.Observable.prototype", "rxjs/operator/first": "Rx.Observable.prototype", "rxjs/operator/map": "Rx.Observable.prototype", "rxjs/operator/pluck": "Rx.Observable.prototype", "rxjs/operator/startWith": "Rx.Observable.prototype", "rxjs/operator/switchMap": "Rx.Observable.prototype", "rxjs/operator/takeUntil": "Rx.Observable.prototype", "rxjs/operator/throttleTime": "Rx.Observable.prototype", } if (format === "es") { globals = Object.assign(globals, { "tslib": "tslib", }) } let input let file switch (format) { case "es": input = "./publish/src/index.js" file = "./publish/esm15/index.js" break case "umd": input = "./publish/esm5/index.js" file = "./publish/bundles/ng-kylin.umd.js" break default: throw new Error(`format ${format} is not supported`) } export default { input, output: { file, format, }, exports: "named", name: "ngKylin", plugins: [replace({ "import * as moment": "import moment" }), resolve()], external: Object.keys(globals), globals, }shell腳本定義執(zhí)行流程(build.sh)
#!/usr/bin/env bash rm -rf ./publish cp -r src/app/components src/temp_components node ./html.merge.js echo "Generating entry file using Angular compiler" $(npm bin)/ngc -p tsconfig-aot.json rm -rf src/temp_components echo "Bundling to es module" export ROLLUP_FORMAT=es $(npm bin)/rollup -c rollup-config.js rm -rf publish/src/*.js rm -rf publish/src/**/*.js sed -e "s/from ".//from "./src//g" publish/src/index.d.ts > publish/index.d.ts sed -e "s/":".//":"./src//g" publish/src/index.metadata.json > publish/index.metadata.json rm publish/src/index.d.ts publish/src/index.metadata.json echo "Transpiling es module to es5" $(npm bin)/tsc --allowJs --importHelpers --target es5 --module es2015 --outDir publish/esm5 publish/esm15/index.js echo "Bundling to umd module" export ROLLUP_FORMAT=umd $(npm bin)/rollup -c rollup-config.js echo "Minifying umd module" $(npm bin)/uglifyjs publish/bundles/ng-kylin.umd.js --output publish/bundles/ng-kylin.umd.min.js echo "Copying package.json" cp package.json publish/package.json
至此,項(xiàng)目打包結(jié)束。
源碼
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89156.html
摘要:如何在中使用動(dòng)畫前端掘金本文講一下中動(dòng)畫應(yīng)用的部分。與的快速入門指南推薦前端掘金是非常棒的框架,能夠創(chuàng)建功能強(qiáng)大,動(dòng)態(tài)功能的。自發(fā)布以來,已經(jīng)廣泛應(yīng)用于開發(fā)中。 如何在 Angular 中使用動(dòng)畫 - 前端 - 掘金本文講一下Angular中動(dòng)畫應(yīng)用的部分。 首先,Angular本生不提供動(dòng)畫機(jī)制,需要在項(xiàng)目中加入Angular插件模塊ngAnimate才能完成Angular的動(dòng)畫機(jī)制...
摘要:正文架構(gòu)概覽正文架構(gòu)概覽接觸大概一個(gè)月吧,期間寫了個(gè)項(xiàng)目,趁現(xiàn)在稍微有點(diǎn)時(shí)間,來回顧梳理一下。里的模塊,并不等同于項(xiàng)目中的模塊概念。當(dāng)然,這只是我目前階段的理解。聲明 本系列文章內(nèi)容梳理自以下來源: Angular 官方中文版教程 官方的教程,其實(shí)已經(jīng)很詳細(xì)且易懂,這里再次梳理的目的在于復(fù)習(xí)和鞏固相關(guān)知識(shí)點(diǎn),剛開始接觸學(xué)習(xí) Angular 的還是建議以官網(wǎng)為主。 因?yàn)檫@系列文章,更多的會(huì)...
摘要:延伸閱讀學(xué)習(xí)與實(shí)踐資料索引與前端工程化實(shí)踐前端每周清單半年盤點(diǎn)之篇前端每周清單半年盤點(diǎn)之與篇前端每周清單半年盤點(diǎn)之篇 前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為新聞熱點(diǎn)、開發(fā)教程、工程實(shí)踐、深度閱讀、開源項(xiàng)目、巔峰人生等欄目。歡迎關(guān)注【前端之巔】微信公眾號(hào)(ID:frontshow),及時(shí)獲取前端每周清單;本文則是對(duì)于半年來發(fā)布的前端每周清單...
摘要:首先,要確認(rèn)安裝了,并且創(chuàng)建了目錄并執(zhí)行初始化。想必看見上面的那么多包會(huì)一臉懵逼,沒關(guān)系,我第一眼看見這些的那刻,和你現(xiàn)在的表情一樣,下面在適當(dāng)?shù)臅r(shí)候我會(huì)逐個(gè)解釋的,你只需要相信我上面的包都是跑所必須的,缺一不可。 關(guān)于介紹,只說一句:Angular 2是一個(gè)強(qiáng)大、全面、龐大的MVVM框架。 安裝 安裝,也算是一個(gè)坎,因?yàn)槟阈枰惭b一大堆東西,卻不知道每個(gè)東西是做什么的,盡管有Angu...
摘要:相比于開發(fā)人員的數(shù)量,目前框架類庫和工具的數(shù)量似乎更多一些。本文將會(huì)討論目前最為流行的客戶端框架類庫和工具以及它們之間的基本差異。典型的類庫包括字符串處理日期元素事件動(dòng)畫網(wǎng)絡(luò)請(qǐng)求等功能。所以不需要明確的區(qū)分類庫框架和工具。 相比于JavaScript開發(fā)人員的數(shù)量,目前JavaScript框架、類庫和工具的數(shù)量似乎更多一些。截至2017年5月,GitHub上的快速搜索顯示,有超過110...
閱讀 1245·2021-11-25 09:43
閱讀 1350·2021-09-26 09:55
閱讀 2410·2021-09-10 11:20
閱讀 3383·2019-08-30 15:55
閱讀 1458·2019-08-29 13:58
閱讀 1181·2019-08-29 12:36
閱讀 2356·2019-08-29 11:18
閱讀 3420·2019-08-26 11:47