欧美亚洲综合图区在线|天天射天天干国产成卜|99久久免费国产精精品|国产的欧美一区二区三区|日韩中文字幕无码不卡专区|亚麻成人aV极品一区二区|国产成人AV区一区二区三|成人免费一区二区三区视频网站

當(dāng)前位置:首頁(yè) > 網(wǎng)站建設(shè) > 正文內(nèi)容

前端模板引擎有哪些(前端模板引擎一般用來(lái)開(kāi)發(fā)什么)

網(wǎng)站建設(shè)2年前 (2023-03-05)1318

今天給各位分享前端模板引擎有哪些的知識(shí),其中也會(huì)對(duì)前端模板引擎一般用來(lái)開(kāi)發(fā)什么進(jìn)行解釋,如果能碰巧解決你現(xiàn)在面臨的問(wèn)題,別忘了關(guān)注本站,現(xiàn)在開(kāi)始吧!

本文目錄一覽:

現(xiàn)在前端流行的框架有什么??

現(xiàn)在前端主要流行三大框架。給大家具體分析一下這三個(gè)前端框架:

1、Angular

大家眼里比較“叼”的框架,甚至有人說(shuō)三大框架中只有她能稱的上一個(gè)完整的框架,因?yàn)樗臇|西比較完善,包含模板,數(shù)據(jù)雙向綁定,路由,模塊化,服務(wù),過(guò)濾器,依賴注入等所有功能。對(duì)于剛開(kāi)始學(xué)習(xí)使用框架的小伙伴們,可以推薦這個(gè)框架,學(xué)會(huì)之后簡(jiǎn)直能顛覆之前你對(duì)前端開(kāi)發(fā)的認(rèn)知。使用 TypeScript能夠提高代碼可維護(hù)性,有利于后期重構(gòu)。雙向數(shù)據(jù)流很方便,但是等業(yè)務(wù)復(fù)雜之后,你可能就搞不清楚數(shù)據(jù)流了。還有令人不開(kāi)心的臟值檢查,以及directive的封裝并沒(méi)有解決視圖與數(shù)據(jù)關(guān)系完全分離,有時(shí)候還要用$digist強(qiáng)制觸發(fā)檢測(cè)。

2、React

這個(gè)框架本身比較容易理解,他的結(jié)構(gòu)很清晰,就是由十幾個(gè)API組成,然后異步渲染,我們只需要處理好接口和維護(hù)就好了,但是很多人反映上手還是有一定的的難度的。React是單向數(shù)據(jù)流,代碼寫(xiě)起來(lái)會(huì)較雙向數(shù)據(jù)流的多一些,但是同樣的排查問(wèn)題時(shí)思路清晰很多。

3、Vue

號(hào)稱是最簡(jiǎn)單,最容易上手的框架,同時(shí)也是行內(nèi)的大趨勢(shì),還可以用來(lái)開(kāi)發(fā)最火的小程序。畢竟用這神器,代碼碼的飛快,項(xiàng)目也能快速上線。同時(shí)他也是雙向數(shù)據(jù)流。有些人認(rèn)為Vue是Angular和React的結(jié)合,既有Angular的模板語(yǔ)法也有React的組件化體系。

當(dāng)你學(xué)會(huì)其中某個(gè)框架之后,你再轉(zhuǎn)用其他框架的時(shí)候,學(xué)會(huì)是很容易的,因?yàn)榉椒ǘ际谴笸‘惖?。具體的使用還是得看公司的項(xiàng)目適合或者要求哪個(gè)框架。

前端開(kāi)發(fā)主要學(xué)習(xí)那些技術(shù)以適應(yīng)工作需求?

一、前端是什么?

前端即網(wǎng)站前臺(tái)部分,也叫前端開(kāi)發(fā),運(yùn)行在PC端,移動(dòng)端等瀏覽器上展現(xiàn)給用戶瀏覽的網(wǎng)頁(yè)。隨著互聯(lián)網(wǎng)技術(shù)的發(fā)展,HTML5,CSS3,前端框架的應(yīng)用,跨平臺(tái)響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)能夠適應(yīng)各種屏幕分辨率,完美的動(dòng)效設(shè)計(jì),給用戶帶來(lái)極高的用戶體驗(yàn)。

核心技術(shù)是前端開(kāi)發(fā)中最基本也是最必須的三個(gè)技能。前端的開(kāi)發(fā)中,在頁(yè)面的布局時(shí), HTML將元素進(jìn)行定義,CSS對(duì)展示的元素進(jìn)行定位,再通過(guò)JavaScript實(shí)現(xiàn)相應(yīng)的效果和交互。雖然表面看起來(lái)很簡(jiǎn)單,但這里面需要掌握的東西絕對(duì)不會(huì)少。在進(jìn)行開(kāi)發(fā)前,需要對(duì)這些概念弄清楚、弄明白,這樣在開(kāi)發(fā)的過(guò)程中才會(huì)得心應(yīng)手。

二、前端都需要學(xué)什么(可以分為八個(gè)階段)?

1、第一階段:

? HTML+CSS:

HTML進(jìn)階、 CSS進(jìn)階、p+CSS布局、HTML+CSS整站開(kāi)發(fā)、

? JavaScript基礎(chǔ):

Js基礎(chǔ)教程、js內(nèi)置對(duì)象常用方法、常見(jiàn)DOM樹(shù)操作大全、ECMAscript、DOM、BOM、定時(shí)器和焦點(diǎn)圖。

? JS基本特效:

