[vue] iframe 関連の問題

1. iframe ページを更新する

iframe のアドレスが変更されていない場合、iframe ページが開かれるたびにページが積極的に更新されることはありません。

以下にいくつかの方法がありますが、いずれも実現可能です. ページを開くたびに更新してください.

  1. iframe にキーを追加する

<template>
  <div id="Iframe">
    <el-dialog
      append-to-body
      style="margin-top: -10vh"
      custom-class="scrollbar"
      :visible.sync="iframeVisible"
      width="90%"
      @close="close"
    >
      <iframe
        :key="key"
        id="iframe"
        ref="iframeBox"
        :src="url"
        frameborder="0"
        width="100%"
        sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
        :style="{ height: calHeight }"
        scrolling="auto"
      ></iframe>
    </el-dialog>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
import { getToken, setToken } from "@/utils/auth";

export default {
  name: "Iframe",
  computed: {
    ...mapGetters(["userid", "name"]),
    //计算属性 , 设置iframe高度为窗口高度少100px
    calHeight() {
      return window.innerHeight - 150 + "px";
    },
  },
  props: {
    url: String,
    dataid: String,
  },
  data() {
    return {
      iframeVisible: false,
      key: new Date().getTime(),
    };
  },
  watch: {
    // 方法一:
    // iframe上添加key,然后监听
    $route: {
      handler(val) {
        this.key = new Date().getTime();
      },
      immediate: true,
    },
  },
};
</script>

  1. iframe の src のアドレスにタイムスタンプを追加します

<template>
  <div id="Iframe">
    <el-dialog
      append-to-body
      style="margin-top: -10vh"
      custom-class="scrollbar"
      :visible.sync="iframeVisible"
      width="90%"
      @close="close"
    >
      <iframe
        id="iframe"
        ref="iframeBox"
        :src="url"
        frameborder="0"
        width="100%"
        sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
        :style="{ height: calHeight }"
        scrolling="auto"
      ></iframe>
    </el-dialog>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
import { getToken, setToken } from "@/utils/auth";

export default {
  name: "Iframe",
  computed: {
    ...mapGetters(["userid", "name"]),
    //计算属性 , 设置iframe高度为窗口高度少100px
    calHeight() {
      return window.innerHeight - 150 + "px";
    },
  },
  props: {
    url: String,
    dataid: String,
  },
  data() {
    return {
      iframeVisible: false,
    };
  },
  watch: {
     url(newVal, oldVal) {
       if (getToken()) {
         // 方法二
         this.iframeInit(newVal);
       }
     },
  },
  methods: {
    //iframe 初始化
     iframeInit(newVal) {
       let iframe = document.createElement("iframe");
    //利用异步延迟加载和链接随机传参来达到刷新iframe缓存的目的,不加此步骤iframe页面不更新
       this.forceUpdataIframe(iframe, newVal);
     },
     //强制刷新iframe缓存
     forceUpdataIframe(iframe, newVal) {
       setTimeout(() => {
         let fresh_link =
           new Date().getTime() + Math.floor(Math.random() * 1000000); //获取当前时间戳
         String.prototype.splice = function (start, newStr) {
           return this.slice(0, start) + newStr + this.slice(start);
         };
         let strIndex = newVal.indexOf("/#/");
         let url = newVal.splice(strIndex, "?time=" + fresh_link);
         console.log("url", url);
         iframe.src = url;
         // window.open(newVal + "?time=" + fresh_link, "refresh_name");
       }, 300);
     },
  },
};
</script>

2. iframe はロードされましたが、プログレス バーはまだロード中です

  1. 他のソフトウェアが iframe に影響を与える可能性があります

私が遭遇した状況は、私には問題がなく、他の人にも問題はありませんでしたが、別の人は常にロードしている進行状況バーに遭遇し、後で彼のコンピューターの小さなキツネの財布が原因であることがわかりました.バックグラウンドで実行されているため、影響を受けます iframe に到達したら、オフにするだけです。

