单击链接滚动到特定部分 react.js

新手上路,请多包涵

我已经实现了一个侧面菜单,每个部分都有一个链接标签,但我不确定如何在单击它们时将用户带到特定部分时实现该功能。如果它在同一个组件中并且我以正常方式生成这些部分,但我以不同的方式进行,我知道如何做到这一点,我不确定如何实现像 react-scroll 或 scrollchor 这样的东西。

在这里,我通过映射我在另一个文件中的一些数据来使用 buildTree 生成这些部分。

 export default class CheckboxGroup extends PureComponent {
  constructor(props) {
    super(props);
    this.checkboxState = new Map();
    this.state = {
      checkboxState: new Map(),
    };
  }

  static propTypes = {
    data: PropTypes.any.isRequired,
    onChange: PropTypes.func.isRequired,
    counter: PropTypes.number,
  };

  treeCheckboxOnChange = (parentLabel, id, checked) => {
    this.checkboxState = this.checkboxState.setIn([parentLabel, id], checked);
    this.setState({
      checkboxState: this.checkboxState,
    });
  };

  mapParents = (counter, child) => {
    const parentLabel = child.get('label');
    return (
      <li key={child.get('name')} className='field'>
      <SegmentHeader style={segmentStyle} title={child.get('label')} icon={child.get('icon')}>
        <div className='fields' style={zeroMargin}>
          <div className='four wide field'>
            <TreeCheckbox
              label={`Grant ${child.get('label')} Permissions`}
              parentLabel={parentLabel}
              counter={counter}
              onChange={this.treeCheckboxOnChange}
            />
            {child.get('items') && this.buildTree(child.get('items'), counter + child.get('name'), parentLabel)}
          </div>
          <div className='twelve wide field'>
            <GrantDropdown checkboxState={this.state.checkboxState.get(parentLabel, new Map())} label={child.get('label')} childItems={child.get('items')}/>
          </div>
        </div>
      </SegmentHeader>
    </li>
    );
  };

  mapDataArr = (counter, parentLabel) => (child) => (
    (counter === 0) ?
      this.mapParents(counter, child)
      :
      <li key={child.get('name')}>
        <TreeCheckbox label={child.get('label')} parentLabel={parentLabel} onChange={this.treeCheckboxOnChange}/>
        {child.get('items') && this.buildTree(child.get('items'), counter + child.get('name'), parentLabel)}
      </li>
  )

  buildTree = (dataArr, counter, parentLabel) => (
    <ul key={counter} style={listStyle}>
      {dataArr.map(this.mapDataArr(counter, parentLabel))}
    </ul>
  )

  render() {
    return (
      <div className='tree-view'>
        {this.buildTree(this.props.data, this.props.counter)}
      </div>
    );
  }
}

我使用了相同的技术来映射数据以创建我的粘性 sideNav。

 export default class SideNav extends Component {

  static propTypes = {
    data: PropTypes.any.isRequired,
    counter: PropTypes.number,
  };

  mapPermissionNames = (counter, child) => (
    <li key={child.get('name')}>
      <Link>{child.get('label')}</Link>
    </li>
  )

  mapDataArr = (counter) => (child) => (
    (counter === 0) ?
      this.mapPermissionNames(counter, child)
      :
      <li key={child.get('name')}>
        <Link>{child.get('label')}</Link>
      </li>
  )

  buildTree = (dataArr, counter) => (
    <ul key={counter} style={listStyle}>
      {dataArr.map(this.mapDataArr(counter))}
    </ul>
  )

  render() {
    return (
      <div className='tree-view'>
        {this.buildTree(this.props.data, this.props.counter)}
      </div>
    );
  }
}

这是它们都被渲染的父级。

 export default class LocationPermissions extends AbstractSettingsComponent {

  handlePermissionChange = (e, { value }) => {
    this.updatePerson('locationPermissions', value);
  }

  updateCheckmarks = (id, checked) => {
    const { currentPerson } = this.props;
    if (checked && !currentPerson.get('permissions').includes(id)) {
      this.updatePerson('permissions', id, true);
    } else if (!checked && currentPerson.get('permissions').includes(id)) {
      this.filterItem(['currentPerson', 'permissions'], id, 1);
    }
  }

  render() {
    const { currentPerson } = this.props;
    return (
      <div>
        <SegmentHeader icon='building' title='Location Permissions'>
          <div className='two fields' style={zeroMarginBottom}>
            <div className='field'>
              <OptionSelector
                label={`Grant ${this.getPerson()} permissions for...`}
                options={this.getPermissionOptions()}
                value={currentPerson.get('locationPermissions') || 0}
                onChange={this.handlePermissionChange}
              />
            </div>
            {currentPerson.get('locationPermissions') === 2 &&
              <div className='field'>
                <label>Grant Location Admin Permissions For</label>
                <LocationMultiSelect name='Every' {...this.props}/>
              </div>
            }
          </div>
        </SegmentHeader>
        <StickyContainer>
        {currentPerson.get('locationPermissions') === 3 &&
          <div className='fields'>
            <div className='three wide field'>
              <Sticky style={{ paddingTop: '15px' }}>
                <SideNav
                  data={permissionSections}
                  counter={0}
                />
              </Sticky>
            </div>
            <div className='twelve wide field'>
            <CheckboxGroup
              data={permissionSections}
              counter={0}
              onChange={this.updateCheckmarks}
            />
          </div>
        </div>
        }
        </StickyContainer>
      </div>
    );
  }
}

我无法理解如何实现诸如 react-scroll 或 scrollchor 或 react-router 链接标签之类的东西,以便能够单击该部分并滚动到页面上的该部分。任何建议都将非常受欢迎。

原文由 StuffedPoblano 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 254
2 个回答

我可以通过以下方式使用浏览器支持的方式:

 <a href={`#${child.get('label')}`}>{child.get('label')}</a>

然后只需向列表元素添加一个 id。

原文由 StuffedPoblano 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是我在没有复杂步骤或第 3 方库的情况下完成的方法

1- 创建一个带有 onClick 事件的 div 并添加 window.location.replace 以将当前 URL 替换为所需的 URL。这是一个例子

<div onClick={() => window.location.replace("/#about")}>
<span>go to about</span>
</div>

2- 在您的部分中添加您要访问的 ID。

 <h2 id="about">About</h2>

并且所有这些都在没有第 3 方库的情况下完成。干杯。

原文由 jerryurenaa 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题