我在react中构建了自己的Table组件。我想添加更多的配置,比如可滑动行。
问题是,所有用于反应可滑动的NPM附加组件都是包装器,将包装我的组件。
tr标记不能由div或任何其他html标记包装,但td除外。
在底线中,我如何使我的行组件(也就是tr)可以滑动?
这是我的代码:
let RowComp = <Row key={index} cols={this.props.cols} row={row} onRowClick={this.onRowClick}/>;
if(this.props.onRowSwipe){
return (
<Swipe key={index} onSwipeRight={() => this.props.onRowSwipe(row)}>
{RowComp}
</Swipe>
);
}
return RowComp;
当然,我收到了反应警告,tr不能包装。我能做些什么呢?我怎么才能让我的刷卡?
非常感谢:)
发布于 2018-10-24 06:01:37
我在应用程序中尝试过类似的东西。没有任何本机swipe事件,但是有三个事件可以让您解决问题:onTouchStart
、onTouchMove
、onTouchEnd
。下面您可以看到我的一个可滑动菜单的实验性实现:正如您所看到的,我已经在App.js组件中创建了三个函数:handleTouchStart
、handleTouchMove
、handleTouchEnd
。
handleTouchStart
函数接收事件作为支柱,并保存初始的X和Y位置handleTouchMove
函数再次接收事件作为支柱,并查找当前和初始位置之间的差异。handleTouchEnd
函数检查X和Y之间的差异,并显示或隐藏菜单。不幸的是,您无法访问onTouchEnd事件的最后一个位置,这就是为什么您必须使用onTouchMove事件.
,你还得检查一下垂直移动是否发生过。这就是为什么我还检查Y位置之间的差异,但您需要绝对值
如果X差为负值,则表示您向左移动。如果X差是正的,那就意味着你向右移动.。
--您还必须在不同的设备中进行大量测试,以确定初始X位置与最终X位置之间的理想差异
最后,我将函数作为道具传递给组件,并将它们绑定到三个事件。
App.js (父组件)
import React, { Component } from "react";
import styled from "styled-components";
import Header from "components/Header";
import Navbar from "components/Navbar";
import SideMenu from "components/SideMenu";
import MainContent from "components/Content";
const AppWrapper = styled.section`
height: 100vh;
width: 100vw;
display: grid;
grid-template-rows: 70px auto;
@media (max-width: 884px) {
grid-template-columns: 60vw auto;
}
@media (min-width: 885px) {
grid-template-columns: 200px auto;
}
`;
class App extends Component {
swipe = {
firstPositionX: null,
firstPositionY: null,
positionDifferenceX: null,
positionDifferenceY: null
};
constructor(props) {
super(props);
this.state = {
sideMenuDisplay: window.innerWidth >= 885 ? true : false
// movement: -60
};
}
componentDidMount() {
window.addEventListener("resize", this.updateSideMenuDisplay);
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateSideMenuDisplay);
}
updateSideMenuDisplay = () => {
this.setState({ sideMenuDisplay: window.innerWidth >= 885 ? true : false });
};
toggleSideMenu = () => {
this.setState(prevState => ({
sideMenuDisplay: !prevState.sideMenuDisplay
}));
};
handleTouchStart = e => {
this.swipe.firstPositionX = e.touches[0].screenX;
this.swipe.firstPositionY = e.touches[0].screenY;
};
handleTouchMove = e => {
this.swipe.positionDifferenceX =
e.touches[0].screenX - this.swipe.firstPositionX;
this.swipe.positionDifferenceY =
e.touches[0].screenY - this.swipe.firstPositionY;
};
handleTouchEnd = () => {
if (Math.abs(this.swipe.positionDifferenceY) <= 150) {
this.setState(
prevState => ({
sideMenuDisplay:
prevState.sideMenuDisplay === false
? this.swipe.positionDifferenceX > 50
: !(this.swipe.positionDifferenceX < -50)
}),
() => {
this.swipe.firstPositionX = null;
this.swipe.positionDifferenceX = null;
this.swipe.firstPositionY = null;
this.swipe.positionDifferenceY = null;
}
);
}
};
render() {
const sideMenuDisplay = this.state.sideMenuDisplay;
return (
<AppWrapper>
<Header display={sideMenuDisplay} />
<Navbar onClick={this.toggleSideMenu} display={sideMenuDisplay} />
<SideMenu
}
}
export default App; display={sideMenuDisplay}
onTouchStart={this.handleTouchStart}
onTouchMove={this.handleTouchMove}
onTouchEnd={this.handleTouchEnd}
/>
<MainContent
display={sideMenuDisplay}
onTouchStart={this.handleTouchStart}
onTouchMove={this.handleTouchMove}
onTouchEnd={this.handleTouchEnd}
/>
</AppWrapper>
);
}
}
export default App;
SideMenu.js (子组件)
import React, { Component } from "react";
import SideMenuElement from "./SideMenuElement";
import MembersIcon from "./MembersIcon";
import DashboardIcon from "./DashboardIcon";
import {
SideMenuSection,
SideMenuItems,
SideMenuElementLogo,
AppMobileLogo
} from "./styles";
import logoIcon from "static/logo@3x.png";
class SideMenu extends Component {
constructor(props) {
super(props);
this.state = { selectedItem: "dashboard" };
}
selectItem = item => {
this.setState({ selectedItem: item });
};
render() {
const selectedItem = this.state.selectedItem;
return (
<SideMenuSection
display={`${this.props.display}`}
onTouchStart={this.props.onTouchStart}
onTouchMove={this.props.onTouchMove}
onTouchEnd={this.props.onTouchEnd}
>
<SideMenuItems>
<SideMenuElementLogo>
<AppMobileLogo src={logoIcon} alt="App Logo" />
</SideMenuElementLogo>
<SideMenuElement
item="dashboard"
icon={DashboardIcon}
selected={selectedItem === "dashboard"}
onClick={this.selectItem}
>
Dashboard
</SideMenuElement>
<SideMenuElement
item="members"
icon={MembersIcon}
selected={selectedItem === "members"}
onClick={this.selectItem}
>
Members
</SideMenuElement>
</SideMenuItems>
</SideMenuSection>
);
}
}
export default SideMenu;
发布于 2018-10-25 07:00:11
谢谢你的回复。我终于想出来了。我心里想,怎样才能合法地包扎一个tr?
答案是:tbody。
我使用了react来用tbody节点包装tr,这一切都像魔术一样没有警告。
import Swipe from 'react-swipe-component';
<Swipe key={index} nodeName="tbody" onSwipeRight={() => this.props.onRowSwipe(row)}>
{RowComp}
</Swipe>
无论如何,谢谢你的评论:)
https://stackoverflow.com/questions/52969953
复制相似问题