3、iframe パラメータ

ここでボタンをクリックすると iframe ページが表示されます. iframe はポップアップ ウィンドウにカプセル化されています. これを使用すると, ページ上の iframe を直接使用してジャンプすることができます. iframe をカプセル化する必要はありません.
ここにメインコードを貼り付けます

1. iframe の src でパラメータを取得する

ページを使用してパラメーターを渡す

<template>
  <div id="EditDialog">
      <el-dialog
      append-to-body
      custom-class="dialog"
      :title="title.appname"
      :visible.sync="dialog"
      width="90%"
      style="margin-top: -10vh"
      >
          <div
              style="display: inline; margin: 0 5px"
              v-for="(obj, ind) in List.button"
              :key="ind"
            >
              <el-button
                v-if="obj.type === 3"
                size="small"
                class="Cancelbtn"
                @click="newpage(obj)"
                >{
    
    { obj.name }}</el-button
              >
            </div>
      </el-dialog>

      <!-- 新页面 -->
     <Iframe ref="Iframe" :dataid="Form.dataid" :url="url"></Iframe>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
import Iframe from "@/views/dashboard/Iframe/Iframe.vue";
import { AddComments, Reject,Confirm,BpmUrge,BpmBack,BPMALL} from "@/api/Bpm";

export default {
   data() {
    return {
      dialog: false,
      url: "", //给iframe的地址 
    };
  },
   methods: {
    //打开iframe页面
    newpage(obj) {
      // obj.add_url后端返回的是这样的:http://192.168.4.160:9528/#/Generation?dataid={dataid}
      //其中http://192.168.4.160:9528是在开发阶段就是我们前端运行的地址,项目部署后,就是后端正式的地址
      //  /#/Generation是页面
      //dataid是参数,需要我们赋值的
      if (obj.add_url) {
        const a = obj.add_url.replace(/{dataid}/, this.Form.dataid);
        obj.add_url = a; //绝对路径,也就是http://192.168.4.160:9528开头
        this.url = a;
        //注意使用这种方法iframe需要加sandbox="allow-forms allow-scripts allow-same-origin allow-popups",不然会全屏
        //this.List.add_url = `/#/Generation`;//相对路径
      }
      this.$refs.Iframe.iframeVisible = true;//打开组件的弹窗
    },
   }
}
</script>

iframe コンポーネント

<template>
  <div id="Iframe">
    <el-dialog
      append-to-body
      style="margin-top: -10vh"
      custom-class="scrollbar"
      :visible.sync="iframeVisible"
      width="90%"
      @close="close"
    >
      <iframe
        :key="key"
        id="iframe"
        ref="iframeBox"
        :src="url"
        frameborder="0"
        width="100%"
        sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
        :style="{ height: calHeight }"
        scrolling="auto"
      ></iframe>
    </el-dialog>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
import { getToken, setToken } from "@/utils/auth";

export default {
  name: "Iframe",
  computed: {
    ...mapGetters(["userid", "name"]),
    //计算属性 , 设置iframe高度为窗口高度少100px
    calHeight() {
      return window.innerHeight - 150 + "px";
    },
  },

  props: {
    url: String,
    dataid: String,
  },
  data() {
    return {
      iframeVisible: false,
      key: new Date().getTime(),
    };
  },
  watch: {
    $route: {
      handler(val) {
        this.key = new Date().getTime();
      },
      immediate: true,
    },
  },
  mounted() {
    // 注册监听框架传来的数据
    this.$nextTick(() => {
      // 在外部 Vue 的 window 上添加 postMessage 的监听,并且绑定处理函数 handleMessage
      window.addEventListener("message", this.handleMessage);
    });
  },
  destroyed() {
    // 注意移除监听!
    window.removeEventListener("message", this.handleMessage);
  },
  methods: {
    close() {
      this.iframeVisible = false;
    },

    handleMessage(event) {
      if (event) {
        this.iframeVisible = event.data;
      } else {
        this.iframeVisible = true;
      }
    },
  },
};
</script>

