我在React使用中踩過的坑
總結一下初學React的坑。
1、class必須用className代替,否則不識別,因為和js混淆
很多屬性不識別,比如colspan
<table class="ui">
JSX要寫成
<table className="ui">
<th colspan='6'></th>
JSX要寫成
<th colSpan='6'></th>
我真是嗶了狗了。對於不知道的入門者來說,幾萬年找不出錯誤也是很正常的,我一直在百度React 不識別class什麼的,啥都沒有,偶然看demo發現他寫的是className,才想起來class是js的關鍵字,可我又不寫ES6,我也不用class啊。
2、迭代多重json
這個東西在jquery裡還是很簡單的,就是,麻煩!
這也是JSX的好處。
事情是這樣的,某天,我突然想裝逼,考慮到我也看了幾十分鐘的React,說不定會用了,於是在一個檔案裡沒有寫jquery,用了React。
我的需求是這樣的:
我有一個json:
var json={
'num':5,
'_s1':{'class_Name':'balabala','point':'3','loc':'balabala'},
'_s2':{'class_Name':'balabala','point':'3','loc':'balabala'},
'_s3':{'class_Name' :'balabala','point':'3','loc':'balabala'},
'_s4':{'class_Name':'balabala','point':'3','loc':'balabala'},
'_s5':{'class_Name':'balabala','point':'3','loc':'balabala'},
}
大概就是這樣的結構,兩重巢狀,我要把它放到一個好看的表格裡
表格是這個樣子的:
我的table結構是
<table class="ui celled padded orange table"><thead><tr ><th class="single line">課程名稱</th><th>課程學分</th><th>所屬專業</th><th>上課地點</th><th>熱度</th><th>是否選擇</th></tr></thead><tbody><tr><td><h2 class="ui aligned header">高等數學</h2></td><td class="single line"><div class="ui red button"><i class="heart icon"></i>課程熱度</div><a class="ui basic red left pointing label">20</a></td><td><!--<div class="ui star rating"data-rating="3"data-max-rating="3"></div>-->資訊二</td><td class="right aligned"><a href="#">資訊三</a></td><td>資訊4</td><td class="ui center"><button class="circular ui icon button"id="show_circle"><i class="icon add"></i></button></td></tr><tr><td><h2 class="ui aligned header">高等數學</h2></td><td class="center single line"><div class="ui red button"><i class="heart icon"></i>課程熱度</div><a class="ui basic red left pointing label">20</a></td><td><!--<div class="ui star rating"data-rating="3"data-max-rating="3"></div>-->資訊二</td><td class="right aligned"><a href="#">資訊三</a></td><td>資訊4</td><td class="ui center"><button class="circular ui icon button"id="show_circle"><i class="icon add"></i></button></td></tr></tbody><tfoot><tr><th colspan="6"><div class="ui right floated pagination menu"><a class="icon item"><i class="left chevron icon"></i></a><a class="item">1</a><a class="item">2</a><a class="item">3</a><a class="item">4</a><a class="icon item"><i class="right chevron icon"></i></a></div></th></tr></tfoot></table>
大致就是n個<tr>
每個<tr>
裡n個<td>
我需要把<td>
裡放上json的資料。
我先是選擇元件迭代
定義一個<tr>
元件,把<td>
放裡面並展開
就像這樣(錯誤程式碼):
var Class_TR = React.createClass({
render: function() {
return <tr>
<td><h2 class="ui aligned header">{this.props.classname}</h2></td>
<td class="single line">{this.props.point}</td>
<td>{this.props.major}</td>
<td class="left aligned">{this.props.loc}</td>
<td><div class="ui red button"><i class="heart icon"></i>喜歡</div><span class="ui basic red left pointing label">20</span></td>
<td class="center aligned"><button class="circular ui icon button" id="{this.props.sid}"><i class="icon add"></i></button></td>
</tr>;
}
然後在做tbody元件,方法同理
這裡就有坑,
return <tr>
<td><h2 class="ui aligned header">{this.props.classname}</h2></td>
這個就會報錯,他說text不能是tr的子元素,於是就很納悶,我哪有text啊?
百度了一下,發現是tr後面多打了個空格,他認為你後面跟著的是text,就很氣,但你打回車就沒問題。。。。
這和JSX的解析原理有關,下一個坑也是這個的
做好元件之後發現迭代有毛病
單次迭代,map倒是很容易搞定
附贈json轉map方法
/**
*物件轉換為Map
*/
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
/**
*json轉換為map
*/
function jsonToMap(jsonStr) {
return objToStrMap(jsonStr);
}
Map迭代Example
var options = utils.Map_Class.map(function(data){
return <option value={data.code} key={data.code} >{data.cn}</option>
你看,單層的迭代一下搞定。其實這裡還是有個大坑,一會說。
還有一種迭代方式更爽,寫個陣列,往裡面push dom 元素,然後在下面return里加上{rows}這個陣列,就可以封裝元件,也能達到多次迭代
然後push時就會有坑。
var Class_TE_ALL=React.createClass({
render:function(){
var each_tr=[];
var sid="";
for(var i = 0;i<this.props.Map_Class.num;i++)
{
sid="_"+i;
each_tr.push(<Class_TR key="{this.props.Map_Class[sid]['classname']}" sid="{sid}" classname="{this.props.Map_Class[sid]['classname']}" point="{this.props.Map_Class[sid]['point']}" major="{this.props.Map_Class[sid]['major']}" loc="{this.props.Map_Class[sid]['loc']}" />)
}
return <tbody>{each_tr}</tbody>;
}
元件封裝還需要層層傳參,最外層傳個Map,然後在解析一層傳下去,再在內層分別獲取值,不喜歡這樣,所以最後沒有用元件,用的直接for迭代。
嚴重錯誤程式碼
var Class_TR = React.createClass({
render: function(){
var rows=[];
var item={};
var sid="",uid="",vid="";
//console.log(Json_Class)
for (var i = 0; i <Json_Class["num"]; i++) {
item=Json_Class["_"+i];
sid="-"+i;uid="_"+i;vid="+"+i;
rows.push(<tr key={sid}>);
rows.push(<td key={item.class_name+"_"+i}><h2>{item.class_name}</h2></td>);
rows.push(<td key={item.point+"_"+i}>{item.point}</td>);
rows.push(<td key={item.major+"_"+i}>{item.major}</td><td key={item.loc+"_"+i}>{item.loc}</td>);
rows.push(</tr>);
}
return <tbody>{rows}</tbody>;
}
});
看起來蠻不錯的,不需要動態傳參,把靜態引數顯示出來。
但其實除了class的坑,JSX解析理解也是很坑的。
不要以為在{}裡就可以開心的寫JS程式碼,看見標籤還是給你往Html上解析
所以上述rows.push()會push出一堆
);rows.push(
很納悶吧!
因為他看見<>就會去找標籤,然後就不執行js程式碼了
所以:
rows.push()一行要把所有Dom元素都push進去!!!
別管什麼結構了。。。。
最後要寫成
var Class_TR = React.createClass({
render: function(){
var rows=[];
var item={};
var sid="",uid="",vid="";
//console.log(Json_Class)
for (var i = 0; i <Json_Class["num"]; i++) {
item=Json_Class["_"+i];
sid="-"+i;uid="_"+i;vid="+"+i;
rows.push(<tr key={sid}><td key={item.class_name+"_"+i}><h2 className = "ui aligned header">{item.class_name}</h2></td><td key={item.point+"_"+i} className= "single line">{item.point}</td><td key={item.major+"_"+i}>{item.major}</td><td key={item.loc+"_"+i} className="left aligned">{item.loc}</td><td key={vid}><div className="ui red button"><i className="heart icon"></i>喜歡</div><span className="ui basic red left pointing label">20</span></td><td key={uid} className="center aligned"><button className="circular ui icon button" id={uid+"_"}><i className="icon add"></i></button></td></tr>);
}
return <tbody>{rows}</tbody>;
}
});
才能把json迭代並放到td裡
從結果上來說,若不使用元件封裝的話,JSX寫起來只是用了JS變數嵌入html裡,和jsp,php寫法沒什麼區別,並沒有很便利。(當然那些是後端模板)
所以還是要複用元件!!!!
還有一種迭代方法,map也可以多重迭代。那個寫法還是很簡潔的。
感覺今天把這輩子JSX的坑都踩完了。
尤其是他報錯不給報是哪,我在底下tr錯的時候,一直以為元件遍歷錯誤。
改了3小時的bug,整個人都快累死了。
功能還一點沒做。