需要在页面上显示支付宝付款码。后端对接后,前端请求后端获取数据,通过 form 表单提交数据最终会得到一个 url。但这个 url 不是图片链接而是一个 html,其中二维码以 canvas 的形式展示。
问题,如何在 dialog 弹窗中显示这个付款码?因为 form 表单请求后会刷新页面。
既然是一个 html,那可以使用 iframe 来显示这个图片,这样即便触发刷新也不影响当前页面。于是有2个思路:
iframe 中发起 form 表单请求。form 表单的响应信息放到 iframe 中。查阅资料,发现 form 表单有一个属性 target ,可以指定响应信息的显示位置。所以第2种更简单一点。
在 mdn 中,
form.target有 4 个可选值,但也可指定为iframe.name。这样就能用iframe来显示form表单提交的响应信息。
需要一个 form 表单和 iframe
<form target="iframe">
<input type="hidden" />
form>
<iframe name="iframe">iframe>
<template>
<div style="width: 200px; height: 200px">
<iframe name="iframe" frameborder="0" class="alipay-iframe">iframe>
div>
<form target="iframe" ref="_formALIPAY" method="post" :action="info.submitUrl">
<input v-for="(value, key) in info.formInputs" :key="key" :name="key" :value="value" type="hidden" />
form>
template>
<script setup>
import { ref, watch, nextTick } from 'vue'
// { submitUrl: '', formInputs: {} }
const props = defineProps(['info'])
const _formALIPAY = ref(null)
watch(
() => props.info,
async (nv) => {
if (nv) {
await nextTick()
_formALIPAY.value.submit()
}
}
)
script>
<style>
.alipay-iframe {
width: 305px;
height: 305px;
transform-origin: 40px 40px; // 缩放原点
transform: scale(0.52459); // (200 - 40)/305
}
style>
网路问题导致请求慢时,iframe 是一个空白的区域,需要加一个 loading 动画。
1,通过 v-if 或 v-show 的方式来判断展示 loading
不行,因为无法得知 form 请求完成的时间。
2,一开始展示 loading,当 iframe 有内容时,自动覆盖掉 loading
不行,因为 iframe 一开始就有宽高和背景,如果一开始置为空得到请求后再设置,那又回到了第一个方式。
3,背景图!(使用的方案)
给 iframe 加一个 gif 的背景图,这样图片展示后自动覆盖。
<style>
.alipay-iframe {
// ...
background-image: url('./loading.gif');
background-repeat: no-repeat;
background-size: 150px 150px;
background-position: center;
}
style>
以上。