关于iframe一些通讯的记录(可适用工作流审批,文中有项目实践,欢迎咨询)
Posted 是小橙鸭丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于iframe一些通讯的记录(可适用工作流审批,文中有项目实践,欢迎咨询)相关的知识,希望对你有一定的参考价值。
一.知识点
(1).我们可以通过postMessage(发送方)和onmessage(接收方)这两个html5的方法, 来解决跨页面通信问题,或者通过iframe嵌套的不同页面之间的通信
a.父页面代码如下
<div v-if="src" class="iframe">
<iframe
ref="iframe"
id="iframe"
width="100%"
height="600"
loading="lazy"
:src="src"
frameborder="0"
scrolling="no"
marginheight="0"
marginwidth="0"
@load="loaded"
></iframe>
</div>
a1.父页面向子页面发送信息(两种方法)
第一种
const iframe = document.getElementId('iframe')//id
//第一个参数是发送的消息,无格式要求;第二个参数是域名限制,当不限制域名时填写*
// 后面的 * 号就是处理跨域问题的,任何域名都不会出现跨域问题
// 传递的参数可以是数组,对象,字符串等
iframe.contentWindow.postMessage('你需要传的数据', "*"); //数据比如(,'*'),('123','*')
// 也可以指定传送域名地址,这个域名不会出现跨域问题,写父页面(接收)域名地址
iframe.contentWindow.postMessage("需要传递的参数", 'http://0.0.0.0:8080')
第二种
this.$refs.iframe.contentWindow.postMessage(workDetailsData.workflowList,'*')
a2.子页面接收父页面收到的信息
* 函数防抖
* @param fn
* @param interval
* @returns Function
* @constructor
*/
export const Debounce = (fn, t) =>
let delay = t || 500
let timer
return function ()
let args = arguments
if (timer)
clearTimeout(timer)
timer = setTimeout(() =>
timer = null
fn.apply(this, args)
, delay)
import Debounce from '@/utils/public.js'
mounted()
window.onmessage = this.handleMesg
// addEventListener触发多次问题
// window.addEventListener('message', this.handleMesg)
,
//防抖处理
handleMesg: Debounce(function (e)
//这里做接收数据的操作
if(e)
console.log(e.data)
),
a.3子页面(iframe加载的页面)向父页面传递消息
window.parent.postMessage(string: '我是iframe里面的数据', "*");
a.4父页面接收子页面传递的消息
window.onmessage = function(event)
console.log(event.data.string) //我是iframe里面的数据
a.5 父页面接收子页面传递的消息(第二种)
//监听单个事件
window.addEventListener('message', function (msg)
console.log(msg.data.string)
)
二.项目实践
1.效果图
编辑
编辑
编辑
逻辑如下
1.首先点击审批通过按钮,调用方法
<el-button
v-if="hasApproved"
type="primary"
size="small"
@click="submit('Approved')"
>
审批通过
</el-button>
2.方法如下
// 审批
submit(data)
this.operateStatus = data //传过来的状态储存起来
if (this.suspended) //默认是false 请求详情接口时会根据后端返回这个字段判断他是否挂起
this.$message.error('该任务已挂起,无法进行操作!')
return
if (data === '撤回')
this.confirmSubmit()
return
let label = data === 'Approved' ? '审批通过' : '审批拒绝'
this.assignee_schema_model.comment =
data === 'Approved' ? '批准' : '拒绝'
this.dialogTitle = `确认是否$label`
this.msgContent = `确认$label吗?`
this.visible = true //打开弹窗
,
弹窗如下
3.点击确定调用接口方法,调用接口时进行一些判断操作如下
confirmSubmit()
let data = this.operateStatus
this.isLoading = true
if (data === 'Approved' || data == 'Rejected')
const params = //审批流接口需要的参数
variables: [
name: 'approveResult',
value: data === 'Approved' ? 'Approved' : 'Rejected', //判断是同意还是拒绝
,
name: 'comment',
value: this.assignee_schema_model.comment,
,
name: 'isWithdraw',
value: '0',
,
],
action: 'complete',
comment: this.assignee_schema_model.comment,
currentTaskId: this.$route.query.id,
if (!this.assignee_schema_model.comment) //判断是否写了批注 不能为空
this.$message.error('请输入批注!')
this.isLoading = false
return
//重点 这里假如你是需要在自己的页面,比如商品详情页面,即iframe的页面自己调用自己中心的后端接口,不通过公共的审批接口时,需要进入这里,this.isPostMsg这个数据需要自己判断是否需要进入
if (this.isPostMsg && data == 'Approved')
// 审批动作在iframe页面中完成
this.$refs.iframe.contentWindow.postMessage( //向iframe 页面传递信息
status: data,
value: this.assignee_schema_model.comment,
params: params,
,
'*'
)
this.visible = false
this.isLoading = false
window.addEventListener('message', this.handleMesg) //接收iframe页面传递过来的信息
return //不往下执行 即不调用公共审批接口
if (!this.src) //判断配置
console.log('审批流配置问题,formKey为空')
this.$message.error(
'流程配置问题,/activiti/task接口返回的formKey为空'
)
this.visible = false
this.isLoading = false
return
if (!this.isOpenIframe(this.src))
//没有被审批流程的菜单权限
this.$message.error(this.authMenuMsg)
this.visible = false
this.isLoading = false
return
taskAction(params) //调用公共审批接口 (包含了同意和拒绝) 根据定义的参数判断
.then((res) =>
if (res.failed === true)
this.$message.error(res.message || '操作失败,请联系管理员')
this.isLoading = false
else
this.$message.success('操作成功')
this.visible = false
this.isLoading = false
this.$store.dispatch( //关闭当前页面路由
'tabsBar/delVisitedRoute',
this.$route.fullPath
)
this.$router.push(`/tcl/tof/message/workflow/wait-list`) //跳转到待办列表页面
)
.catch((error) =>
this.$message.error(error)
this.isLoading = false
)
else
// 撤回
backAction(this.$route.query.id) //撤回流程公共 接口
.then((res) =>
if (res.failed === true)
this.$message.error(res.message || '操作失败,请联系管理员')
this.isLoading = false
else
this.$message.success('操作成功')
this.$store.dispatch(
'tabsBar/delVisitedRoute',
this.$route.fullPath
)
// this.$router.go(-1)
this.visible = false
this.isLoading = false
this.$router.push(`/tcl/tof/message/workflow/wait-list`)
)
.catch((error) =>
this.$message.error(error)
this.isLoading = false
)
,
4.父页面的handleMesg方法(重点交互)
//防抖 (debounce): 将多次高频操作优化为只在最后一次执行,通常使用的场景是:用户输入,只需再输入完成后做一次输入校验即可。
//防抖处理 高频调用
handleMesg: Debounce(function (e)
if (e.data.type == 'getDataDetail')
//子页面想要获取待办详情接口数据 会主动发送一个事件过来
//如判断type是哪个页面过来的
//这里向子页面发送数据回去
this.$refs.iframe.contentWindow.postMessage(
workDetailsData.workflowList, //待办详情接口返回的数据
'*'
)
//这里可以自定义提示信息的操作
//iframe子页面会发送一个方法过来 如第五点
if (e.source)
if (e.data.status == 'Approved')
//补充知识
//getElementsByClassName() 方法返回文档中所有指定类名的元素集合,作为 NodeList 对象。
//NodeList 对象代表一个有顺序的节点列表。NodeList 对象 我们可通过节点列表中的节点索引号来访问列表中的节点(索引号由0开始)。
//提示: 你可以使用 NodeList 对象的 length 属性来确定指定类名的元素个数,并循环各个元素来获取你需要的那个元素。
let doms = document.getElementsByClassName('el-message')[0]
if (doms == undefined)
this.$message.success('审批通过')
this.visible = false
this.$store.dispatch(
'tabsBar/delVisitedRoute',
this.$route.fullPath
)
if (this.$route.query.type === 'workflow')
this.$router.push(`/tcl/tof/order/sales/workflow`)
else this.$router.push(`/tcl/tof/message/workflow/wait-list`)
else if (e.data.status == 'Rejected')
let doms = document.getElementsByClassName('el-message')[0]
if (doms == undefined)
this.$message.success('审批拒绝')
this.visible = false
if (this.$route.query.type === 'workflow')
this.$router.push(`/tcl/tof/order/sales/workflow`)
else this.$router.push(`/tcl/tof/message/workflow/wait-list`)
else if (e.data.status == 'innerError')
let msgObj = e.data
this.$message(
type: msgObj.msgType,
message: msgObj.msg,
)
),
5.子页面方法
that.postMsgToFrame('缺少附件', 'warning')
postMsgToFrame(msg, errType)
if (this.isPorcess)
window.parent.postMessage(
type: 'custAddMsg',
status: 'innerError',
msgType: errType,
msg: msg,
,
'*'
)
else
this.$message(
type: errType,
message: msg,
)
,
子页面一开始要获取审批流待办详情接口数据来进行一些判断如下
mounted()
// console.log('workDetailsData', workDetailsData)
//首先向父页面主动发送事件
if (this.$route.query.type == 'delay')
window.parent.postMessage(
type: 'getDataDetail',
,
'*'
)
//父页面发送事件过来,这里接收事件和数据,进行对应的操作,如判断该字段在哪个节点是否需要显示
window.addEventListener('message', (e) =>
if (e.data)
let showNode = []
if (this.options.nodeStatus && this.options.nodeStatus.length > 0)
this.options.nodeStatus.forEach((item) =>
showNode.push(item.value)
)
console.log('这里的数据看看', showNode)
if (showNode.indexOf(e.data.name) != -1)
obsData.isFlagShowCol = true
)
,
配置平台配置流程
iframe页面判断审批同意接口是否调用自己中心的后端接口
computed:
isPorcess:
get()
let ll = this.$route.query
if (ll.custPostMsgFlg && ll.custPostMsgFlg.indexOf('true') > -1)
return true
else
return false
,
,
进入页面在mounted判断,需要节点都挂载完毕,然后在方法methods中调用审批方法,是由父页面点击审批通过发送事件过来进行调用
mounted()
if (this.isPorcess)
window.addEventListener('message', this.handleMesg)
methods:
// 点击审批
async handleMesg(e)
console.log('e', e)
if (e.data.status === 'Approved') //判断是否同意
// this.$refs.Address.$refs.tabs.validate()
this.examineApprove()
,
async examineApprove()
//先进行表单必填校验操作 通过才调用接口
let flag = await this.$refs.Address.validateForm()
this.$refs['commentForm'].validate((isPass) =>
this.schema_model.comment = this.commentForm.comment //批注自定义
this.$refs['filterForm'].validate((valid) =>
//校验
if (valid && flag && isPass)
const loading = this.$baseLoading(
target: 'document.body.tree',
)
subsidyPriceProcess(this.schema_model).then((res) =>
if (res.success == false)
loading.close()
this.$message.error('审批不通过,接口报错')
else
loading.close()
//iframe 向父组件传值
window.parent.postMessage(
type: 'commodityApprove',
status: 'Approved',
,
'*'
)
)
else
this.$message(
type: 'error',
message: '表单校验不通过!',
)
return false
)
)
,
以上是关于关于iframe一些通讯的记录(可适用工作流审批,文中有项目实践,欢迎咨询)的主要内容,如果未能解决你的问题,请参考以下文章