<style lang="scss">
#Iframe {
  width: 100%;
  //   height: 100%;
  // padding: 0 10vw;
  z-index: -1 !important;

  .el-dialog__header {
    background-color: transparent !important;
    padding: 0;
  }
  .el-dialog__body {
    background-color: #f9fafc;
    border-radius: 10px;
    padding: 40px 50px 30px;
    height: calc(100vh - 80px);
    overflow: hidden;
    overflow-y: scroll;

    &::-webkit-scrollbar {
      width: 6px;
      height: 6px;
    }

    // 滚动条的轨道的两端按钮,允许通过点击微调小方块的位置。
    &::-webkit-scrollbar-button {
      display: none;
    }

    // 滚动条里面的小方块,能向上向下移动(或往左往右移动,取决于是垂直滚动条还是水平滚动条)
    &::-webkit-scrollbar-thumb {
      background: rgba(144, 147, 153, 0.3);
      cursor: pointer;
      border-radius: 4px;
    }

    // 边角,即两个滚动条的交汇处
    &::-webkit-scrollbar-corner {
      display: none;
    }

    // 两个滚动条的交汇处上用于通过拖动调整元素大小的小控件
    &::-webkit-resizer {
      display: none;
    }
  }

  .el-dialog__headerbtn .el-dialog__close {
    color: #909399;
    width: 50px;
    height: 30px;
    line-height: 30px;
    border-radius: 5px;
    background-color: #fff;
    box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
  }
  // 发起新的弹窗
  .dialog-footer {
    height: 50px;
    line-height: 50px;
    background: #fff;
    box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
    border-radius: 5px;
    flex-wrap: wrap;
    margin-top: 20px;
  }
  .dialog-header {
    height: 60px;
    line-height: 60px;
    background: #fff;
    box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
    border-radius: 5px;
    flex-wrap: wrap;
    margin-bottom: 20px;
    padding: 0 10px;
    font-size: 16px;
    font-weight: 600;
  }
  .center {
    display: flex;
    width: 100%;
    background: #fff;
    box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
    border-radius: 5px;
    padding: 20px;
  }
}
.scrollbar {
  width: 100%;
  //   height: 100%;
  // padding: 0 10vw;
  z-index: -1 !important;

  .el-dialog__header {
    background-color: transparent !important;
    padding: 0;
  }
  .el-dialog__body {
    background-color: #f9fafc;
    border-radius: 10px;
    padding: 40px 50px 30px;
    height: calc(100vh - 80px);
    overflow: hidden;
    overflow-y: scroll;

    &::-webkit-scrollbar {
      width: 6px;
      height: 6px;
    }

    // 滚动条的轨道的两端按钮,允许通过点击微调小方块的位置。
    &::-webkit-scrollbar-button {
      display: none;
    }

    // 滚动条里面的小方块,能向上向下移动(或往左往右移动,取决于是垂直滚动条还是水平滚动条)
    &::-webkit-scrollbar-thumb {
      background: rgba(144, 147, 153, 0.3);
      cursor: pointer;
      border-radius: 4px;
    }

    // 边角,即两个滚动条的交汇处
    &::-webkit-scrollbar-corner {
      display: none;
    }

    // 两个滚动条的交汇处上用于通过拖动调整元素大小的小控件
    &::-webkit-resizer {
      display: none;
    }
  }

  .el-dialog__headerbtn .el-dialog__close {
    color: #909399;
    width: 50px;
    height: 30px;
    line-height: 30px;
    border-radius: 5px;
    background-color: #fff;
    box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
  }
  // 发起新的弹窗
  .dialog-footer {
    height: 50px;
    line-height: 50px;
    background: #fff;
    box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
    border-radius: 5px;
    flex-wrap: wrap;
    margin-top: 20px;
  }
  .dialog-header {
    height: 60px;
    line-height: 60px;
    background: #fff;
    box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
    border-radius: 5px;
    flex-wrap: wrap;
    margin-bottom: 20px;
    padding: 0 10px;
    font-size: 16px;
    font-weight: 600;
  }
  .center {
    display: flex;
    width: 100%;
    background: #fff;
    box-shadow: 2px 2px 6px rgba(138, 169, 192, 0.2);
    border-radius: 5px;
    padding: 20px;
  }
}
</style>