常見(jiàn)特效、例如:tab、導(dǎo)航、整頁(yè)滾動(dòng)、輪播圖、JS制作幻燈片、彈出層、手風(fēng)琴菜單、瀑布流布局、滾動(dòng)事件、滾差視圖。

? JS高級(jí)特征:

正則表達(dá)式、排序算法、遞歸算法、閉包、函數(shù)節(jié)流、作用域鏈、基于距離運(yùn)動(dòng)框架、面向?qū)ο蠡A(chǔ)、

? JQuery:基礎(chǔ)使用

懸著器、DOM操作、特效和動(dòng)畫(huà)、方法鏈、拖拽、變形、JQueryUI組件基本使用。

2、第二階段:HTML5和移動(dòng)Web開(kāi)發(fā)

? HTML5:

HTML5新語(yǔ)義標(biāo)簽、HTML5表單、音頻和視頻、離線和本地存儲(chǔ)、SVG、Web Socket、Canvas.

? CSS3:

CSS3新選擇器、偽元素、臉色表示法、邊框、陰影、flex布局、background系列屬性改變、Transition、動(dòng)畫(huà)、景深和深透、3D效果制作、Velocity.js框架、元素進(jìn)場(chǎng)、出場(chǎng)策略、炫酷CSS3網(wǎng)頁(yè)制作。

? Bootstrap:

響應(yīng)式概念、媒體查詢、響應(yīng)式網(wǎng)站制作、刪格系統(tǒng)、刪格系統(tǒng)原理、Bootstrap常用模板、LESS和SASS。

? 移動(dòng)Web開(kāi)發(fā):

跨終端WEB和主流設(shè)備簡(jiǎn)介、視口、流式布局、彈性盒子、rem、移動(dòng)終端JavaScript事件、手機(jī)中常見(jiàn)JS效果制作、手機(jī)聚劃算頁(yè)面、手機(jī)滾屏。

3、第三階段:HTTP服務(wù)和AJAX編程

? WEB服務(wù)器基礎(chǔ):

服務(wù)器基礎(chǔ)知識(shí)、Apache服務(wù)器和其他WEB服務(wù)器介紹、Apache服務(wù)器搭建、HTTP介紹。

? AJAX上篇:

Ajax簡(jiǎn)介和異步的概念、Ajax框架的封裝、XMLHttpRequest對(duì)象詳細(xì)介紹方法、兼容性處理方法、Ajax框架的封裝、Ajax中緩存問(wèn)題、XML介紹和使用、會(huì)處理簡(jiǎn)單的GET或者POST請(qǐng)求、

? AJAX下篇:

JSON和JSON解析、數(shù)據(jù)綁定和模板技術(shù)、JSONP、跨域技術(shù)、圖片預(yù)讀取和lazy-load技術(shù)、JQuery框架中的AjaxAPI、使用Ajax實(shí)現(xiàn)爆布流案例額。

4、第四階段:面向?qū)ο筮M(jìn)階

? 面向?qū)ο蠼K極篇:

從內(nèi)存角度到理解JS面向?qū)ο?、基本類型、?fù)雜類型、原型鏈、ES6中的面向?qū)ο?、ES6中變量的作用域(let ,const(聲明變量只讀),塊級(jí)作用域),ES6中函數(shù)新特性。

? 面向?qū)ο笕筇卣鳎?/p>

繼承性、多態(tài)性、封裝性。

? 面向?qū)ο笾袆?chuàng)建對(duì)象的五種方法:

自定義對(duì)象 、工廠模式創(chuàng)建對(duì)象、構(gòu)造函數(shù)、 混合模式創(chuàng)造對(duì)象、JSO格式創(chuàng)建對(duì)象。

5、第五階段:封裝一個(gè)屬于自己的框架

? 框架封裝基礎(chǔ):

事件流、冒泡、捕獲、事件對(duì)象、事件框架、選擇框架。

? 框架封裝中級(jí):

運(yùn)動(dòng)原理、單物體運(yùn)動(dòng)框架、多物體運(yùn)動(dòng)框架、運(yùn)動(dòng)框架面向?qū)ο蠓庋b。

? 框架封裝高級(jí)和補(bǔ)充:

JQuery框架雛形、可擴(kuò)展性、模塊化、封裝屬于傳智自己的框架。

6、第六階段:模塊化組件開(kāi)發(fā)

? 面向組件編程:

面向組件編程的方式、面向組件編程的實(shí)現(xiàn)原理、面向組件編程實(shí)戰(zhàn)、基于組件化思想開(kāi)發(fā)網(wǎng)站應(yīng)用程序。

? 面向模塊編程:

AMD設(shè)計(jì)規(guī)范、CMD設(shè)計(jì)規(guī)范、RequireJS,LoadJS、淘寶的SeaJS。

7、第七階段:主流的流行框架

? Web開(kāi)發(fā)工作流:

GIT/SVN、Vue-cli腳手架、NPM/Bower依賴管理工具、Grunt/Gulp/Webpack。

? 前端主流框架:

Vue.js、Angular.js、React.JS、Bootstrap。

? 常用庫(kù):

React.js、Vue.js、JQuery.js。

8、第八階段:Node.js全棧開(kāi)發(fā):

? 快速入門:

Node.js發(fā)展、生態(tài)圈、Io.js、Linux/Windows/OS X環(huán)境配置、REPL環(huán)境和控制臺(tái)程序、異步編程,非阻塞I/O、模塊概念,模塊管理工具、開(kāi)發(fā)流程,調(diào)試,測(cè)試。

