|
導讀網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立... 網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立在超文本基礎之上的。超級文本標記語言之所以稱為超文本標記語言,是因為文本中包含了所謂“超級鏈接”點。 本篇文章給大家帶來的內容是關于React DND實現的卡片排序功能(代碼示例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。在公司初學react,其中一個要求讓我實現拖拽排序的功能,完成之后記錄一下實現方法,采用antd和reactDND來實現這個功能。 一、環境搭建首先,使用 npm install -g create-react-app create-react-app my-app cd my-app OK,構建好了react項目,然后我們引入 $ yarn add antd $ yarn add react-dnd $ yarn add react-dnd-html5-backend 引用完antd后可以按照antd官網上的方法完成按需加載。 二、功能實現我們先使用antd寫出一個簡單的卡片列表,修改項目目錄的APP.js和App.css文件,新建一個文件CardItem.js //App.js
import React, { Component } from 'react';
import CardItem from './CardItem'
import './App.css';
const CardList = [{ //定義卡片內容
title:"first Card",
id:1,
content:"this is first Card"
},{
title:"second Card",
id:2,
content:"this is second Card"
},{
title:"Third Card",
id:3,
content:"this is Third Card"
}
];
class App extends Component {
state = {
CardList
};
render() {
return (
<div className='card'>
{CardList.map((item,index) => {
return(
<CardItem //向次級界面傳遞參數
key={item.id}
title={item.title}
content={item.content}
index={index}
/>
)
})}
</div>
);
}
}
export default App;
//App.css
.card{
display: flex;
margin: 50px;
}
.card div{
margin-right: 20px;
}
//CardItem.js
import React, { Component } from 'react';
import {Card} from 'antd'
class CardItem extends Component{
render(){
return(
<div>
<Card
title={this.props.title}
style={{ width: 300 }}
>
<p>{this.props.content}</p>
</Card>
</div>
)
}
}
export default CardItem好了,卡片編寫完成了,現在運行一下我們的項目,看一下效果 $ npm start or yarn start
OK,編寫完成,我們現在要做的就是使用 react-dnd中提供了DragDropContext,DragSource,DropTarget 3種API;
理解了這些API的作用,一個卡片排序的構建思路大體就浮現出來了,怎么樣實現一個卡片排序,其實很簡單,就是把卡片列表中的每一個卡片都設置為 首先設定 //App.js
import React, { Component } from 'react';
import CardItem from './CardItem'
+ import {DragDropContext} from 'react-dnd'
+ import HTML5Backend from 'react-dnd-html5-backend'
import './App.css';
/*..
..*/
- export default App;
+ export default DragDropContext(HTML5Backend)(App);好了,現在被App.js所包裹的子組件都可以使用DropTarget和DragSource了,我們現在在子組件CardItem中設定react-dnd使得卡片現在能夠有拖動的效果。 //CardItem.js
import React, { Component } from 'react';
import {Card} from 'antd'
+ import { //引入react-dnd
DragSource,
DropTarget,
} from 'react-dnd'
const Types = { // 設定類型,只有DragSource和DropTarget的類型相同時,才能完成拖拽和放置
CARD: 'CARD'
};
//DragSource相關設定
const CardSource = { //設定DragSource的拖拽事件方法
beginDrag(props,monitor,component){ //拖拽開始時觸發的事件,必須,返回props相關對象
return {
index:props.index
}
},
endDrag(props, monitor, component){
//拖拽結束時的事件,可選
},
canDrag(props, monitor){
//是否可以拖拽的事件。可選
},
isDragging(props, monitor){
// 拖拽時觸發的事件,可選
}
};
function collect(connect,monitor) { //通過這個函數可以通過this.props獲取這個函數所返回的所有屬性
return{
connectDragSource:connect.dragSource(),
isDragging:monitor.isDragging()
}
}
//DropTarget相關設定
const CardTarget = {
drop(props, monitor, component){ //組件放下時觸發的事件
//...
},
canDrop(props,monitor){ //組件可以被放置時觸發的事件,可選
//...
},
hover(props,monitor,component){ //組件在target上方時觸發的事件,可選
//...
},
};
function collect1(connect,monitor) {//同DragSource的collect函數
return{
connectDropTarget:connect.dropTarget(),
isOver:monitor.isOver(), //source是否在Target上方
isOverCurrent: monitor.isOver({ shallow: true }),
canDrop: monitor.canDrop(),//能否被放置
itemType: monitor.getItemType(),//獲取拖拽組件type
}
}
class CardItem extends Component{
render(){
const { isDragging, connectDragSource, connectDropTarget} = this.props;
let opacity = isDragging ? 0.1 : 1; //當被拖拽時呈現透明效果
return connectDragSource( //使用DragSource 和 DropTarget
connectDropTarget( <div>
<Card
title={this.props.title}
style={{ width: 300 ,opacity}}
>
<p>{this.props.content}</p>
</Card>
</div> )
)
}
}
// 使組件連接DragSource和DropTarget
let flow = require('lodash.flow');
export default flow(
DragSource(Types.CARD,CardSource,collect),
DropTarget(Types.CARD,CardTarget,collect1)
)(CardItem)最后這個連接方法我參考了 reactDND官網 的說明,你可以去 lodash.flow的官網 進行查看并下載。 Even if you don't plan to use decorators, the partial application can import { DragSource, DropTarget } from 'react-dnd';
import flow from 'lodash/flow';
class YourComponent {
render() {
const { connectDragSource, connectDropTarget } = this.props
return connectDragSource(connectDropTarget(
/* ... */
))
}
}
export default flow(
DragSource(/* ... */),
DropTarget(/* ... */)
)(YourComponent);現在我們已經完成了一個拖拽效果的實現,現在我們來看一下效果
可以很明顯的看到拖拽帶來的效果,接下來我們要完成拖拽放置后的排序函數。 //CardItem.js
const CardTarget = {
hover(props,monitor,component){
if(!component) return null; //異常處理判斷
const dragIndex = monitor.getItem().index;//拖拽目標的Index
const hoverIndex = props.index; //放置目標Index
if(dragIndex === hoverIndex) return null;// 如果拖拽目標和放置目標相同的話,停止執行
//如果不做以下處理,則卡片移動到另一個卡片上就會進行交換,下方處理使得卡片能夠在跨過中心線后進行交換.
const hoverBoundingRect = (findDOMNode(component)).getBoundingClientRect();//獲取卡片的邊框矩形
const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;//獲取X軸中點
const clientOffset = monitor.getClientOffset();//獲取拖拽目標偏移量
const hoverClientX = (clientOffset).x - hoverBoundingRect.left;
if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX) { // 從前往后放置
return null
}
if (dragIndex > hoverIndex && hoverClientX > hoverMiddleX) { // 從后往前放置
return null
}
props.DND(dragIndex,hoverIndex); //調用App.js中方法完成交換
monitor.getItem().index = hoverIndex; //重新賦值index,否則會出現無限交換情況
}
}//App.js
handleDND = (dragIndex,hoverIndex) => {
let CardList = this.state.CardList;
let tmp = CardList[dragIndex] //臨時儲存文件
CardList.splice(dragIndex,1) //移除拖拽項
CardList.splice(hoverIndex,0,tmp) //插入放置項
this.setState({
CardList
})
};
/* ...
*/
//添加傳遞參數傳遞函數
<CardItem //向次級界面傳遞參數
key={item.id}
title={item.title}
content={item.content}
index={index}
onDND={this.handleDND}
/>好了,現在我們已經完成了一個卡片排序功能的小demo,讓我們來看一下效果吧!
以上就是React DND實現的卡片排序功能(代碼示例)的詳細內容,更多請關注php中文網其它相關文章! 網站建設是一個廣義的術語,涵蓋了許多不同的技能和學科中所使用的生產和維護的網站。 |
溫馨提示:喜歡本站的話,請收藏一下本站!