https://segmentfault.com/q/1010000016866230
求助朋友们。
Antd Design Pro2 多页签下,两个路由使用同一组件,页面如何独立
链接里面就是具体问题描述。朋友们,若有解决方案,恳请留言相助。
https://segmentfault.com/q/1010000016866230
求助朋友们。
Antd Design Pro2 多页签下,两个路由使用同一组件,页面如何独立
链接里面就是具体问题描述。朋友们,若有解决方案,恳请留言相助。
这种标签模式在本地应用中没什么毛病,但在web游览器中他其实和游览器行为是完全对立的。
传统路由如react-router之类的东西, 都是用过监听游览器路径来实现路由的, 所以路由入口是唯一的。
而标签模式下, 很难单纯通过url识别究竟是新建一个标签,还是在更新某个标签内部的页面内容, 需要通过用户行为来识别。
操作1 用户点击菜单打开 /pageA
操作2 然后又点击菜单打开 /pageB
操作3 最后点击游览器返回的返回上一页
这时候,程序只能跟踪到url变成了/pageA, 在不知到用户操作情况下,无法判定究竟是要作出下列哪个行为
正常点的web页面, 路由的入口仅仅是url, 而url本身没有上下文, 无状态, 所以不存在歧义,刷新,前进,后退不会造成问题。
但是标签模式没法仅仅从url上消除歧义,需要至少需要通过 用户操作+上下文, 而用户行为+上下文难以映射为url,所以不要指望用传统的路由来做标签模式的路由了。
下面是个简单的标签模式的实现,注意如果要用标签模式,就别指望用基于URL变化的传统路由了,乖乖自己写路由吧。
import PageA from "./PageA"
import PageA from "./PageA"
class App extends React.Component {
state = { current: 0, pages: [] }
uniqId = 0
render(){
return (
<div>
<aside>
<div onClick={()=> this.create("Page A", PageA, { search: {id: "xxxxx"} })}>
新建页面PageA
</div>
<div onClick={()=> this.create("Page B", PageB, { search: {id: "xxxxx"} })}>
新建页面PageB
</div>
</aside>
<nav>
{this.pages.map((page, i)=>
<div onClick={()=> this.setState({current: i})}>
{page.title}
</div>
)}
</nav>
{this.state.pages.map(({key, component, props}, index)=>(
<div key={key} style={display: index === this.state.current ? "block": "none"}>
<component {...props}
createPage={this.createPage.bind(this)}
changePage={this.replacePage.bind(this, index)}/>
</div>
))}
</div>
)
}
createPage(title, component, props) {
this.setState({ pages: [
...this.state.pages,
{ component, title, props, key: this.uniqId++ }],
current: this.state.pages.length,
})
}
replacePage(index, title, component, props ){
const pages = [...this.sate.pages];
pages[index] = { key: this.uniqId++, component, title, props };
this.setState({pages})
}
}
用 redux, 或者 React.createContext 配合 高阶组件
额,现在问题是pageA,pageB两个是同一个组件,只是路由不一样。为什么会这样呢,是因为需求要通过配置生成页面,也就是说通过参数不同,我在这个组件里渲染不同的dom。比如pageA这个页面有5个input,pageB页面有6个input。但实际上两个页面关联的组件都是同一个组件。
然后,我在页签下,同时打开这两个页面,由于用的是同一个组件,参数就被后打开的重置了。比如先打开pageA,再打开pageB,pageA的input也变成6个了。
加一个key,当切换标签的时候,让react强制重新生成组件
return (){
return (
<>
<Nav></Nav>
<Main key={this.state.activePath} />
</>
)
}
这个肯定不行的,不能刷新的。
不过问题已经解决了,是自己2了。两个页面渲染依赖的model是同一个,也就是说state是同一个,state变化就把所有页面都重现渲染了。现在对state拆一下,之前是state:[],现在是state:{key:state1,key:state2},每个页面都有一个唯一的key,也就有专属的state了。
仍然非常感谢您的搭理。祝您生活愉快。
我这边多路由的状态管理是自己用redux实现的,我之前的问题是多个路由对应了一个state,后来将多个路由的state分为多个,就解决了。至于状态管理如何用redux实现, 我这边没现成写好的答案,你可以百度下。
你好大佬,我这边有个类似的需求。
前提
1.公司技术栈老旧,之前的项目都是后端直接用jsp写的,大部分管理后台类的项目都是iframe嵌入到页面,多标签页模式。
2.现在我用antdpro搭了一套管理后台,左侧菜单从后端获取,菜单对应的页面分两种:需要使用iframe嵌入的若干页面,我自己用组件写的有相应路由的页面。
3.由于老项目点击菜单不会改变url,所以iframe渲染的页面我把后端返回的路径拼接成完整的待嵌入页面链接,key放入到redux中。格式如下:
{
path: {
'1edb365':{
path: 'viewlet=1&originid=2',
frUrl: true
}
},
activeKey: '1edb365'
}
其中,path对象存储着目前打开的标签页的信息,每个标签页都有唯一的key值,activeKey代表激活哪个标签页,frUrl是一个标识符若是需要iframe嵌入的则为true,否则为false需要跳转到对应路由。
问题
1.我在点击菜单项的时候会根据其后端返回的每一项菜单内部的frUrl值决定是否点击之后增加redux里的path项,并修改当前activeKey。这些iframe嵌入的页面都在路由/Iframe下进行渲染,路由对应组件接受props,拿到完整页面的url进行渲染。但是,我不知道如何渲染自己的路由页面。
2.自己的页面势必涉及到唯一的路由,如果要做到老项目的效果,点击任何菜单不会修改地址栏路径,又能区分自己页面还是iframe页面,该如何改造。