? 核心模塊和對(duì)象:

全局對(duì)象global,process,console,util、事件驅(qū)動(dòng),事件發(fā)射器、加密解密,路徑操作,序列化和反序列化、文件流操作、HTTP服務(wù)端與客戶端、Socket.IO。

? Web開(kāi)發(fā)基礎(chǔ):

HTTP協(xié)議,請(qǐng)求響應(yīng)處理過(guò)程、關(guān)系型數(shù)據(jù)庫(kù)操作和數(shù)據(jù)訪問(wèn)、非關(guān)系型數(shù)據(jù)庫(kù)操作和數(shù)據(jù)訪問(wèn)、原生的Node.js開(kāi)發(fā)Web應(yīng)用程序、Web開(kāi)發(fā)工作流、Node.js開(kāi)發(fā)Blog案例。

? 快速開(kāi)發(fā)框架:

Express簡(jiǎn)介+MVC簡(jiǎn)介、Express常用API、Express路由模塊、Jade/Ejs模板引擎、使用Express重構(gòu)Blog案例、Koa等其他常見(jiàn)MVC框架。

? Node.js開(kāi)發(fā)電子商務(wù)實(shí)戰(zhàn):

需求與設(shè)計(jì)、賬戶模塊注冊(cè)登錄、會(huì)員中心模塊、前臺(tái)展示模塊、購(gòu)物車,訂單結(jié)算、在線客服即時(shí)通訊模塊。

前端技術(shù)棧有哪些

給大家介紹下web前端開(kāi)發(fā)需要掌握的知識(shí)點(diǎn),可以參考下。

1、PC端頁(yè)面制作與動(dòng)畫(huà)特效

學(xué)習(xí)HTML+CSS搭建網(wǎng)頁(yè)、CSS動(dòng)畫(huà)特效、PhotoShop切圖等基礎(chǔ)知識(shí),獲得初級(jí)Web前端工程師技能,主要進(jìn)行PC端網(wǎng)頁(yè)制作與樣式設(shè)計(jì)實(shí)現(xiàn),能夠配合UI設(shè)計(jì)師進(jìn)行項(xiàng)目開(kāi)發(fā)。

2、移動(dòng)端頁(yè)面制作與響應(yīng)式實(shí)現(xiàn)

講解移動(dòng)端布局與設(shè)備適配、響應(yīng)式設(shè)計(jì)與實(shí)現(xiàn)等,獲得移動(dòng)端頁(yè)面適配工程師技能,主要進(jìn)行移動(dòng)端網(wǎng)頁(yè)的布局制作與樣式設(shè)計(jì)實(shí)現(xiàn)??梢赃m配各種手機(jī)尺寸,并能利用響應(yīng)式進(jìn)行移動(dòng)端與PC端適配。

3、JavaScript與jQuery開(kāi)發(fā)

同HTML5基礎(chǔ)知識(shí)一樣,JavaScript開(kāi)發(fā)與jQuery開(kāi)發(fā)是職業(yè)晉升必備的技能包,獲得中級(jí)Web開(kāi)發(fā)工程師技能,主要進(jìn)行頁(yè)面行為交互,實(shí)現(xiàn)網(wǎng)站常見(jiàn)特效,加輪播圖,選項(xiàng)卡,拖拽效果等,并能配合UI和后端進(jìn)行項(xiàng)目開(kāi)發(fā)。

4、HTML5高級(jí)框架技術(shù)開(kāi)發(fā)

常用的Vue框架開(kāi)發(fā),React框架開(kāi)發(fā),Angular框架開(kāi)發(fā),數(shù)據(jù)可視化技術(shù)。可獲得中級(jí)Web前端工程師技能,主要適用框架開(kāi)發(fā)企業(yè)項(xiàng)目,實(shí)現(xiàn)單頁(yè)面應(yīng)用開(kāi)發(fā)??梢酝瓿蓮?fù)雜的數(shù)據(jù)交互應(yīng)用場(chǎng)景,具備獨(dú)立開(kāi)發(fā)項(xiàng)目能力。

5、全棧前后端技術(shù)開(kāi)發(fā)

Node.JS技術(shù),其他后端技術(shù),如Java或PHP??色@得高級(jí)Web前端工程師技能,主要進(jìn)行前后端全棧樣式開(kāi)發(fā),能獨(dú)立完成一個(gè)中小型項(xiàng)目的前后臺(tái),對(duì)于網(wǎng)站開(kāi)發(fā)有著非常熟練的編程能力。

可以從零開(kāi)始,一步步的掌握前端開(kāi)發(fā)的各項(xiàng)相關(guān)技能,最終達(dá)到企業(yè)對(duì)初級(jí)前端開(kāi)發(fā)工程師、中級(jí)前端開(kāi)發(fā)工程師、高級(jí)開(kāi)發(fā)工程師等職位的要求。

js模板引擎事件怎么解決

前端

深入node.js 3 模板引擎原理 事件 文件操作 可讀流的實(shí)現(xiàn)原

模板引擎是基于new Function + with 實(shí)現(xiàn)的。

ejs使用

實(shí)現(xiàn):

思路:借助fs的readFile先讀取文件內(nèi)容,然后使用正則表達(dá)式替換掉即可。

打印的結(jié)果是一樣的。

復(fù)雜的情況呢?拼接字符串,拼成想要的代碼

主要難點(diǎn)就是在字符串的拼接,第二部分,將全文分為三部分,然后拼接對(duì)應(yīng)的,如

