摘要:一個(gè)組件的顯示形態(tài)和行為有可能是由某些數(shù)據(jù)決定的。一個(gè)簡(jiǎn)單的點(diǎn)贊功能我們會(huì)從一個(gè)簡(jiǎn)單的點(diǎn)贊功能講起。我們需要結(jié)構(gòu),準(zhǔn)確地來(lái)說(shuō)我們需要這個(gè)點(diǎn)贊功能的字符串表示的結(jié)構(gòu)。下一節(jié)小書(shū)前端組件化二優(yōu)化操作中我們繼續(xù)優(yōu)化這個(gè)例子,讓它更加通用。
React.js 小書(shū) Lesson1-2 - 前端組件化(一):從一個(gè)簡(jiǎn)單的例子講起
本文作者:胡子大哈
本文原文:http://huziketang.com/books/react/lesson2
轉(zhuǎn)載請(qǐng)注明出處,保留原文鏈接以及作者信息
在線閱讀:http://huziketang.com/books/react/
React.js 是一個(gè)幫助你構(gòu)建頁(yè)面 UI 的庫(kù)。如果你熟悉 MVC 概念的話,那么 React 的組件就相當(dāng)于 MVC 里面的 View。如果你不熟悉也沒(méi)關(guān)系,你可以簡(jiǎn)單地理解為,React.js 將幫助我們將界面分成了各個(gè)獨(dú)立的小塊,每一個(gè)塊就是組件,這些組件之間可以組合、嵌套,就成了我們的頁(yè)面。
一個(gè)組件的顯示形態(tài)和行為有可能是由某些數(shù)據(jù)決定的。而數(shù)據(jù)是可能發(fā)生改變的,這時(shí)候組件的顯示形態(tài)就會(huì)發(fā)生相應(yīng)的改變。而 React.js 也提供了一種非常高效的方式幫助我們做到了數(shù)據(jù)和組件顯示形態(tài)之間的同步。
React.js 不是一個(gè)框架,它只是一個(gè)庫(kù)。它只提供 UI (view)層面的解決方案。在實(shí)際的項(xiàng)目當(dāng)中,它并不能解決我們所有的問(wèn)題,需要結(jié)合其它的庫(kù),例如 Redux、React-router 等來(lái)協(xié)助提供完整的解決方法。
很多課程一上來(lái)就給大家如何配置環(huán)境、怎么寫(xiě) React.js 組件。但是本課程還是希望大家對(duì)問(wèn)題的根源有一個(gè)更加深入的了解,其實(shí)很多的庫(kù)、框架都是解決類(lèi)似的問(wèn)題。只有我們對(duì)這些庫(kù)、框架解決的問(wèn)題有深入的了解和思考以后,我們才能得心應(yīng)手地使用它們,并且有新的框架出來(lái)也不會(huì)太過(guò)迷茫;因?yàn)槠鋵?shí)它們解決都是同一個(gè)問(wèn)題。
這兩節(jié)課我們來(lái)探討一下是什么樣的問(wèn)題導(dǎo)致了我們需要前端頁(yè)面進(jìn)行組件化,前端頁(yè)面的組件化需要解決什么樣的問(wèn)題。后續(xù)課程我們?cè)賮?lái)看看 React.js 是怎么解決這些問(wèn)題的。
所以這幾節(jié)所講的內(nèi)容將和 React.js 的內(nèi)容沒(méi)有太大的關(guān)系,但是如果你能順利了解這幾節(jié)的內(nèi)容,那么后面哪些對(duì)新手來(lái)說(shuō)很復(fù)雜的概念對(duì)你來(lái)說(shuō)就是非常自然的事。
一個(gè)簡(jiǎn)單的點(diǎn)贊功能我們會(huì)從一個(gè)簡(jiǎn)單的點(diǎn)贊功能講起。 假設(shè)現(xiàn)在我們需要實(shí)現(xiàn)一個(gè)點(diǎn)贊、取消點(diǎn)贊的功能。
如果你對(duì)前端稍微有一點(diǎn)了解,你就順手拈來(lái):
HTML:
為了模擬現(xiàn)實(shí)當(dāng)中的實(shí)際情況,所以這里特意把這個(gè) button 里面的 HTML 結(jié)構(gòu)搞得稍微復(fù)雜一些。有了這個(gè) HTML 結(jié)構(gòu),現(xiàn)在就給它加入一些 JavaScript 的行為:
JavaScript:
const button = document.querySelector(".like-btn") const buttonText = button.querySelector(".like-text") let isLiked = false button.addEventListener("click", () => { isLiked = !isLiked if (isLiked) { buttonText.innerHTML = "取消" } else { buttonText.innerHTML = "點(diǎn)贊" } }, false)
功能和實(shí)現(xiàn)都很簡(jiǎn)單,按鈕已經(jīng)可以提供點(diǎn)贊和取消點(diǎn)贊的功能。這時(shí)候你的同事跑過(guò)來(lái)了,說(shuō)他很喜歡你的按鈕,他也想用你寫(xiě)的這個(gè)點(diǎn)贊功能。這時(shí)候問(wèn)題就來(lái)了,你就會(huì)發(fā)現(xiàn)這種實(shí)現(xiàn)方式很致命:你的同事要把整個(gè) button 和里面的結(jié)構(gòu)復(fù)制過(guò)去,還有整段 JavaScript 代碼也要復(fù)制過(guò)去。這樣的實(shí)現(xiàn)方式?jīng)]有任何可復(fù)用性。
結(jié)構(gòu)復(fù)用現(xiàn)在我們來(lái)重新編寫(xiě)這個(gè)點(diǎn)贊功能,讓它具備一定的可復(fù)用。這次我們先寫(xiě)一個(gè)類(lèi),這個(gè)類(lèi)有 render 方法,這個(gè)方法里面直接返回一個(gè)表示 HTML 結(jié)構(gòu)的字符串:
class LikeButton { render () { return ` ` } }
然后可以用這個(gè)類(lèi)來(lái)構(gòu)建不同的點(diǎn)贊功能的實(shí)例,然后把它們插到頁(yè)面中。
const wrapper = document.querySelector(".wrapper") const likeButton1 = new LikeButton() wrapper.innerHTML = likeButton1.render() const likeButton2 = new LikeButton() wrapper.innerHTML += likeButton2.render()
這里非常暴力地使用了 innerHTML ,把兩個(gè)按鈕粗魯?shù)夭迦肓?wrapper 當(dāng)中。雖然你可能會(huì)對(duì)這種實(shí)現(xiàn)方式非常不滿意,但我們還是勉強(qiáng)了實(shí)現(xiàn)了結(jié)構(gòu)的復(fù)用。我們后面再來(lái)優(yōu)化它。
實(shí)現(xiàn)簡(jiǎn)單的組件化你一定會(huì)發(fā)現(xiàn),現(xiàn)在的按鈕是死的,你點(diǎn)擊它它根本不會(huì)有什么反應(yīng)。因?yàn)楦緵](méi)有往上面添加事件。但是問(wèn)題來(lái)了,LikeButton 類(lèi)里面是雖然說(shuō)有一個(gè) button,但是這玩意根本就是在字符串里面的。你怎么能往一個(gè)字符串里面添加事件呢?DOM 事件的 API 只有 DOM 結(jié)構(gòu)才能用。
我們需要 DOM 結(jié)構(gòu),準(zhǔn)確地來(lái)說(shuō):我們需要這個(gè)點(diǎn)贊功能的 HTML 字符串表示的 DOM 結(jié)構(gòu)。假設(shè)我們現(xiàn)在有一個(gè)函數(shù) createDOMFromString ,你往這個(gè)函數(shù)傳入 HTML 字符串,但是它會(huì)把相應(yīng)的 DOM 元素返回給你。這個(gè)問(wèn)題就可以額解決了。
// ::String => ::Document const createDOMFromString = (domString) => { // TODO }
先不用管這個(gè)函數(shù)應(yīng)該怎么實(shí)現(xiàn),先知道它是干嘛的。拿來(lái)用就好,這時(shí)候用它來(lái)改寫(xiě)一下 LikeButton 類(lèi):
class LikeButton { render () { this.el = createDOMFromString(` `) this.el.addEventListener("click", () => console.log("click"), false) return this.el } }
現(xiàn)在 render() 返回的不是一個(gè) html 字符串了,而是一個(gè)由這個(gè) html 字符串所生成的 DOM。在返回 DOM 元素之前會(huì)先給這個(gè) DOM 元素上添加事件再返回。
因?yàn)楝F(xiàn)在 render 返回的是 DOM 元素,所以不能用 innerHTML 暴力地插入 wrapper。而是要用 DOM API 插進(jìn)去。
const wrapper = document.querySelector(".wrapper") const likeButton1 = new LikeButton() wrapper.appendChild(likeButton1.render()) const likeButton2 = new LikeButton() wrapper.appendChild(likeButton2.render())
現(xiàn)在你點(diǎn)擊這兩個(gè)按鈕,每個(gè)按鈕都會(huì)在控制臺(tái)打印 click,說(shuō)明事件綁定成功了。但是按鈕上的文本還是沒(méi)有發(fā)生改變,只要稍微改動(dòng)一下 LikeButton 的代碼就可以完成完整的功能:
class LikeButton { constructor () { this.state = { isLiked: false } } changeLikeText () { const likeText = this.el.querySelector(".like-text") this.state.isLiked = !this.state.isLiked likeText.innerHTML = this.state.isLiked ? "取消" : "點(diǎn)贊" } render () { this.el = createDOMFromString(` `) this.el.addEventListener("click", this.changeLikeText.bind(this), false) return this.el } }
這里的代碼稍微長(zhǎng)了一些,但是還是很好理解。只不過(guò)是在給 LikeButton 類(lèi)添加了構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)會(huì)給每一個(gè) LikeButton 的實(shí)例添加一個(gè)對(duì)象 state,state 里面保存了每個(gè)按鈕自己是否點(diǎn)贊的狀態(tài)。還改寫(xiě)了原來(lái)的事件綁定函數(shù):原來(lái)只打印 click,現(xiàn)在點(diǎn)擊的按鈕的時(shí)候會(huì)調(diào)用 changeLikeText 方法,這個(gè)方法會(huì)根據(jù) this.state 的狀態(tài)改變點(diǎn)贊按鈕的文本。
現(xiàn)在這個(gè)組件的可復(fù)用性已經(jīng)很不錯(cuò)了,你的同事們只要實(shí)例化一下然后插入到 DOM 里面去就好了。
下一節(jié)《React.js 小書(shū) Lesson3 - 前端組件化(二):優(yōu)化 DOM 操作》中我們繼續(xù)優(yōu)化這個(gè)例子,讓它更加通用。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/89655.html
摘要:因?yàn)楣ぷ髦幸恢痹谑褂?,也一直以?lái)想總結(jié)一下自己關(guān)于的一些知識(shí)經(jīng)驗(yàn)。于是把一些想法慢慢整理書(shū)寫(xiě)下來(lái),做成一本開(kāi)源免費(fèi)專(zhuān)業(yè)簡(jiǎn)單的入門(mén)級(jí)別的小書(shū),提供給社區(qū)。本書(shū)的后續(xù)可能會(huì)做成視頻版本,敬請(qǐng)期待。本作品采用署名禁止演繹國(guó)際許可協(xié)議進(jìn)行許可 React.js 小書(shū) 本文作者:胡子大哈本文原文:React.js 小書(shū) 轉(zhuǎn)載請(qǐng)注明出處,保留原文鏈接以及作者信息 在線閱讀:http://huzi...
摘要:一個(gè)組件的顯示形態(tài)由多個(gè)狀態(tài)決定的情況非常常見(jiàn)。我們順利地消除了手動(dòng)的操作。非一般的暴力,因?yàn)槊看味贾匦聵?gòu)造新增刪除元素,會(huì)導(dǎo)致瀏覽器進(jìn)行大量的重排,嚴(yán)重影響性能。下一節(jié)小書(shū)前端組件化三抽象出公共組件類(lèi)我們把這個(gè)通用模式抽離到一個(gè)類(lèi)當(dāng)中。 React.js 小書(shū) Lesson3 - 前端組件化(二):優(yōu)化 DOM 操作 本文作者:胡子大哈本文原文:http://huziketang....
摘要:前端日?qǐng)?bào)精選機(jī)制詳解與中實(shí)踐應(yīng)用基礎(chǔ)與實(shí)踐如何用獲取虛擬鍵盤(pán)高度適用所有平臺(tái)和入門(mén)教程阮一峰的網(wǎng)絡(luò)日志編程技能提升指南中文到底什么是又是什么眾成翻譯調(diào)用模塊騰訊前端團(tuán)隊(duì)社區(qū)小書(shū)從一個(gè)簡(jiǎn)單的例子講起小書(shū)教程小書(shū)優(yōu)化操作小書(shū)教 2017-09-07 前端日?qǐng)?bào) 精選 JavaScript Event Loop 機(jī)制詳解與 Vue.js 中實(shí)踐應(yīng)用 Redux 基礎(chǔ)與實(shí)踐如何用 js 獲取虛擬...
摘要:在實(shí)際項(xiàng)目當(dāng)中狀態(tài)提升并不是一個(gè)好的解決方案,所以我們后續(xù)會(huì)引入這樣的狀態(tài)管理工具來(lái)幫助我們來(lái)管理這種共享狀態(tài),但是在講解到之前,我們暫時(shí)采取狀態(tài)提升的方式來(lái)進(jìn)行管理。 React.js 小書(shū) Lesson17 - 前端應(yīng)用狀態(tài)管理 —— 狀態(tài)提升 本文作者:胡子大哈本文原文:http://huziketang.com/books/react/lesson17 轉(zhuǎn)載請(qǐng)注明出處,保留原...
摘要:最后抽離出來(lái)了一個(gè)類(lèi),可以幫助我們更好的做組件化。一個(gè)組件有自己的顯示形態(tài)上面的結(jié)構(gòu)和內(nèi)容行為,組件的顯示形態(tài)和行為可以由數(shù)據(jù)狀態(tài)和配置參數(shù)共同決定。接下來(lái)我們開(kāi)始正式進(jìn)入主題,開(kāi)始正式介紹。下一節(jié)鏈接直達(dá)小書(shū)基本環(huán)境安裝 React.js 小書(shū) Lesson4 - 前端組件化(三):抽象出公共組件類(lèi) 本文作者:胡子大哈本文原文:http://huziketang.com/books...
閱讀 3604·2023-04-25 15:52
閱讀 643·2021-11-19 09:40
閱讀 2839·2021-09-26 09:47
閱讀 1088·2021-09-22 15:17
閱讀 3665·2021-08-13 13:25
閱讀 2382·2019-08-30 15:56
閱讀 3550·2019-08-30 13:56
閱讀 2185·2019-08-30 11:27