react遇到的各種坑


  • 標簽里用到<label for>的,for 要寫成htmlFor
  • 標簽里的class要寫成className
  • 組件首字母一定要大寫
  • 單標簽最后一定要閉合
  • 如果html里要空格轉義,&nbsp;注意不要漏了分號;
  • style要寫成style={{clear: 'both',backgroundColor:'red',width:'200px'}}
  • 組件里能用<button>的地方就不要用input type="button"了,否則寫個value還要用{}
  • 標簽里的ref屬性的屬性名不要出現中橫杠比如message-content,如果有多個單詞,直接寫成駝峰形式
  • 把要改變的數據寫進父組件的getInitialState的屬性里,然后通過this.props.listArr傳進去,表明初始狀態是組件里listArr里的屬性。
  • 如果將子組件改變的數據傳遞給父組件呢?可以在父組件里申明一個函數,里面傳參data,然后在創建出子組件的對象的時候在屬性上傳入父組件的這個函數,然后在子組件里觸發了某個事件的函數里,通過this.props.addItem()這樣的方式調用父組件的函數,這個addItem就是父組件的函數,里面傳參
  • 如果組件之間的通信超過的一層,傳參就非常麻煩,需要用到react的一個插件叫PubSub訂閱發布

(1) 先導入庫
(2) 全局設置一個事件名稱,子組件和父組件共用,比如var deleteItem = 'deleteItem';
(3) 子組件,觸發事件之后,發布事件


//使用PubSub.publish(),第一個參數是公用的事件名稱,第二個參數是你要傳播的值 deleteItemHandler:function(){ PubSub.publish(deleteItem, this.props.item); },

(4) 父組件,是等組件全部渲染之后,因為組件還在內存中,虛擬DOM還沒有渲染出來,沒有正式出現在頁面上時,是獲取不到真是DOM的,所以在componentDidMount的函數里訂閱一個從子組件發布出來的事件,在渲染完成后,會自動觸發這個函數