let str = "";

with(obj){

str+= `!DOCTYPE html

html lang="en"

head

meta charset="UTF-8"

meta http-equiv="X-UA-Compatible" content="IE=edge"

meta name="viewport" content="width=device-width, initial-scale=1.0"

titleDocument/title

/head

body

`

arr.forEach(item={

str+=`

li

${item}

/li

`

})

str+=`

/body

/html`}

return str

登錄后復(fù)制

這就是拼出來(lái)的字符串,然后再new Function,包裹一層函數(shù),將with的obj傳入,返回str。

大概長(zhǎng)這樣。

效果就是:

所以本質(zhì)就是將獲取到的內(nèi)容,使用正則表達(dá)式匹配,拼接字符串成我們想要的內(nèi)容,用with包裹,改變內(nèi)部作用域,再通過(guò)new Function將str包裝成一個(gè)函數(shù),傳入對(duì)應(yīng)的值給obj。然后運(yùn)行之后str就能正常通過(guò)作用域獲取值賦值。

buffer

在服務(wù)端,需要一個(gè)東西來(lái)標(biāo)識(shí)內(nèi)存,但不能是字符串,因?yàn)樽址疅o(wú)法標(biāo)識(shí)圖片。node中使用buffer來(lái)標(biāo)識(shí)內(nèi)存的數(shù)據(jù)。他把內(nèi)存轉(zhuǎn)換成了16進(jìn)制來(lái)顯示(16進(jìn)制比較短)buffer每個(gè)字節(jié)的取值范圍就是0-0xff(十進(jìn)制的255).

node中buffer可以和字符串任意的轉(zhuǎn)換(可能出現(xiàn)亂碼)

編碼規(guī)范:ASCII - GB8030/GBK - unicode - UTF8

Buffer代表的是內(nèi)存,內(nèi)存是一段固定空間,產(chǎn)生的內(nèi)存是固定大小,不能隨意增加。

擴(kuò)容:需要?jiǎng)討B(tài)創(chuàng)建一個(gè)新的內(nèi)存,把內(nèi)容遷移過(guò)去。

創(chuàng)建一個(gè)長(zhǎng)度為5的buffer,有點(diǎn)像數(shù)組,但是數(shù)組可以擴(kuò)展,而buffer不可以擴(kuò)展。

還有一種聲明buffer。

Buffer.form。

一般使用alloc來(lái)聲明一個(gè)buffer,或者把字符串轉(zhuǎn)換成Buffer使用。文件操作也是采用Buffer形式。

buffer使用

無(wú)論是二進(jìn)制還是16進(jìn)制,表現(xiàn)得東西是一樣的。

base64編碼:

base64可以放在任何路勁的鏈接里,可以減少請(qǐng)求次數(shù)。但是文件大小會(huì)變大。比如webpack中的asset/type,把一些小的文件轉(zhuǎn)換成了Base64編碼內(nèi)嵌到了文件當(dāng)中,雖然可以減少請(qǐng)求次數(shù),但也增大了文件的大小。

base64的來(lái)源就是將每個(gè)字節(jié)都轉(zhuǎn)化為小于64的值。沒(méi)有加密功能,因?yàn)橐?guī)則很簡(jiǎn)單。如

第一步:將buffer中每個(gè)位置的值轉(zhuǎn)為二進(jìn)制。如上。

一個(gè)字節(jié)有八位,八位的最大值是255,有可能超過(guò)64。而base64編碼是要將每個(gè)字節(jié)轉(zhuǎn)化為小于64的值。所以就取每個(gè)字節(jié)的6位。6位的最大值就是2*6 - 1 = 63。也就是:

第二步:將38的形式轉(zhuǎn)成64的,保證每個(gè)字節(jié)小于64。將其轉(zhuǎn)為十進(jìn)制。

第三步,通過(guò)特定的編碼規(guī)則轉(zhuǎn)換即完成。

將我們獲取到的十進(jìn)制傳入,因?yàn)槊總€(gè)字節(jié)都是小于64的,所以不超過(guò)。

完成。

buffer的常用方法

除了form和alloc還有

slice

// slice

const a = Buffer.from([1,2,3,4,5])

const d = a.slice(0,2)

d[1] = 4

console.log(d);

console.log(a);

登錄后復(fù)制

與數(shù)組的用法相同,但是他并不是淺復(fù)制,而是直接關(guān)聯(lián)在一起。改變d也會(huì)改變a。而數(shù)組的slice是淺復(fù)制。改變?cè)紨?shù)據(jù)的值不會(huì)改變。

copy

將Buffer的數(shù)據(jù)拷貝到另一個(gè)數(shù)據(jù)上。

const a = Buffer.from([1, 2, 3, 4, 5]);

const d = Buffer.alloc(5);

a.copy(d, 1, 2, 3); //四個(gè)參數(shù),拷貝到哪里?從d的第一個(gè)開(kāi)始拷貝 a的a[2]-a[3]

console.log(d);

登錄后復(fù)制

copy四個(gè)參數(shù),分別是拷貝的目標(biāo)d。從d的第幾個(gè)長(zhǎng)度開(kāi)始??截恆的第2到第3位。

所以應(yīng)該是 Buffer 00 03 00 00 00

concat

用于拼接buffer

Buffer.concat(arr, index)

第二個(gè)參數(shù)是拼接出來(lái)的Buffer的長(zhǎng)度,如果大于原本的長(zhǎng)度,用00填寫(xiě)。

