摘要:比如在的時(shí)候組件掛載的時(shí)候會(huì)根據(jù)指定的參數(shù)繼續(xù)向下執(zhí)行,則會(huì)在掛載的時(shí)候還沒(méi)發(fā)生點(diǎn)擊事件就直接執(zhí)行了父組件的函數(shù)。即中轉(zhuǎn)函數(shù)的效果,保證了時(shí)的函數(shù)都是并且也防止了子組件在掛載時(shí),順著調(diào)用父組件的函數(shù)從而避免了一系列錯(cuò)誤。
寫在前面
以前寫Vue寫慣了,心血來(lái)潮,寫起了react。
github地址:Close2React
項(xiàng)目使用框架版本主要有 react(15.4.1) + react-dom(15.4.1) + webpack(1.13.3) + axios(0.15.3) + node(6.2.2), 點(diǎn)擊查看項(xiàng)目簡(jiǎn)介:一段人人都應(yīng)該知道的從 vue 到 react 的過(guò)渡史
目前該項(xiàng)目有兩個(gè)分支, half-es6 + master
half-es6和master實(shí)現(xiàn)的功能一樣, 實(shí)現(xiàn)了CURD + Axios + Others
half-es6的寫法并沒(méi)有完全使用es6的class的概念, master是完善了它
現(xiàn)在讓我們快速了解React的事件綁定都有什么坑~
?? ?? ??
// 父組件主要是為了實(shí)現(xiàn)tab的切換 const Content = React.createClass({ getInitialState() { return { tabTxt: ["CURD", "Axios", "Others"], choice: 0, //目前激活的tab的下標(biāo) } }, switchChoice(idx){ // 設(shè)置choice this.setState({ choice: idx }) }, renderTabInit(text, idx) { return ({text} ) }, render() { ...... } });
自以為把方法傳入了子組件,就在Tab子組件中直接this.props.choose調(diào)用父組件的方法
const Tab = React.createClass({
render(){
return (
{this.props.children}
)
}
});
結(jié)果瀏覽器打開(kāi)就爆炸了。boom
正確姿勢(shì)大概意思就是說(shuō):
我在父組件中的setState在渲染的時(shí)候?qū)е铝艘粋€(gè)錯(cuò)誤。React不能更新一個(gè)正在變化的state。
組件中的render應(yīng)該是一個(gè)帶有state和props的pure function(純函數(shù))。如果不是純函數(shù),構(gòu)造器會(huì)產(chǎn)生一些副作用。
比如在render的時(shí)候(組件掛載的時(shí)候)會(huì)根據(jù)props指定的參數(shù)繼續(xù)向下執(zhí)行,則會(huì)在掛載的時(shí)候(還沒(méi)發(fā)生點(diǎn)擊事件)就直接執(zhí)行了父組件的函數(shù)。順便解釋一下pure function
1、給出同樣的參數(shù)值,該函數(shù)總是求出同樣的結(jié)果。該函數(shù)結(jié)果值不依賴任何隱藏信息或程序執(zhí)行處理可能改變的狀態(tài)或在程序的兩個(gè)不同的執(zhí)行,也不能依賴來(lái)自I/O裝置的任何外部的輸入
2、結(jié)果的求值不會(huì)促使任何可語(yǔ)義上可觀察的副作用或輸出,例如易變對(duì)象的變化或輸出到I/O裝置
const Tab = React.createClass({
chooseTab() { // 子組件的中轉(zhuǎn)函數(shù)
this.props.choose(this.props.idx); //在這里調(diào)用父組件的函數(shù)
},
render(){
return (
{this.props.children}
)
}
});
這個(gè)中轉(zhuǎn)函數(shù)的名詞是我自己取的,只是這樣就能讓點(diǎn)擊事件的函數(shù)變成pure function,就不會(huì)在組件掛載的時(shí)候就沿著props繼續(xù)向下執(zhí)行,就能避免在掛載組件的時(shí)候就直接調(diào)用父組件的setState了。
--
案例2 todolist 的 編輯 & 保存 示例效果圖 錯(cuò)誤示范// 父組件 const PageA = React.createClass({ getInitialState() { ... }, // 初始化todolist的數(shù)據(jù) componentDidMount(){ ... }, // 掛載組件時(shí)的函數(shù) initDidCount() { ... }, // 更新完成的進(jìn)度 handleTxtChange(event){ // 重點(diǎn): 當(dāng)input的輸入值變化時(shí)調(diào)用這個(gè)函數(shù) let index = event.target.getAttribute("data-index"); // 強(qiáng)行得到todolist的index // 這里一定需要index這個(gè)參數(shù)作為修改this.state.list時(shí)候的下標(biāo) this.state.list[index].text = event.target.value; // 把input的值更新到state上去 this.setState({ list: this.state.list }); this.initDidCount(); // 更新完成進(jìn)度 }, handleCheckChange(event,idx) { ... }, // checkbox的onChange,和input的onChange一樣 deleteItem(idx) { ... }, // 刪除 initListLi(val,idx) { return () }, render() { ...... } });
這里也會(huì)和案例1有同樣的情況,父組件用props傳入的方法里面有setState,如果在子組件的reader中直接用this.props.handleTxtChange 調(diào)用的話,會(huì)導(dǎo)致函數(shù)不純。
錯(cuò)誤姿勢(shì)1// 錯(cuò)誤的父組件1 ... handleTxtChange(event,idx){ // 重點(diǎn):【錯(cuò)誤寫法1】 強(qiáng)行傳了兩個(gè)參數(shù) console.log(event, idx); // 在控制臺(tái)上輸出結(jié)果 this.state.list[idx].text = event.target.value; // 把input的值更新到state上去 this.setState({ list: this.state.list }); this.initDidCount(); // 更新完成進(jìn)度 }, ... // 錯(cuò)誤的子組件1 ... render (){ return (
{this.props.text}
} ...你會(huì)發(fā)現(xiàn),你想要給props的方法里傳的自定義參數(shù)index能正常獲取,
而框架自帶參數(shù)event怎么都拿不到,
結(jié)果只能如下,event會(huì)變成undefined。
// 錯(cuò)誤的父組件2 ... handleTxtChange(event){ // 重點(diǎn):【錯(cuò)誤寫法2】 只有框架自帶參數(shù)event console.log(event.target); // 在控制臺(tái)上輸出結(jié)果 let index = event.target.getAttribute("data-index"); // 強(qiáng)行拿到標(biāo)簽上的自定義屬性 this.state.list[index].text = event.target.value; // 把input的值更新到state上去 this.setState({ list: this.state.list }); this.initDidCount(); // 更新完成進(jìn)度 }, ... // 錯(cuò)誤的子組件2 ... render (){ return (
{this.props.text}
} ...當(dāng)發(fā)現(xiàn)多傳了參數(shù),導(dǎo)致了框架自帶的默認(rèn)參數(shù)event怎么都取不到的時(shí)候,
決定不傳參數(shù),用其他歪門邪道(比如自定義屬性)拿到想要的參數(shù)。
在input中輸入內(nèi)容,結(jié)果如下。雖然正確,但這樣寫感覺(jué)實(shí)在是不夠智能。
總之,這樣寫雖然解決了問(wèn)題,但我還是覺(jué)得姿勢(shì)還是不對(duì)。
// 正確的父組件 ... handleTxtChange(event,idx){// 重點(diǎn):【正確姿勢(shì)】 不僅帶了框架默認(rèn)參數(shù)event,還帶了自定義參數(shù) this.state.list[idx].text = event.target.value; this.setState({ // 最正常的賦值寫法 list: this.state.list }); this.initDidCount(); }, ... // 正確的子組件 ... handleTxt(event) { // 用一個(gè)中轉(zhuǎn)函數(shù)來(lái)存onChange時(shí)會(huì)調(diào)用的父組件的函數(shù) // 并加上任意的參數(shù) this.props.handleTxtChange(event, this.props.index); }, render (){ return (
{this.props.text}
} ...案例3如果這樣寫的話,是達(dá)到了和案例1一樣的效果。
即中轉(zhuǎn)函數(shù)的效果,保證了render時(shí)的函數(shù)都是pure function
并且也防止了子組件在掛載時(shí),render順著this.props.function調(diào)用父組件的函數(shù)
從而避免了一系列錯(cuò)誤。
案例3純粹是為了演示一個(gè)增加操作,在增加一條記錄后,需要清空input的內(nèi)容時(shí)踩的坑
// 父組件 addLiItem(obj) { this.state.list.push(obj); // 沒(méi)啥好說(shuō),就是添加一個(gè)元素到list中去 this.setState({ list: this.state.list }); this.initDidCount(); },
// 子組件 const Add = React.createClass({ getInitialState() { return { addValue: "", addStatus: false } }, handleAddChange(event) { this.setState({ addValue: event.target.value }) }, add(){ this.props.addLiItem({ text: this.state.addValue, status: false }); this.setState({ //【重點(diǎn)部分】 addValue: "" }, ()=>{ this.refs.addIpt.value = ""; // 利用ref操作dom }); }, // 如果只是setState的時(shí)候發(fā)現(xiàn)完成沒(méi)辦法達(dá)到清空的效果 // 這時(shí)候的【正確姿勢(shì)】是去操作dom,一定要操作dom render() { return (// 定義了一個(gè)ref是addIpt的input標(biāo)簽) } });
--
總結(jié)為了盡可能使用pure function,也為了保證掛載的時(shí)候不要出問(wèn)題
在子組件需要調(diào)用父組件的this.props.function的時(shí)候
盡可能使用中轉(zhuǎn)函數(shù)
你懂得~~
github地址:Close2React
我是嘉寶Appian,一個(gè)賣萌出家的算法妹紙。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/86607.html
摘要:本文針對(duì)的讀者具備性能優(yōu)化的相關(guān)知識(shí)雅虎條性能優(yōu)化原則高性能網(wǎng)站建設(shè)指南等擁有實(shí)戰(zhàn)經(jīng)驗(yàn)。這種機(jī)制能減少瀏覽器次數(shù),從而提高性能。僅會(huì)檢查該和它的子,當(dāng)你確定當(dāng)前操作僅影響它們時(shí),用可以稍微提升性能。 搬運(yùn)自: http://atian25.github.io/2014/05/09/angular-performace/ 不知不覺(jué),在項(xiàng)目中用angular已經(jīng)半年多了,踩了很多坑...
摘要:年前公司由一個(gè)項(xiàng)目是使用來(lái)開(kāi)發(fā)的所以遇到了一些問(wèn)題比較影響開(kāi)發(fā)進(jìn)程的就是路由問(wèn)題了實(shí)際上就是這個(gè)組件比較難懂這里給大家講解一下希望大家少踩點(diǎn)坑另外本篇文章使用的是環(huán)境主要講解的還是如何使用記錄中路由的狀態(tài)但是會(huì)穿插一些小內(nèi)容這里雖然講到的是 年前公司由一個(gè)項(xiàng)目是使用 ReactNative 來(lái)開(kāi)發(fā)的所以遇到了一些問(wèn)題,比較影響開(kāi)發(fā)進(jìn)程的就是路由問(wèn)題了,實(shí)際上就是 ReactNaviga...
摘要:功能三滴滴費(fèi)用計(jì)算古人云細(xì)節(jié)決定成敗,一個(gè)良好的微信小程序往往就是一些細(xì)節(jié)打動(dòng)人心,居然是模仿,雖做不到百分百,至少還是很希望一模一樣。 最近時(shí)常感嘆道:時(shí)間總是那么的快,轉(zhuǎn)瞬即逝。對(duì)于像我這種剛?cè)腴T的小生來(lái)講,技術(shù)每天都在更新,框架也層出不窮,有時(shí)候還沒(méi)弄懂這個(gè)知識(shí)大牛們又推出了更好的技術(shù)。當(dāng)然學(xué)習(xí)好的技術(shù)也是十分重要的。但是在學(xué)習(xí)之后怎樣才能夠得到自己想要的呢,一個(gè)好的建議便是靜...
摘要:第二步就是調(diào)用,我在文件夾簡(jiǎn)歷了個(gè)的文件,方便管理。然后在里面引入至此,安裝基本完成,下面介紹這個(gè)東西的用法。其實(shí)這東西用法簡(jiǎn)單的一比,就是幾個(gè)屬性而已。例如然后在組件中直接調(diào)用這樣就直接運(yùn)行了這個(gè)方法。 項(xiàng)目終于做完了,博客也很久沒(méi)更新了,寫下這個(gè)項(xiàng)目用到的一些知識(shí),以后大家也少踩點(diǎn)坑第一步當(dāng)然還是安裝了,這里只介紹npm的安裝方法,別的請(qǐng)自行百度。 npm install vuex...
摘要:的網(wǎng)站仍然使用有漏洞庫(kù)上周發(fā)布了開(kāi)源社區(qū)安全現(xiàn)狀報(bào)告,發(fā)現(xiàn)隨著開(kāi)源社區(qū)的日漸活躍,開(kāi)源代碼中包含的安全漏洞以及影響的范圍也在不斷擴(kuò)大。與應(yīng)用安全是流行的服務(wù)端框架,本文即是介紹如何使用以及其他的框架來(lái)增強(qiáng)應(yīng)用的安全性。 showImg(https://segmentfault.com/img/remote/1460000012181337?w=1240&h=826); 前端每周清單專注...
閱讀 2471·2021-11-17 09:33
閱讀 758·2021-11-04 16:13
閱讀 1329·2021-10-14 09:50
閱讀 691·2019-08-30 15:53
閱讀 3657·2019-08-30 14:18
閱讀 3268·2019-08-30 14:14
閱讀 2093·2019-08-30 12:46
閱讀 3178·2019-08-26 14:05