先上两张页面截图,下文中要用到
A页面
B页面
用户希望点击 A 页面的【顾客姓名】,然后弹框显示 B 页面的内容。之前是通过页面跳转实现的,用户反馈太麻烦了,效率低下,要求改成弹框。
由于 B 页面是个合成的复杂页面,将其改造成组件,然后进行弹框将会比较麻烦。项目做了三四年,经过了很多人的手,代码修改维护已经很难了,一般不轻易动原先的代码。既然改造方案不好实行,那么就想到了通过 iframe 的方式,直接将 B 页面嵌套在弹框里进行显示就可以了。
1、在 A 页面中写一个弹框,然后弹框里面放入 iframe
<el-dialog :visible.sync="showMemberInfo" title="会员信息">
<div style="width: 80vw; height: 80vh;">
<iframe
:src="iframeSrc"
width="100%"
height="100%"
frameborder="0"
scrolling="no">
</iframe>
</div>
</el-dialog>
el-dialog 是 element-ui 的弹框组件,iframeSrc 是B页面的页面路径,下面是 A 页面中的部分代码
data () {
showMemberInfo: false,
iframeSrc: ''
},
methods: {
viewMemberInfo (row) {
// 项目采用的是 hash 路由模式
this.iframeSrc = `/#/member/info?vipId=${row.vipId}`
this.showMemberInfo = true
}
}
2、 B 页面接收一个 vipId 参数,通过传入的 vipId 加载会员相关信息。 但是,通过 iframe 弹框的方式,尽管每次传入的 iframeSrc 中的 vipId 更新了,但是弹出的 B 页面的数据并没有自动更新。所以我们需要自行处理一下,下面是 B 页面的部分代码
data () {
return {
// ...
}
},
created () {
this.getMemberInfo()
},
beforeRouteUpdate(to, from, next) {
// 关于此路由钩子的说明
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
this.getMemberInfo() // 获取会员信息
next();
},
methods: {
getMemberInfo () {
// ...
}
}
我们的处理方式主要是通过 beforeRouteUpdate 路由钩子来实现,当路由参数更新时,会自动触发此钩子,然后在钩子内部调用获取会员信息的方法就行了,这样每次传入的 vipId 参数变更时,都能拿到对应的会员数据,而不会是上一次的缓存数据 。
3、由于 iframe 是直接嵌套的整个页面,所以左边的菜单栏也会出现在弹框中,这就感觉比较奇怪了,所以我们需要处理一下。我们可以判断当前页面是否是在 iframe 中打开,如果是,则隐藏左边的菜单栏。
// 计算属性
computed: {
// 判断页面是否是在 iframe 中打开
isIframe () {
return window.self !== window.top;
}
}
在 template 中使用
<div class="menu" v-if="!isIframe">...</div>