Buffer.myConcat = function (

bufferList,

length = bufferList.reduce((a, b) = a + b.length, 0)

) {

let bigBuffer = Buffer.alloc(length);

let offset = 0;

bufferList.forEach((item) = {

//使用copy每次拷貝一份然后offset向下走。

item.copy(bigBuffer, offset);

offset += item.length;

});

return bigBuffer

};

登錄后復(fù)制

借助copy,逐個(gè)拷貝一份即可。

文件操作

fs模塊有兩種基本api,同步,異步。

io操作,input,output,輸入輸出。

讀取時(shí)默認(rèn)是buffer類型。

寫(xiě)入的時(shí)候,默認(rèn)會(huì)將內(nèi)容以u(píng)tf8格式寫(xiě)入,如果文件不存在則創(chuàng)建。

讀取的data是Buffer類型,寫(xiě)入的是utf8格式。

這種讀寫(xiě)適合小文件

讀取文件某段內(nèi)容的辦法

fs.open用于打開(kāi)一個(gè)文件。fs.read用來(lái)讀取內(nèi)容并且寫(xiě)入到buffer中。

fs.write用于將內(nèi)容寫(xiě)入某個(gè)文件之中。如上,打開(kāi)了b.txt,然后用fs.wirte。五個(gè)參數(shù),分別是fd,buffer,從buffer的第0個(gè)位置,到buffer的第0個(gè)位置,從b.txt的第0位開(kāi)始寫(xiě),回調(diào)函數(shù)。

寫(xiě)入成功。

這種寫(xiě)法也不太美觀,每次都需要fs.open然后fs.read或者fs.wirte,容易造成回調(diào)地獄。

流 Stream的出現(xiàn)

源碼的實(shí)現(xiàn)步驟:

fs的CreateReadStrem是new了一個(gè)ReadStream,他是基于Stream的Readable類的,然后自己實(shí)現(xiàn)了_read方法。供Stream.prototype.read調(diào)用。

1 內(nèi)部會(huì)先open文件,然后直接直接繼續(xù)讀取操作,默認(rèn)是調(diào)用了pause暫停。

2 監(jiān)聽(tīng)用戶是否綁定了data事件,resume,是的話開(kāi)始讀取事件

3 調(diào)用fs.read 將數(shù)據(jù)讀取出來(lái)。

4 調(diào)用this.push去emit data事件,然后判斷是否可以讀取更多再去讀取。

第一種: fs.readFile(需要將文件讀取到磁盤中,占用內(nèi)容)=fs.wirteFile

第二種: fs.open = fs.read = fs.write 回調(diào)地獄。

實(shí)現(xiàn)讀取三個(gè)字節(jié)寫(xiě)入三個(gè)字節(jié)。采用fs.open fs.read fs.write的方法。

實(shí)現(xiàn)copy方法。

看實(shí)現(xiàn):

首先創(chuàng)建一個(gè)三字節(jié)的Buffer。

然后使用fs.open打開(kāi)要讀取和要寫(xiě)入的文件。

因?yàn)槲覀兪敲咳齻€(gè)每三個(gè)讀取,所以需要采用遞歸方式,一直讀取文件。

直到讀取完畢,調(diào)用回調(diào)函數(shù)。fs.read和fs.write的參數(shù)都是類似的,即fd,buffer,buffer的start,buffer的end,讀取文件/寫(xiě)入文件的start、回調(diào)函數(shù)(err,真正讀取到的個(gè)數(shù)/真正寫(xiě)入的個(gè)數(shù))

現(xiàn)在基本實(shí)現(xiàn)了讀一部分,寫(xiě)一部分,但是讀寫(xiě)的邏輯寫(xiě)在一起了,需要把他拆開(kāi)。

流 Stream模塊

可讀流

不是一下子把文件都讀取完畢,而是可以控制讀取的個(gè)數(shù)和讀取的速率。

流的概念跟fs沒(méi)有關(guān)系,fs基于stream模塊底層擴(kuò)展了一個(gè)文件讀寫(xiě)方法。

所以fs.open,fs.read等需要的參數(shù),createReadStream也需要、

返回一個(gè)對(duì)象,獲取需要監(jiān)聽(tīng)data事件。

close事件在end事件之后觸發(fā)。

由此可以看出:流的內(nèi)部基于 fs.open fs.close fs.read fs.write以及事件機(jī)制。

暫停是不再觸發(fā)data事件

rs.resume()是恢復(fù)。

實(shí)現(xiàn)readStream

從vscode調(diào)試源碼得知

實(shí)現(xiàn)思路:

createReadStream內(nèi)部new了一個(gè)ReadStream的實(shí)例,ReadStream是來(lái)自于Stream模塊。

做一系列參數(shù)默認(rèn)后, 調(diào)用this.open方法,這個(gè)方法會(huì)去調(diào)用fs.open去打開(kāi)文件,打開(kāi)之后觸發(fā)事件,從回調(diào)的形式發(fā)布訂閱模式,然后監(jiān)聽(tīng)事件,當(dāng)發(fā)現(xiàn)有用戶注冊(cè)了data事件之后,調(diào)用fs.read,j監(jiān)聽(tīng)open事件,在open之后再去讀取文件等等。

這樣我們的讀寫(xiě)邏輯就分離開(kāi)了,從回調(diào)的形式變成了發(fā)布訂閱模式,有利于解耦。

第一步:

第一步:參數(shù)初始化,并調(diào)用fs.open

open打開(kāi)之后會(huì)觸發(fā)open事件,注意,這里是異步的

