【總結】總結寫了3個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