Open shuangmianxiaoQ opened 5 years ago
最近做需求时有一个模仿在线Windows文件加的需求,难度不大,在模拟导航时发现了一个巧妙的方法,记录一下(下面是在线的完整Demo)。
Windows
Demo
大致效果图如下:
模拟导航前进后退时,一开始想到的办法是设置两个状态,去根据条件判断什么时候能前进或后退,但是这个条件可能不太好找,写起来也啰嗦。于是在谷歌上搜索了一番,看到栈这个关键词,突发奇想,浏览器的前进后退不就是用栈结构进行入栈出栈来实现的嘛,那么先来看看怎么使用JS实现栈数据结构:
JS
// 模拟一个简单的栈 class Stack { constructor() { this.stack = []; this.action = ""; } push(...items) { this.action = "PUSH"; return this.stack.push(...items); } pop() { this.action = "POP"; return this.stack.pop(); } }
上面这个构造函数很简单,就是设置两个状态,一个记录栈的内容,一个记录栈操作(入栈和出栈),那么后面就是使用这个栈了,就是在点击文件夹或点击导航时进行入栈和出栈操作即可
state = { stack: new Stack() }; pushToStack = () => { this.state.stack.push(1); this.setState(() => ({ stack: this.state.stack })); }; popFromStack = () => { this.state.stack.pop(); this.setState(() => ({ stack: this.state.stack })); };
最后就是完成能否前进后退的功能了,根据简单的推演,可以得出下面的结论(下面isPrev表示能否后退,isNext表示能否前进): 初始状态 -> isPrev: false, isNext: false 入栈 -> 压入值为新值时,isPrev: true, isNext: false;压入之前存在的值,isPrev: true, isNext: true 出栈 -> 栈不空时,isPrev: true, isNext: true;栈空时,isPrev: false, isNext: true
isPrev
isNext
isPrev: false, isNext: false
isPrev: true, isNext: false
isPrev: true, isNext: true
isPrev: false, isNext: true
下面是转换状态的一个简单实现:
// value 是上面的栈实例 const computedStatus = value => { const { stack, action } = value; let status = { isPrev: false, isNext: false }; if (action === "PUSH") { status = { isPrev: true, isNext: false }; } else if (action === "POP") { status = stack.length === 0 ? { isPrev: false, isNext: true } : { isPrev: true, isNext: true }; } return status; };
经过实践之后,发现上面的入栈出栈方式并不能很好的解决导航前进后退,反而是将问题复杂化了。 在同事的指导下,采用了另一种思路,巧妙地解决了问题:
下面是大致的栈数据结构:
最后判断能否前进后退也很简单。如果指针指向头位置则导航不能后退,如果指针指向尾位置则导航不能前进
最近做需求时有一个模仿在线
Windows
文件加的需求,难度不大,在模拟导航时发现了一个巧妙的方法,记录一下(下面是在线的完整Demo
)。大致效果图如下:
模拟栈数据结构
模拟导航前进后退时,一开始想到的办法是设置两个状态,去根据条件判断什么时候能前进或后退,但是这个条件可能不太好找,写起来也啰嗦。于是在谷歌上搜索了一番,看到栈这个关键词,突发奇想,浏览器的前进后退不就是用栈结构进行入栈出栈来实现的嘛,那么先来看看怎么使用
JS
实现栈数据结构:使用栈
上面这个构造函数很简单,就是设置两个状态,一个记录栈的内容,一个记录栈操作(入栈和出栈),那么后面就是使用这个栈了,就是在点击文件夹或点击导航时进行入栈和出栈操作即可
实现前进后退功能
最后就是完成能否前进后退的功能了,根据简单的推演,可以得出下面的结论(下面
isPrev
表示能否后退,isNext
表示能否前进): 初始状态 ->isPrev: false, isNext: false
入栈 -> 压入值为新值时,isPrev: true, isNext: false
;压入之前存在的值,isPrev: true, isNext: true
出栈 -> 栈不空时,isPrev: true, isNext: true
;栈空时,isPrev: false, isNext: true
下面是转换状态的一个简单实现:
分割线
经过实践之后,发现上面的入栈出栈方式并不能很好的解决导航前进后退,反而是将问题复杂化了。 在同事的指导下,采用了另一种思路,巧妙地解决了问题:
下面是大致的栈数据结构:
最后判断能否前进后退也很简单。如果指针指向头位置则导航不能后退,如果指针指向尾位置则导航不能前进