第二步: 監(jiān)聽(tīng)用戶注冊(cè)的data事件,當(dāng)用戶注冊(cè)了data事件才去調(diào)用fs.read。調(diào)用this.read的時(shí)候open還沒(méi)完成。

所以第一次read的時(shí)候需要判斷,然后只監(jiān)聽(tīng)一次open事件,重復(fù)打開(kāi)read事件。

這個(gè)end和start配合,表示讀取文件從哪到哪的位置,但是end是包后的,比如上面的end為4,實(shí)際上讀取到的是5。

創(chuàng)建buffer存放讀取的內(nèi)容,再判斷應(yīng)該讀取多少內(nèi)容,以哪個(gè)小為準(zhǔn)。

然后打開(kāi)fs.read。將讀取到的buffer發(fā)布出去。再次調(diào)用this.read去繼續(xù)讀取。

start=1,end=4,讀取到2345的內(nèi)容,正確。

不給end,每次3個(gè)3個(gè)的讀取。

接著實(shí)現(xiàn)暫停,需要一個(gè)開(kāi)關(guān)。

這樣就基本完成了。

總結(jié):

一開(kāi)始實(shí)現(xiàn)的的copy方法,也是利用fs.open, fs.read, fs.write等,通過(guò)回調(diào)的形式完成的,這樣雖能完成,但是內(nèi)聚度較高,容易形成回調(diào)地獄。

而基于fs模塊,和events模塊,實(shí)現(xiàn)的可讀流,可以有效的解耦剛才的代碼,通過(guò)發(fā)布訂閱模式,在一開(kāi)始訂閱事件,在每個(gè)時(shí)間點(diǎn)對(duì)應(yīng)發(fā)布事件,然后代碼執(zhí)行,各司其職。

open和close是文件流獨(dú)有的,

可讀流具備:on (‘data’ | ‘end’ | ‘error’), resume, pause這些方法。

相關(guān)代碼:

// copy

const fs = require("fs");

const path = require("path");

// let buf = Buffer.alloc(3);

// //open打開(kāi)一個(gè)文件,第一個(gè)參數(shù)是路勁,第二個(gè)參數(shù)是打開(kāi)文件用途,第三個(gè)是回調(diào)函數(shù)。

// fs.open(path.resolve(__dirname, "a.txt"), "r", function (err, fd) {

// // fd 是file descriptor文件描述

// console.log("fd", fd);

// //讀取a.txt的內(nèi)容,并且將內(nèi)容寫(xiě)入buf中的第0個(gè)位置到3第三個(gè)位置,從a.txt的第六個(gè)位置開(kāi)始

// fs.read(fd, buf, 0, 3, 3, function (err, data) {

// fs.open(path.resolve(__dirname, "./b.txt"), "w", function (err, fd2) {

// fs.write(fd2, buf, 0, 3, 0, function (err, data2) {

// console.log("buf", buf);

// console.log("data2", data2);

// });

// });

// });

// });

function copy(source, target, cb) {

const BUFFER_SIZE = 3;

const buffer = Buffer.alloc(BUFFER_SIZE);

//每次讀入文件的位置

let r_offset = 0;

//每次寫(xiě)入新文件的位置

let w_offset = 0;

//讀取一部分?jǐn)?shù)據(jù),寫(xiě)入一部分?jǐn)?shù)據(jù)

//第三個(gè)參數(shù)可以是權(quán)限 權(quán)限有三個(gè)組合 rwx 可讀可寫(xiě)可執(zhí)行 r的權(quán)限是4,w的權(quán)限是2,x的權(quán)限是1 421 = 777 可寫(xiě)可讀可執(zhí)行

// 0o666表示最大的權(quán)限,默認(rèn)不用寫(xiě)。

//讀取的文件必須要存在。寫(xiě)入文件不存在會(huì)創(chuàng)建,如果文件有內(nèi)容會(huì)清空。

fs.open(source, "r", function (err, fd1) {

//打開(kāi)寫(xiě)的文件

fs.open(target, "w", function (err, fd2) {

//每次讀取三個(gè)寫(xiě)入三個(gè),回調(diào)的方式實(shí)現(xiàn)的功能,需要用遞歸

// 同步代碼則可以采用while循環(huán)

function next() {

fs.read(

fd1,

buffer,

0,

BUFFER_SIZE,

r_offset,

function (err, bytesRed) {

// bytesRed真正讀取到的個(gè)數(shù)

if (err) {

cb("讀取失敗");

return;

}

if (bytesRed) {

//將讀取到的內(nèi)容寫(xiě)入target目標(biāo)

fs.write(

fd2,

buffer,

0,

bytesRed,

w_offset,

function (err, written) {

if (err) retrun;

// written 真正寫(xiě)入的個(gè)數(shù)

r_offset += bytesRed; //每次寫(xiě)入之后,下一次讀取的內(nèi)容就該往前進(jìn)

w_offset += written;

next();

}

);

} else {

//讀取內(nèi)容為空,結(jié)束

fs.close(fd1, () = {});

fs.close(fd2, () = {});

cb();

}

}

);

}

next();

});

});

}

copy("./a.txt", "b.txt", (err, data) = {

console.log("copy success");

});

登錄后復(fù)制

createStream的實(shí)現(xiàn)

const EventMitter = require("events");

const fs = require("fs");