//使用PubSub.subscribe(),第一個參數是公用的事件名稱,第二個參數是一個回調函數,可以是用箭頭函數方式使它內部this指向組件對象,evName是事件對象,data就是子組件發布過來,這里接受到的data componentDidMount:function(){ PubSub.subscribe(deleteItem,(evName,data) =>{ var newArr = this.state.listArr.filter(function(item,index){ return item!= data; }); this.setState({ listArr:newArr }); }); },
  • 這里順便復習一下Arrayfilter()方法,參數里是個函數,參數是項和下標,return里寫一個條件,所有符合條件的都會提取出來放到一個新的數組里,這里將數組里不等於傳回來的這個data里的值的每一項都放到了newArr里,然后通過setState(),更新state里數組的值
  • 利用ReactCSSTransitionGroup來添加一些簡單的動畫效果,比如列表內容增加或者刪除時可以有漸進漸出的效果。但是這個標簽默認是span標簽,使用在table或者options里提示警告,不能在tableoptions里嵌套span,所以可以通過它本身的component屬性,比如component="div"直接將這個標簽渲染為我們需要的標簽即可。另外css里對應的動畫時間要和這里標簽里的時間對應

    var ListComponent = React.createClass({ render: function(){ return ( <ReactCSSTransitionGroup component="div" id="message-container" transitionName="messageContainer" transitionEnterTimeout={800} //這里定義漸進的時間 > { //這里放該組件的子級,也就意味寫着這里面所有的內容的都會有動畫效果, this.props.mesArr.map(function(ele){ return <ItemComponent key={ele.time} {...ele} /> }) } </ReactCSSTransitionGroup> ) } });
  • 通過搜索框輸入字符讓顯示區即時地篩選出搜索結果的效果。這里的難點是,如果直接通過onChange來獲取打入的字符串來更新父組件的state里的數據,會造成數據返回不到原來的狀態。所以思路可以是這樣的,在父組件state里先創建一個空數組,每次當搜索框獲取到焦點時,就把父組件當前的顯示數據賦值給這個新建的數組,然后filter的時候是通過這個新數組里的數據進行篩選,而不是原來的數據,另外,當搜索框內容為空或者失去焦點時,再把視圖的數據恢復到得到焦點時的狀態即可。下面是可以實現的父組件中的代碼:

//在搜索框聚焦時,將當前state里的userList賦值給currentList,然后每次輸入,篩選的對象都是currentList focusHandler:function(){ this.state.currentList = this.state.userList; }, //在失去焦點時立刻將剛才存儲的currentList賦值給userList,讓視圖再恢復到點擊搜索框之前 blurHandler:function(){ this.setState(function(){ return { userList: this.state.currentList } }); }, //搜索功能 searchUser:function(text){ //這里要將text進行判斷,如果為空,就要讓視圖呈現剛聚焦時的狀態,否則就進行篩選 if(text!=''){ var newText = text.toLowerCase(); var newArr = this.state.currentList.filter(function(item){ //每次點擊通過保存的currentList來過濾 return item.username.toLowerCase().indexOf(newText) != -1; }); this.setState(function(){ return { userList: newArr } }); }else{ this.setState(function(){ return { userList: this.state.currentList } }); } },
  • React-Router動畫的結合使用
    除了兩種技術的結合之外,有個很重要的地方不要忘記,就是要讓每個單獨的組件設置樣式為position:absolute,否則在動畫切換時會出現短暫組件疊加的的情況,用戶體驗非常差,但是絕對定位后,每個組件都在同一個地方漸入漸出了。
//這里是react創建組件的ES6新寫法,省略了function和內部的render,return。 const MenuComponent = ({ children, location }) => ( <div> //這里是將組件Menu下控制的路由寫在這里,每個路徑用Link標簽包起來,通過屬性to來控制對應不同的路徑 <div className="col-md-3 list-group"> <Link to="/statistic" className="list-group-item active">Website Statistic Data</Link> <Link to="/topics" className="list-group-item">Hot Topics</Link> <Link to="/visits" className="list-group-item">Today's Visits</Link> <Link to="/status" className="list-group-item">Server Status</Link> </div> //這里把要對應的做成動畫的區域用ReactCSSTransitionGroup包起來 <ReactCSSTransitionGroup className="col-md-9 pr clearfix" component="div" transitionName="content" transitionEnterTimeout={500} transitionLeaveTimeout={500} > {React.cloneElement(children, {key: location.pathname,className:"pa"})} </ReactCSSTransitionGroup> </div> ) -------------------------------------------------------------- //這里是render方法里的寫法 ReactDOM.render( <Router> //根路由 // "/"代表根路由,IndexRoute表示索引頁,如果沒有索引頁可以作為默認顯示的內容 <Route path="/" component={MenuComponent}> <IndexRoute component={StatisticComponent} /> <Route default path="statistic" component={StatisticComponent} /> <Route path="topics" component={TopicComponent} /> <Route path="visits" component={GuestComponent} /> <Route path="status" component={StateComponent} /> </Route> </Router> ,document.getElementById('container') );
  • 用ES6的箭頭函數寫組件
const MenuComponent = ({ children, location }) => { //定義組件里的函數直接在組件里申明即可 const changeLink = (ev) => { var parent = ev.target.parentNode; var children = parent.children; for(var i=0; i<children.length; i++){ children[i].classList.remove('active'); } ev.target.classList.add('active'); }; //這屆寫return (),里面寫標簽 return ( <div> <div className="col-md-3 list-group" onClick={changeLink}> //這里不用再寫this.changeLink了 <Link to="/statistic" className="list-group-item active">Website Statistic Data </Link> <Link to="/topics" className="list-group-item">Hot Topics</Link> <Link to="/visits" className="list-group-item">Today's Visits</Link> <Link to="/status" className="list-group-item">Server Status</Link> </div> <ReactCSSTransitionGroup className="col-md-9 pr" component="div" transitionName="content" transitionEnterTimeout={500} transitionLeaveTimeout={500} > {React.cloneElement(children, {key: location.pathname, className: "pa"})} </ReactCSSTransitionGroup> </div> ); };


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM