拖動加載API字段
實現通過鼠標拖拽一個後臺API到Form實現自動加載API所以的字段成表單
拖動組件採用react-dnd
這個插件,數據交互和頁面更新等等使用Hooks實現
Hooks官方文檔https://react.docschina.org/docs/hooks-intro.html
ReactDnd官方文檔http://react-dnd.github.io/react-dnd/
實現流程
數據源
http://jianjiacheng.com/json/swagger.json
項目結構
實現流程
效果圖
Demo源碼
https://github.com/jianjiachenghub/ReactHooksDnD.git
拖動加載組件封裝DragBox
組件需要使用useDrag這個dnd插件封裝好的hook
然後將hook返回的函數賦值給DOM的ref屬性進行操作
Items 是拖拽數據的表現形式,用 Object 來表示。
import React from 'react'
import { useDrag } from 'react-dnd'
import { Menu, Icon ,Button} from 'antd';
const DragBox = ({ name, data }) => {
const [{ opacity }, drager] = useDrag({
item: { name, type:'dragBox',data},
collect: monitor => ({
opacity: monitor.isDragging() ? 0.4 : 1,
}),
})
return (
<div ref={ drager }><Button value="large" type="dashed" block>{name}</Button></div>
)
}
export default DragBox
接受拖動的組件Dustbin
accept屬性指定只能接受拖動的item裏type爲dragBox的
drop是一個監聽滑動完成的一個回調
import React from 'react'
import { useDrop } from 'react-dnd'
import CreactForm from "./CreactForm"
const style = {
minHeight: 780,
height: '100%',
border: '1px dashed black'
}
const Dustbin = ({onDrop,data}) => {
const [{ isOver, canDrop }, drop] = useDrop({
accept: 'dragBox',
drop: onDrop,
collect: monitor => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
}),
})
const getForm = (data)=>{
if (Object.keys(data).length !== 0) {
const {data:{properties}} = data
return <CreactForm data={properties}/>
}
}
return (
<div ref={drop} style={{ ...style}}>
{getForm(data)}
</div>
)
}
export default Dustbin
界面的展示組件DndMenu
在這個數據的JS代碼部分解析好數據並傳遞給子組件
<Layout>
<Sider>
{returnData.map(({ name, data }, index) => (
<DragBox
name={name}
data={data}
key={index}
/>
))}
</Sider>
<Content>
<Dustbin
onDrop={item => handleDrop(item)}
data={dropData}
/>
</Content>
</Layout>
啓用DND需要放到DndProvider中
import React from 'react'
import ReactDOM from 'react-dom'
import DndMenu from './menu'
import { DndProvider } from 'react-dnd'
import HTML5Backend from 'react-dnd-html5-backend'
function Dnd() {
return (
<div className="App">
<DndProvider backend={HTML5Backend}>
<DndMenu />
</DndProvider>
</div>
)
}
export default Dnd
HOOKS組件注意的問題
useEffect()請求數據的邏輯
- useEffect() 可以讓你在函數組件中執行副作用操作
- 默認情況下,它在第一次渲染之後和每次更新之後都會執行。
- 但是我們不需要在更新的時候再次產生副作用
- 第二個參數來告訴react只有當這個參數的值發生改變時,才執行我們傳的副作用函數
- 可以在effect的第二個參數帶個空數組表示不監聽任何值的改變來執行副作用
useEffect(() => {
getData()
},[]);
- 這裏採用await解析出axios返回的數據然後調用更新函數
const getData = async () => {
const result = await axios(
`${GLOBAL_URL}/list`
);
console.log(result)
const data = result.data[0]
const api = getKey(data.apiPath)
getTreeData(api,data.apiPath)
const originalData = getOriginalData(data.apiPath,data.apiDefinitions)
setData(originalData)
}
const [returnData, setData] = useState([]);//根據returnData去渲染UI
函數式組件間的數據交流
以前使用Class語法時在子組件內部使用this.props可以拿到父組件傳遞的數據
而現在的函數式語法可以直接在子組件的參數使用解構賦值拿到上層傳遞的數據
const DragBox = ({ name, data }) => {
}
function DndMenu(props) {
return (
<DragBox
name={name}
data={data}
key={index}
/>
)
}
hooks組件怎麼使用AntDesign的表單函數
以前的Class語法在組件內部想要調用Ant裏面Form的函數只需要類修飾器@後
就能在組件內部使用this.props調用到form的API
@Form.create()
@connect(({ usersModal, basicdata, loading }) => ({
usersModal,
basicdata,
loading : loading.models.usersModal,
loadingEditFlag : loading.effects['usersModal/saveEditFlag'],
loadingUpdate : loading.effects['usersModal/UpdateUser'],
loadingGet : loading.effects['usersModal/getUser'],
loadingAdd : loading.effects['usersModal/addUser'],
}))
class UserDetail extends PureComponent {
}
現在則可以再導出組件的時候直接將組件傳入Form.create()返回的函數
export default Form.create()(DndMenu)