class ReadStream extends EventMitter {

constructor(path, options = {}) {

super();

this.path = path;

//操作

this.flags = options.flags || "r";

this.encoding = options.encoding || null;

this.autoClose = options.autoClose || true;

this.start = options.start || 0;

this.end = options.end || Infinity; //讀取的個(gè)數(shù),包后的,如果是1 ,就可能讀取到0,1,2

this.highWaterMark = options.highWaterMark || 64 * 1024;

this.emitClose = options.emitClose || false;

this.offset = this.start; // 每次讀取文件的位移數(shù)

this.flowing = true; //暫停繼續(xù)開(kāi)關(guān)

this.open(); // 文件操作,注意這個(gè)方法是異步的。

// events可以監(jiān)聽(tīng)newListener,可以獲取注冊(cè)的所有事件

this.on("newListener", function (type) {

if (type === "data") {

//用戶訂閱了data事件,才去讀取。

this.read(); //這時(shí)候文件還沒(méi)open,fd為undefined。

}

});

}

pause() {

//暫停

this.flowing = false;

}

resume() {

//繼續(xù)

if (!this.flowing) {

this.flowing = true;

this.read();

}

}

destory(err) {

if (err) {

this.emit("error", err);

}

if (this.autoClose) {

fs.close(this.fd, () = {

this.emit("close");

});

}

}

read() {

//希望在open之后打開(kāi)

if (typeof this.fd !== "number") {

this.once("open", (fd) = {

//之前實(shí)現(xiàn)的copy這段邏輯是寫(xiě)在了fs.open里面,換成發(fā)布訂閱模式之后就可以分離出來(lái)。

this.read(); //第二次read的時(shí)候,fd有值了

});

} else {

//判斷每次讀取多少。因?yàn)閠his.end是包后的,比如start = 0, end = 1, 那么讀取的就是 0 , 1, 2所以需要+1

const howMutchToRead = Math.min(

this.end - this.offset + 1,

this.highWaterMark

);

const buffer = Buffer.alloc(howMutchToRead);

fs.read(

this.fd,

buffer,

0,

howMutchToRead,

this.offset,

(err, byteRead) = {

if (err) {

this.destory(err);

} else {

if (byteRead) {

//讀取到文件,發(fā)布data事件,發(fā)送真正讀取到的內(nèi)容

this.offset += byteRead;

this.emit("data", buffer.slice(0, byteRead));

this.flowing this.read();

} else {

this.emit("end");

if (this.autoClose) {

this.destory();

}

}

}

}

);

}

}

open() {

fs.open(this.path, this.flags, (err, fd) = {

if (err) {

//報(bào)錯(cuò):

this.destory(err);

}

//從回調(diào)的形式變成了發(fā)布訂閱模式

this.fd = fd;

this.emit("open", fd);

});

}

}

const rs = new ReadStream("./a.txt", {

flags: "r", //創(chuàng)建可讀流。

encoding: null, //默認(rèn)Buffer

autoClose: true, //自動(dòng)關(guān)閉,相當(dāng)于讀取完畢調(diào)用fs.close

emitClose: true, //觸發(fā)close事件

start: 0, //從文件哪里開(kāi)始讀取

highWaterMark: 3, //每次讀取的數(shù)據(jù)個(gè)數(shù),默認(rèn)是64*1025字節(jié)。

//end: 4, // 比如這個(gè)就會(huì)讀取 1到5的內(nèi)容

});

rs.on("open", () = {

console.log("文件打開(kāi)了");

});

// rs.on("data", (data) = {

// console.log("監(jiān)聽(tīng)Data事件", data);

// });

// //底層還是 fs.open fs.read fs.close

// const rs = fs.createReadStream("./a.txt", {

// flags: "r", //創(chuàng)建可讀流。

// encoding: null, //默認(rèn)Buffer

// autoClose: true, //自動(dòng)關(guān)閉,相當(dāng)于讀取完畢調(diào)用fs.close

// emitClose: true, //觸發(fā)close事件

// start: 0, //從文件哪里開(kāi)始讀取

// highWaterMark: 3, //每次讀取的數(shù)據(jù)個(gè)數(shù),默認(rèn)是64*1025字節(jié)。

// }); //返回一個(gè)對(duì)象

//沒(méi)監(jiān)聽(tīng)前,是非流動(dòng)模式,監(jiān)聽(tīng)后,是流動(dòng)模式。

//監(jiān)聽(tīng)data事件,并且不停觸發(fā)

rs.on("data", function (chunk) {

console.log(chunk);

//暫停

rs.pause();

});

rs.on("end", function () {

console.log("讀取完畢");

});

rs.on("close", function () {

console.log("文件關(guān)閉");

});

setInterval(() = {

console.log("一秒后");

rs.resume();

}, 1000)

前端模板引擎有哪些的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于前端模板引擎一般用來(lái)開(kāi)發(fā)什么、前端模板引擎有哪些的信息別忘了在本站進(jìn)行查找喔。

掃描二維碼推送至手機(jī)訪問(wèn)。

版權(quán)聲明:本文由飛速云SEO網(wǎng)絡(luò)優(yōu)化推廣發(fā)布,如需轉(zhuǎn)載請(qǐng)注明出處。

本文鏈接:http://landcheck.net/post/11085.html

“前端模板引擎有哪些(前端模板引擎一般用來(lái)開(kāi)發(fā)什么)” 的相關(guān)文章

網(wǎng)站seo優(yōu)化課程(seo課程簡(jiǎn)介)

網(wǎng)站seo優(yōu)化課程(seo課程簡(jiǎn)介)

