摘要:以下內(nèi)容當(dāng)具備語(yǔ)法環(huán)境前端組件基礎(chǔ)概念寫(xiě)過(guò)代碼包你天上手項(xiàng)目下面開(kāi)始地址項(xiàng)目結(jié)構(gòu)如下的方式值得借鑒介紹一個(gè)框架讓開(kāi)發(fā)者可以在中寫(xiě)代碼也就是語(yǔ)法稱(chēng)為虛擬類(lèi)似一個(gè)對(duì)象掛載節(jié)點(diǎn)將寫(xiě)的虛擬變成真的每次都是新舊虛擬之間進(jìn)行比較之后才會(huì)生成真實(shí)創(chuàng)建項(xiàng)
以下內(nèi)容,當(dāng)具備ES6,JS語(yǔ)法,node環(huán)境,前端組件基礎(chǔ)概念,寫(xiě)過(guò)java代碼,包你3天上手React項(xiàng)目,下面開(kāi)始...
demo地址https://gitee.com/tonysb/lear...
項(xiàng)目結(jié)構(gòu)如下,Button的方式值得借鑒
react: 一個(gè)js框架,讓開(kāi)發(fā)者可以在js中寫(xiě)html代碼,也就是jsx語(yǔ)法,稱(chēng)為虛擬dom(類(lèi)似一個(gè)js對(duì)象)
react-dom: 掛載節(jié)點(diǎn),將jsx寫(xiě)的虛擬dom變成真的dom
render: 每次都是新舊虛擬dom之間進(jìn)行比較,之后才會(huì)生成真實(shí)dom
創(chuàng)建react項(xiàng)目命令行使用 npx create-react-app my-app-name 即可創(chuàng)建項(xiàng)目
react中組件(子父之間傳值)A: 父組件 B: 子組件
在A.js文件中使用 其中name為A文件中一個(gè)變量,getName為A文件中一個(gè)方法
在B.js文件中,可直接使用this.props.name或this.props.getName或const { name, getName } = this.props來(lái)得到A中變量,或運(yùn)行A中方法,最后一種最常用,這種方式是ES6中新增的解構(gòu)賦值.
父->子 通過(guò)子標(biāo)簽上加上屬性的方式,直接傳遞,在子重使用this.props來(lái)接住屬性
子->父 通過(guò)在子中調(diào)用父?jìng)鬟f的方法來(lái)完成
具體使用場(chǎng)景: 一個(gè)頁(yè)面右上角掛載一個(gè)三級(jí)聯(lián)動(dòng)選項(xiàng)卡(三級(jí)數(shù)據(jù)從接口獲取),main作為父組件主頁(yè)面,select作為子組件三級(jí)選項(xiàng)卡頁(yè)面
main頁(yè)面負(fù)責(zé)ajax請(qǐng)求,拿總數(shù)據(jù),為子組件準(zhǔn)備好所有即插即用數(shù)據(jù)和方法,在使用select標(biāo)簽的時(shí)候,全部傳遞給子
select頁(yè)面,在this.props中負(fù)責(zé)解構(gòu)所有數(shù)據(jù)和方法,直接使用,無(wú)需關(guān)心邏輯實(shí)現(xiàn)
main叫邏輯組件(聰明組件), select叫UI組件(笨蛋組件)
JSX語(yǔ)法render中return中的代碼都是JSX,和html代碼相似.
在js中直接寫(xiě)html語(yǔ)法,也可以使用自定義標(biāo)簽,比如可以寫(xiě)自己組件,App組件可以寫(xiě)成
render中用JSX語(yǔ)法寫(xiě)html代碼,必須在最外層包括一個(gè)div,不然編譯會(huì)報(bào)錯(cuò),在16版本中,如果使用Fragment來(lái)表示占位符,在html中顯示的時(shí)候,可去掉組件最外層的那個(gè)div,demo如下
// 你的jsx代碼
使用js表達(dá)式/js變量需要使用{}把表達(dá)式包裹起來(lái),demo如下
// ES6 ``,${}加三目運(yùn)算符可處理復(fù)雜的css名字 // for循環(huán)遍歷請(qǐng)使用map方法,sortTableRows是state中一個(gè)變量 {sortTableRows && sortTableRows.map(item => ({item.title} {item.author} {item.comments} {item.points}))}onMiss(item.id)}>miss
html標(biāo)簽中進(jìn)行事件綁定,事件名稱(chēng)首字母必須大寫(xiě),比如 onChange中C就是大寫(xiě)的
在html樣式中,使用className來(lái)代替class
使用dangerouslySetInnerHTML={{__html: item}},可在提交數(shù)據(jù)的時(shí)候,對(duì)數(shù)據(jù)中html標(biāo)簽進(jìn)行轉(zhuǎn)義處理
for需要換成htmlfor
事件綁定jsx合成事件綁定,js高階函數(shù),綁定的是函數(shù),不能讓函數(shù)馬上執(zhí)行
不帶參數(shù)綁定,后面不能加(), 如果加,那函數(shù)會(huì)馬上執(zhí)行,而不是事件發(fā)生時(shí)候回調(diào)執(zhí)行
帶參數(shù)綁定,需要在一個(gè)匿名函數(shù)中寫(xiě)綁定函數(shù)
// 合成事件綁定,不帶參數(shù)
1, state中設(shè)置searchTerm變量,用來(lái)填充input中value值
2, 綁定input中onChange事件,獲取event對(duì)象中value值,將該值set到searchTerm變量中
state: 組件自己內(nèi)部維護(hù)數(shù)據(jù),每次更新只需要關(guān)系需要更改的數(shù)據(jù)
1, set數(shù)據(jù)不依賴(lài)之前的數(shù)據(jù),直接調(diào)用setState
this.setState({ foo: bar })
2, set數(shù)據(jù)依賴(lài)之前數(shù)據(jù),一定要使用帶參數(shù)調(diào)用setState
this.setState((prevState, props) => ( // 你的代碼 )) // bad // setState是異步,代碼中多個(gè)set,有可能fooCount和barCount已經(jīng)被改變 const { fooCount } = this.state const { barCount } = this.props this.setState({ count: fooCount + barCount }) // good this.setState((prevState, props) => ( count: prevState.fooCount + props.barCount ))
props: 父->子,所有傳遞過(guò)來(lái)的數(shù)據(jù)都附加在props中,子在props中可以拿到所有父?jìng)鬟f過(guò)來(lái)的數(shù)據(jù)
render: 只要state進(jìn)行set操作,render一定會(huì)執(zhí)行,包括父state進(jìn)行set之后,父和子的render都會(huì)被執(zhí)行
子組件是UI組件,接完父組件數(shù)據(jù)直接使用,可直接在子組件props中直接使用父組件ajax請(qǐng)求獲取到的數(shù)據(jù)
子組件需要將父組件ajax數(shù)據(jù)賦值到自己的state中,只能在componentWillReceiveProps生命周期中處理,不能在constructor中處理,原因: 父組件ajax請(qǐng)求最起碼第二次render父組件,而子組件中constructor只會(huì)執(zhí)行一次
上述方式處理方式比較麻煩,推薦使用方式3
3, 父組件負(fù)責(zé)提供數(shù)據(jù)和處理處理的函數(shù),子組件只負(fù)責(zé)獲取數(shù)據(jù),渲染頁(yè)面,子組件事件交互,也是通過(guò)props來(lái)調(diào)用父組件中的函數(shù)(常用)
以下是使用場(chǎng)景和注意點(diǎn)
組件掛載階段(只會(huì)執(zhí)行一次,render除外)
constructor(): 設(shè)置state,獲取父組件props,并初始化自己的state,并綁定函數(shù)中this指向
componentWillMount(): 不能獲取頁(yè)面dom元素,目前還沒(méi)用過(guò)
render():渲染頁(yè)面,不做運(yùn)算,到這里為止,所有數(shù)據(jù)都應(yīng)該是經(jīng)過(guò)處理可直接使用的數(shù)據(jù)
componentDidMount(): 可獲取dom元素,ajax請(qǐng)求放這里,調(diào)用setState,設(shè)置dom元素監(jiān)聽(tīng),繪制canvas
組件更新階段(state或props發(fā)生變化)
componentWillReceiveProps(nextProps): nextProps為更新新屬性,可進(jìn)行新舊屬性對(duì)比,也可以根據(jù)新數(shù)據(jù)來(lái)計(jì)算和設(shè)置自己的state
shouldComponentUpdate(nextProps, nextState): 返回布爾值,可做渲染優(yōu)化,根據(jù)場(chǎng)景決定是否渲染該組件,不要調(diào)用setState
componentDidUpdate(prevProps, prevState): 操作 DOM 或者執(zhí)行更多異步請(qǐng)求的機(jī)會(huì)
componentWillUnmount: 取消網(wǎng)絡(luò)請(qǐng)求,刪除監(jiān)聽(tīng),一些收尾工作,不要調(diào)用setState
自定義函數(shù)的時(shí)候,寫(xiě)自定義函數(shù),需要在constructor中進(jìn)行函數(shù)this指向的綁定
在constructor中進(jìn)行this指向綁定,然后寫(xiě)正常函數(shù)
// 方式1 getTodoItem = () => { // 你的邏輯 } // 方式2 constructor(props) { super(props) this.inputOnChange = this.inputOnChange.bind(this) } inputOnChange() { // 你的邏輯 }組件類(lèi)型
ES6類(lèi)組件: 有this,props,有state,有生命周期,根據(jù)設(shè)計(jì)圖,一般當(dāng)作父組件使用,從接口拿數(shù)據(jù),計(jì)算成品數(shù)據(jù),編寫(xiě)事件函數(shù)來(lái)處理數(shù)據(jù)
無(wú)狀態(tài)組件(純函數(shù)): 接收輸入(props),輸出jsx組件實(shí)例,沒(méi)有this,沒(méi)有生命周期,沒(méi)有state,可根據(jù)props中的數(shù)據(jù)來(lái)計(jì)算符合自己要求的數(shù)據(jù)(組件中直接調(diào)用方法),
props中可以傳遞數(shù)據(jù),也可以傳遞函數(shù),一般當(dāng)做子組件使用,demo如下
import React from "react" /*查詢(xún)表單組件 * Search在使用的時(shí)候,標(biāo)簽中間就是children *查詢(xún) children的值就是查詢(xún) */ const Search = ({value, onChange, onSubmit, children}) => { return () } export default Search
import React from "react" import {Slider} from "antd" import moment from "moment" import "./style.less" /* * 時(shí)間軸無(wú)狀態(tài)組件 * timeData: 時(shí)間數(shù)組列表 * timeChange: 時(shí)間軸change事件的回調(diào) * worktime: 當(dāng)前選中時(shí)間 * */ const TimeSlider = ({timeData, timeChange, worktime}) => { /* * 獲取時(shí)間軸當(dāng)前選中值 * */ const getDefaultValue = () => { const { id } = times.find(item => { return item.dateTime === worktime }) return id } /* * 獲取時(shí)間軸的總長(zhǎng)度 * */ const getMax = () => { return timeData.length } /* * 獲取時(shí)間軸顯示的time數(shù)據(jù) * 格式: * { * 0: "2019-11-11" * 24: "2019-11-12" * 23: "2019-11-13" * } * */ let times = [] const getMarks = () => { let dates = [] console.log("timeData len", timeData.length) timeData.map((item, index) => { const time = {id: index, dateTime: item} times.push(time) dates.push(moment(item).format("YYYY-MM-DD")) }) const newDates = [...new Set(dates)] console.log("newDates", newDates) let marks = {} let datesAmount = [] newDates.map(item => { const amount = getDateAmount(item, timeData) const temp = {date: item, amount: amount} datesAmount.push(temp) }) for (let i = 0,length = datesAmount.length; i < length; i++) { const date = { style: { color: "#fff", marginLeft: 0 }, label: moment(datesAmount[i].date).format("MM/DD"), } if (i === 0) { //const mark = JSON.parse(`{"0":"${date}"}`) const mark = {0: date} Object.assign(marks, mark) } else { const index = i - 1 const lastAmount = getLastDateAmount(index, datesAmount) // const mark = JSON.parse(`{"${lastAmount}":"${date}"}`) const mark = { [lastAmount]: date } Object.assign(marks, mark) } } return marks } /* * 根據(jù) 2019-11-11來(lái)獲取 數(shù)據(jù) ["2019-11-11 11:11:11"] 對(duì)應(yīng)的小時(shí)數(shù)量 * */ const getDateAmount = (date, timeData) => { let amount = 0 for (let i = 0,length = timeData.length; i < length; i++ ) { const item = timeData[i] if (item.includes(date)) { amount = amount + 1 } } return amount } /* * 獲取當(dāng)前index往前推一個(gè)的所有小時(shí)數(shù)量 * */ const getLastDateAmount = (index, datesAmount) => { let sum = 0 for (let i = 0; i <= index; i++) { sum = sum + datesAmount[i].amount } return sum } const formatter = (value) => { const time = times.find(item => { return item.id === value }) return moment(time.dateTime).format("HH:mm") } const onTimeChange = (value) => { const time = times.find(item => { return item.id === value }) timeChange(time.dateTime) } return (兩款chrome插件) } export default TimeSlider
React Developer Tools // F12,查看每個(gè)react組件中state和props的值
Redux DevTools // F12,查看redux中store的值
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104066.html
摘要:入門(mén)學(xué)習(xí)筆記整理一搭建環(huán)境入門(mén)學(xué)習(xí)筆記整理二簡(jiǎn)介與語(yǔ)法入門(mén)學(xué)習(xí)筆記整理三組件入門(mén)學(xué)習(xí)筆記整理四事件入門(mén)學(xué)習(xí)筆記整理五入門(mén)學(xué)習(xí)筆記整理六組件通信入門(mén)學(xué)習(xí)筆記整理七生命周期入門(mén)學(xué)習(xí)筆記整理八入門(mén)學(xué)習(xí)筆記整理九路由React 入門(mén)學(xué)習(xí)筆記整理(一)——搭建環(huán)境 React 入門(mén)學(xué)習(xí)筆記整理(二)—— JSX簡(jiǎn)介與語(yǔ)法 React 入門(mén)學(xué)習(xí)筆記整理(三)—— 組件 React 入門(mén)學(xué)習(xí)筆記整理(...
摘要:前言非正經(jīng)入門(mén)是相對(duì)正經(jīng)入門(mén)而言的。不過(guò)不要緊,正式學(xué)習(xí)仍需回到正經(jīng)入門(mén)的方式??焖偃腴T(mén)建議先學(xué)會(huì)用拼文寫(xiě)文檔注冊(cè)一個(gè)賬號(hào),把庫(kù)到自己名下,然后用這個(gè)庫(kù)寫(xiě)自己的博客,參見(jiàn)這份介紹。會(huì)用拼文寫(xiě)文章,相當(dāng)于開(kāi)發(fā)已入門(mén)三分之一了。 本系列博文從 Shadow Widget 作者的視角,解釋該框架的設(shè)計(jì)要點(diǎn),既作為用戶(hù)手冊(cè)的補(bǔ)充,也從更本質(zhì)角度幫助大家理解 Shadow Widget 為什么這...
摘要:前言寫(xiě)此系列博客的目的是對(duì)所學(xué)知識(shí)點(diǎn)的總結(jié)和梳理,包括填坑方案分享,希望能幫助到還并不會(huì)使用的開(kāi)發(fā)者入門(mén)官方文檔中文文檔社區(qū)項(xiàng)目搭建按照官方提供的搭建項(xiàng)目全局安裝或全局安裝后可以使用這條命令創(chuàng)建名為的項(xiàng)目啟動(dòng) 前言 寫(xiě)此系列博客的目的是對(duì)所學(xué)React知識(shí)點(diǎn)的總結(jié)和梳理,包括填坑方案分享,希望能幫助到還并不會(huì)使用React的開(kāi)發(fā)者入門(mén)React React官方文檔React中文文檔R...
摘要:考慮到是快速入門(mén),于是乎我們就記住一點(diǎn),當(dāng)修改值需要重新渲染的時(shí)候,的機(jī)制是不會(huì)讓他全部重新渲染的,它只會(huì)把你修改值所在的重新更新。這一生命周期返回的任何值將會(huì)作為參數(shù)被傳遞給。 安裝react npm install creat-react-app -gshowImg(https://segmentfault.com/img/remote/1460000015639868); 這里直...
稍微整理了一下自己平時(shí)看到的前端學(xué)習(xí)資源,分享給大家。 html MDN:Mozilla開(kāi)發(fā)者網(wǎng)絡(luò) SEO:前端開(kāi)發(fā)中的SEO css 張?chǎng)涡瘢簭場(chǎng)涡竦牟┛?css精靈圖:css精靈圖實(shí)踐 柵格系統(tǒng):詳解CSS中的柵格系統(tǒng) 媒體查詢(xún):css媒體查詢(xún)用法 rem布局:手機(jī)端頁(yè)面自適應(yīng)布局 移動(dòng)前端開(kāi)發(fā)之viewport的深入理解:深入理解viewport 淘寶前端布局:手機(jī)淘寶移動(dòng)端布局 fl...
閱讀 2843·2019-08-30 15:55
閱讀 2878·2019-08-30 15:53
閱讀 2324·2019-08-26 13:47
閱讀 2583·2019-08-26 13:43
閱讀 3196·2019-08-26 13:33
閱讀 2830·2019-08-26 11:53
閱讀 1826·2019-08-23 18:35
閱讀 828·2019-08-23 17:16