パラメーターを受け取り、iframe によってリダイレクトされるページ

data() {
    return {
      dataid: "", //编辑弹窗传递的参数
    };
 },
created() {
    // 获取父级中iframe的src,这样就可以获取参数
    this.dataid = window.parent.document
      .getElementById("iframe")
      .src.split("=")[1];
  },

2. 親コンポーネントのデータを取得して変更する

ここの iframe はポップアップ ウィンドウにあります. iframe 内のページのボタンをクリックすると、iframe が配置されているポップアップ ウィンドウを閉じる必要があります, つまり、親のデータを取得する必要があります.コンポーネントを変更して変更します。

親コンポーネント (iframe が配置されるページ)

<template>
  <div id="Iframe">
    <el-dialog
      append-to-body
      style="margin-top: -10vh"
      custom-class="scrollbar"
      :visible.sync="iframeVisible"
      width="90%"
      @close="close"
    >
      <iframe
        :key="key"
        id="iframe"
        ref="iframeBox"
        :src="url"
        frameborder="0"
        width="100%"
        sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
        :style="{ height: calHeight }"
        scrolling="auto"
      ></iframe>
    </el-dialog>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
  name: "Iframe",
  computed: {
    ...mapGetters(["userid", "name"]),
    //计算属性 , 设置iframe高度为窗口高度少100px
    calHeight() {
      return window.innerHeight - 150 + "px";
    },
  },

  props: {
    url: String,
    dataid: String,
  },
  data() {
    return {
      iframeVisible: false,
      key: new Date().getTime(),
    };
  },
  watch: {
    // iframe上添加key,然后监听
    $route: {
      handler(val) {
        this.key = new Date().getTime();
      },
      immediate: true,
    },
  },
  mounted() {
    // 注册监听框架传来的数据
    this.$nextTick(() => {
      // 在外部 Vue 的 window 上添加 postMessage 的监听,并且绑定处理函数 handleMessage
      window.addEventListener("message", this.handleMessage);
    });
  },
  destroyed() {
    // 注意移除监听!
    window.removeEventListener("message", this.handleMessage);
  },
  methods: {
    close() {
      this.iframeVisible = false;
    },
    handleMessage(event) {
      if (event) {
        this.iframeVisible = event.data;
      } else {
        this.iframeVisible = true;
      }
    },
  },
};
</script>

サブコンポーネント (iframe でリダイレクトされるページ)

<template>
  <div id="GetFrom">
     <el-button size="small" class="addbtn" @click="sub()">保存</el-button >
  </div>
</template>

<script>
export default {
  methods: {
    sub() {
      window.parent.postMessage(false, "*"); //关闭iframe所在的弹窗
    },
  },
};
</script>

3. 親コンポーネントが子コンポーネントにデータを渡す

親コンポーネント

<template>
  <div id="Iframe">
    <button @click="sendMessage()">向iframe通信</button>
      <iframe
        :key="key"
        id="iframe"
        ref="iframeBox"
        :src="url"
        frameborder="0"
        width="100%"
        sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
        :style="{ height: calHeight }"
        scrolling="auto"
      ></iframe>
  </div>
</template>