本篇文章給大家談?wù)劸W(wǎng)站seo優(yōu)化課程,以及seo課程簡(jiǎn)介對(duì)應(yīng)的知識(shí)點(diǎn),希望對(duì)各位有所幫助,不要忘了收藏本站喔。 本文目錄一覽: 1、seo排名優(yōu)化課程 2、網(wǎng)站SEO優(yōu)化有哪些要點(diǎn)? 3、優(yōu)就業(yè)seo課程學(xué)多久 4、[SEO第三課]搜索引擎優(yōu)化SEO一般有哪些步驟或環(huán)節(jié)? 5、《搜索...

建設(shè)網(wǎng)站制作(建設(shè)網(wǎng)站制作公司)

建設(shè)網(wǎng)站制作(建設(shè)網(wǎng)站制作公司)

本篇文章給大家談?wù)劷ㄔO(shè)網(wǎng)站制作,以及建設(shè)網(wǎng)站制作公司對(duì)應(yīng)的知識(shí)點(diǎn),希望對(duì)各位有所幫助,不要忘了收藏本站喔。 本文目錄一覽: 1、怎么制作網(wǎng)站啊? 2、網(wǎng)站建設(shè)的具體的流程有哪些 3、網(wǎng)站建設(shè)的步驟如何建設(shè) 4、網(wǎng)站建設(shè)多少錢? 5、網(wǎng)站怎么建設(shè)? 6、怎樣自己建網(wǎng)站? 怎么制作...

蚌埠網(wǎng)站制作(蚌埠廣告制作公司)

蚌埠網(wǎng)站制作(蚌埠廣告制作公司)

本篇文章給大家談?wù)劙霾壕W(wǎng)站制作,以及蚌埠廣告制作公司對(duì)應(yīng)的知識(shí)點(diǎn),希望對(duì)各位有所幫助,不要忘了收藏本站喔。 本文目錄一覽: 1、蚌埠網(wǎng)站制作,蚌埠網(wǎng)站建設(shè)哪家好 2、蚌埠有哪些網(wǎng)站建設(shè)公司推薦?網(wǎng)站建設(shè)要注意什么? 3、蚌埠達(dá)內(nèi)軟件有限公司怎么樣? 4、營(yíng)銷型網(wǎng)站建設(shè) 5、現(xiàn)在做一個(gè)...

包含寧波網(wǎng)站建設(shè)公司的詞條

包含寧波網(wǎng)站建設(shè)公司的詞條

本篇文章給大家談?wù)剬幉ňW(wǎng)站建設(shè)公司,以及對(duì)應(yīng)的知識(shí)點(diǎn),希望對(duì)各位有所幫助,不要忘了收藏本站喔。 本文目錄一覽: 1、寧波網(wǎng)站建設(shè)哪個(gè)比較好 2、寧波集團(tuán)網(wǎng)站制作哪家好 3、寧波網(wǎng)站建設(shè)公司哪家好 4、寧波模板網(wǎng)站建設(shè)哪個(gè)好 寧波網(wǎng)站建設(shè)哪個(gè)比較好 寧波色彩網(wǎng)絡(luò)科技有限公司,順企網(wǎng)寧波網(wǎng)...

2022個(gè)人簡(jiǎn)歷模板免費(fèi)(2021簡(jiǎn)歷模板免費(fèi))

2022個(gè)人簡(jiǎn)歷模板免費(fèi)(2021簡(jiǎn)歷模板免費(fèi))

本篇文章給大家談?wù)?022個(gè)人簡(jiǎn)歷模板免費(fèi),以及2021簡(jiǎn)歷模板免費(fèi)對(duì)應(yīng)的知識(shí)點(diǎn),希望對(duì)各位有所幫助,不要忘了收藏本站喔。 本文目錄一覽: 1、2022個(gè)人簡(jiǎn)歷中的格式 2、2022文員個(gè)人簡(jiǎn)歷模板 3、簡(jiǎn)單版2022個(gè)人簡(jiǎn)歷模板 2022個(gè)人簡(jiǎn)歷中的格式 ? ? 如何能制作出一份成功...

安卓如何修改APP數(shù)據(jù)(如何修改手機(jī)app 數(shù)據(jù))

安卓如何修改APP數(shù)據(jù)(如何修改手機(jī)app 數(shù)據(jù))

今天給各位分享安卓如何修改APP數(shù)據(jù)的知識(shí),其中也會(huì)對(duì)如何修改手機(jī)app 數(shù)據(jù)進(jìn)行解釋,如果能碰巧解決你現(xiàn)在面臨的問(wèn)題,別忘了關(guān)注本站,現(xiàn)在開(kāi)始吧!本文目錄一覽: 1、開(kāi)發(fā):安卓如何修改內(nèi)存數(shù)據(jù) 2、安卓手機(jī)怎么修改app的網(wǎng)絡(luò)mac 3、android 怎么利用sqllite修改數(shù)據(jù)庫(kù)...

黎川县| 永泰县| 贺州市| 长子县| 徐闻县| 渑池县| 石家庄市| 新竹县| 罗田县| 隆回县| 舒兰市| 司法| 漳州市| 金平| 田阳县| 东源县| 曲靖市| 湟源县| 伽师县| 突泉县| 临泉县| 连江县| 郯城县| 旌德县| 新野县| 大化| 海南省| 武城县| 景宁| 屏山县| 石家庄市| 普安县| 始兴县| 维西| 河间市| 泗洪县| 高密市| 海林市| 广河县| 靖州| 台南市|