打造在线编译器 之 对文件目录的操作

2017-10-23  本文已影响162人  RichardBillion

菜单栏中子文件显示/隐藏的切换动画

最初调研的 rc-collapse 组件,但是其 Collapse 与 Panel 的设置并不适合于文件目录结构的展示,并且这两者父子组件耦合严重,便转而调研单纯的 Collapse组件,比如react-collapse。这是单纯的一个 component-wrapper for collapse animation,在实现目录结构的展示上对开发时的限制减少了很多。但是在实际使用中发现了另一个比较重要的问题:这些 wrapper 都有一个属性isOpened来控制当前组件是展开还是折叠状态,这由我们传入 props 控制,而当切换展示文件时(也就是改变了model 中的 activeId)就会触发该 wrapper 的rerender,即如果该组件原本是展开的,那么切换展示文件之后,该组件就会出现由先折叠(默认状态)转为展开(props 使然)的动画。

在当前的场景(展示多级文件目录)下,动画依靠数据/状态驱动,当前打开的文件即 activeItem,是根据当前页面状态中的 activeId ===item.id? 来添加 active 的样式的。那么在多级菜单栏中,切换文件之后,activeId 改变, activeItem 也必然改变,此时整个目录是在做 diff 比较然后刷新的,那么涉及到文件夹的显示/隐藏必然也将重新渲染(如果文件 isOpened状态保存在每个 Collapse 组件内部,则 rerender 之后都会是恢复 state的初始值,如果放在 props 则必然会显示组件重新渲染的动画过程)而这是我们不希望看到的。

此时想要 jquery 时代的控制:只有在我点击文件夹的时候才进行展开/折叠动画的过程切换,其余 rerender 的时候不应用动画效果。同时点击之后展开/折叠的状态还需要在 props 中去更新,当切换文件时不至于使得原本打开的文件夹被折叠上。此时动画就需要自己使用 CSS 控制去实现就更容易一些,同时基于 props 记录管理文件夹的当前状态。

实现:基于 原生 div 展示 sidebar ,同时默认折叠,当点击文件夹时 通过 updateProps 更新该文件夹 props.isCollapsed 的 值,进而触发对 class 进行修改,实现折叠/显示的切换。当切换激活文件时,整个sideMenu 仍然会rerender, 但因为 props.isCollapsed 一直没变,添加的 class 也不变,所以不会有动画过程出现。所以在整体 rerender 的过程中,如果想要保证内部组件的动画过程在 rerender 时不出现,自行控制 css 是不错的方法。

其中记录各个文件夹的props.isCollapsed状态由 model 中一个对象记录各个文件夹的状态

collapseObj={
    dirId1:true,
    dirId2:false
}

对于每个文件夹结构独立为一个组件(代码有删改):

haddleClick=()=>{
  this.props.updateCollapseObj({
    id:this.props.id,
    state:this.props.getCollapseObj[this.props.id]?false:true
  })
}
render(){
  const {id,name,panel}=this.props;
  let divClass= classNames({
    'panel':true,
    'show':this.props.getCollapseObj[this.props.id]
  })

  return (
    <div>
      <p data-id={id} onClick={this.haddleClick} className="panelName">
        <i className="iconfont icon-folder-closed"></i>
        {name}
      </p>
      <div className={divClass}>
        {panel}
      </div>
    </div> 
    )
}

针对菜单栏添加 contextMenu 如新建文件/重命名/删除文件等操作。

js 支持右键自定义事件contextMenu,但是自己实现时需要封装好一些功能,其中最重要的是不论点击rename/createFile/deleteFile 哪个按钮,我们都需要得到触发该 contextMenu 的元素id。调研的有react-contextmenureact-contexify,尽管后者 star数量上比较少,但更能满足我们的需求,因为在当前场景(展示多级目录)下,我们需要简单的得到触发 contextMenu 的元素,前者对此的支持度并不好。

react-contexify封装在 Item 上的click方法会接受3个参数handleClick(targetNode,ref,data)。得到触发该 contextMenu 的元素targetNode之后,我们如何得到其 id 属性呢,此处不要忘了威力无穷的属性data-xxx,可以给 targetNode 添加data-id属性,然后通过targetNode.dataset.id得到。

对文件的 delete/rename/create 操作,我们由易到难来介绍:

上一篇 下一篇

猜你喜欢

热点阅读