<script>
import { mapGetters } from "vuex";
export default {
  name: "Iframe",
  computed: {
    ...mapGetters(["userid", "name"]),
    //计算属性 , 设置iframe高度为窗口高度少100px
    calHeight() {
      return window.innerHeight - 150 + "px";
    },
  },
  props: {
    url: String,
    dataid: String,
  },
  data() {
    return {
      key: new Date().getTime(),
      iframeWin:'',
    };
  },
  watch: {
    // iframe上添加key,然后监听
    $route: {
      handler(val) {
        this.key = new Date().getTime();
      },
      immediate: true,
    },
  },
  mounted() {
     // 注册监听框架传来的数据
     this.iframeWin = this.$refs.iframeBox.contentWindow
  },
  methods: {
    sendMessage() {
                // 外部vue向iframe内部传数据
                const a = {
                    b: 'Hello-iframe',
                };
                //转化为json字符串,兼容低版本浏览器
                const data = JSON.stringify(a)
                this.iframeWin.postMessage(data, '*')
        },
  },
};
</script>

サブアセンブリ

<script>
export default {
  data() {
    return {
      iframeVisible: false,
      key: new Date().getTime(),
    };
  },
  mounted() {
    // 注册监听,接受父页面消息
    this.$nextTick(() => {
      window.addEventListener("message", this.handleMessage);
    });
  },
  destroyed() {
    // 注意移除监听!
    window.removeEventListener("message", this.handleMessage);
  },
  methods: {
    handleMessage(event) {
                    // 接受消息
                    const x = event.data
                    const data = JSON.parse(x)
                    switch (data.b) {
                        case 'Hello-iframe':
                            {
                                console.log("来自父页面的消息");
                                break;
                            }
                    }
                },
  },
};
</script>

4. その他の問題

1. iframe ページでwordexport などの関数を使用する必要がある

コードにsandbox=" allow-downloads "を追加します

 <iframe
        :key="key"
        id="iframe"
        ref="iframeBox"
        :src="url"
        frameborder="0"
        width="100%"
        sandbox="allow-forms allow-scripts allow-same-origin allow-popups allow-downloads"
        :style="{ height: calHeight }"
        scrolling="auto"
      ></iframe>

補助サンドボックス

allow-forms:允许资源提交表单。如果不使用此关键字,则阻止表单提交。
allow-modals:允许资源打开模式窗口。
allow-orientation-lock:允许资源锁定屏幕方向。
allow-pointer-lock:允许资源使用Pointer Lock API。
allow-popups:允许弹出窗口(例如window.open(),target =“ _ blank”或showModalDialog())。如果不使用此关键字,则弹出窗口将以静默方式无法打开。
allow-popups-to-escape-sandbox:允许沙盒文档打开新窗口,而这些窗口不会继承沙盒。例如,这可以安全地将广告沙箱化,而不必对广告链接到的页面施加相同的限制。
allow-presentation:让资源开始演示会话。
allow-same-origin:如果不使用此令牌,则资源被视为来自特殊来源,该来源始终失败于同源政策。
allow-scripts:让资源运行脚本(但不创建弹出窗口)。
allow-storage-access-access:允许资源使用Storage Access API请求访问父级的存储功能。
allow-top-navigation:允许资源浏览顶级浏览上下文(一个名为_top的浏览上下文)。
allow-top-navigation:允许资源导航顶级浏览上下文,但仅在由用户手势启动的情况下。

2. iframe はポップアップ ウィンドウにあります

iframe にサンドボックスを追加する必要があります。そうしないと、デフォルトでフルスクリーンになります

sandbox="allow-forms allow-scripts allow-same-origin allow-popups"

3. iframe は PDF を表示しますが、表示しません

iframe は iframe をネストし、サンドボックス サンドボックスは親コンポーネントの iframe で使用されるため、子コンポーネントの iframe は PDF を表示できません

他に方法はありません。つまり、子コンポーネントの iframe を抽出し、親コンポーネントの代わりにポップアップ ウィンドウに配置することです。

この記事を読んで、何か得したなと思った方、良かったと思った方は、いいねと保存をお願いします。

おすすめ

転載: blog.csdn.net/Qxn530/article/details/129297977