开发一个封装iframe的vue组件

VUE的基本组成单元,我看应该是组件。用VUE开发前端项目,就是开发一个个组件,然后搭积木一样,将项目搭建出来。组件包含在页面,或者是更大的组件里面。在这里,组件与页面的界限,好像并不明显。事实上,对于单页应用,只有一个页面。

组件的好处,一是可以加强复用;二是能够将特定功能封装,利于调用;三是由于职责分明,组件高内聚,组件间低耦合,利于系统功能的优化、扩展和维护。好处多多。

开发组件,主要有2部分内容:
1、组件内部逻辑
2、外部接口
由于我这两天弄的组件,里面包含有一个<iframe>,那么还有一部分工作内容:
3、iframe接口

一、组件介绍

这是一个地图插件。功能是展示地图,以及接受外部命令,加载图层、绘制图形等相关操作。地图采用arcgis for js实现。由于我们过去开发的项目,地图操作有一些积累,不过并没有前后端分离,没有采用VUE或REACT,还是传统的WEB页面。因为时间紧,也想直接复用以前的成果,于是考虑用<iframe>承载地图页面,封装在VUE组件里,由组件对接外部命令并与iframe里的地图页面交互。

二、组件内部结构及逻辑

1、代码组织结构

2、地图组件

Map.vue

<template>
  <div class="map-container">
  	<!-- 承载地图页面 -->
    <iframe :src="src" ref="iframe" @load="iframeLoad"></iframe>
  </div>
</template>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped="scoped">
  .map-container iframe{
    width: 100%;
    height: 100%;
    border: none;
  }
</style>

<script>
  import config from '../../vue.config'//里面有路径信息

  let iframeWin = null;//私有变量

  export default {
    props:['size'],//纯测试,没啥用,对应<Map id="map" ref="map" size="100"></Map>
    data() {
      return {
        src: '',//地图页面地址
        isLoaded: false,//地图页面是否加载完毕
        iMap: null,//地图页面暴露出来的,供外部访问的对象
        require: null//arcgis的require函数,用于引用自定义插件。我们过去写了不少自定义的地图插件
      }
    },
    created() {
      this.src = config.publicPath + 'map.html'
    },
    mounted() {
    	//监听iframe的消息
      window.addEventListener('message', this.handleMessage)
      iframeWin = this.$refs.iframe.contentWindow
    },
    methods: {
      iframeLoad() {
        this.isLoaded = true;
        window.console.log("map is ready")
      },
      async handleMessage() {//接收来自iframe的消息
        this.require = iframeWin.require;
        this.iMap = iframeWin.iMap;
      },
      loadLayer(nodes,servers){
        this.iMap.layerHandler.load(nodes,servers);
      },
      isReady(){
        return this.isLoaded;
      }
    }
  }
</script>

有关组件的结构,比如

export default {
  props:,//标记里的属性
  data() {//公共变量
  },
  created() {//加载时?
  },
  mounted() {//加载完毕时
  },
  methods: {//公共方法
  }
}

export代表了这是对外。所以里面的属性、变量、方法,都可以被外部访问。如果想私有,应该在export之外定义。如本例:

像这类简单的介绍,在网上怎么也搜不到。vue的中文站点,陈旧,内容支离破碎,对初学者极不友好,加重了学习的成本。

三、iframe接口

组件Map.vue与里面的iframe是怎么通信的呢?
通过系统消息和直接访问iframe的对象。直接访问iframe里的对象有个前提,就是不能跨域。

iframe承载的地图页面map.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
		...
  </head>
  <body>
    <div id="map"></div>
		...
    </div>    

  </body>
</html>
<script src="http://192.168.0.200/pubzy211/arcgis_js_api/3.19/init.js"></script>
<script type="text/javascript">
  var iMap = {}; //外部引用接口

  require([
    "esri/config",
    "esri/map",
    "esri/geometry/Extent",
    "esri/SpatialReference",

    "layerlib/LtLayer",

    "dojo/dom",
    "dojo/_base/array",
    "dojo/parser",
    "dojo/domReady!"
  ], function(
    esriConfig,
    Map,
    Extent,
    SpatialReference,

    LtLayer,
    dom,
    arrayUtils,
    parser
  ) {
    //map
    var map = ...

    /* 外部接口 */
    iMap = {
      map: map,
      legend: legend,
      home: home,
      tipDialog: tipDialog,
      toggle: toggle,
      overviewMap: overviewMap
    };
    iMap.drawHandler = ...
    iMap.layerHandler = ...;
    iMap.centerAt = ...;
    iMap.clear = ...;
    iMap.restoreView = ...;

    // 向父vue页面发送加载完毕信号
    window.parent.postMessage({
      cmd: 'mapIsReady',
      params: {
       success: true,
       data: true
      }
    }, '*');
    /* end of 外部接口 */

  });
</script>

地图组件Map.vue对应iframe部分,详见一.2中的代码

export default {
		。。。
    mounted() {
	    //监听iframe的消息
      window.addEventListener('message', this.handleMessage)
      //获得iframe的window对象
      iframeWin = this.$refs.iframe.contentWindow
    },
    methods: {
      iframeLoad() {
        this.isLoaded = true;
        window.console.log("map is ready")
      },
      async handleMessage() {//接收来自iframe的消息
        this.require = iframeWin.require;
        this.iMap = iframeWin.iMap;
      },
      loadLayer(nodes,servers){
      	//加载图层
        this.iMap.layerHandler.load(nodes,servers);
      }
    }
  }

四、外部接口

Map.vue是一个组件,它要跟它所在的组件或页面进行通信。

现在,Map.vue放在了一个容器页面Home.vue(即测试页面)里,里面还有一个命令组件Layer.vue。点击命令组件里的按钮,地图要做出相应的响应。其中的原理如下:

命令组件的按钮点击后,发射信息到容器页面,然后容器页面调用地图组件的方法。

测试页面Home.vue

<template>
  <div id="app1">
    <div id="map-container">
      <div>地图组件</div>
      <Map id="map" ref="map" size="100"></Map>
    </div>
    <div id="layer-container">
      <div>其他组件</div>
      <Layer @loadLayer="loadLayer" @loadCloud="loadCloud" @clear="clearMap"></Layer>
    </div>
  </div>
</template>

<script>
  import Map from '../components/Map.vue'
  import Layer from '../components/Layer.vue'

  export default {
    name: 'App',
    components: {
      Map,
      Layer
    },
    methods:{
      loadLayer(nodes,servers){//加载图层
        let map = this.$refs.map;
        map.loadLayer(nodes,servers);
      },
      loadCloud(data){//加载卫星云图
        let map = this.$refs.map;
        map.require(["drawlib/Cloud"], function (Cloud) {
          let iMap = map.iMap;
          let cloudId = 'cloud';
          let cloud = new Cloud(iMap.map);
          iMap.drawHandler.push(cloudId, cloud);
          cloud.draw(data,cloudId);
        });
      },
      clearMap(){//清除
        let map = this.$refs.map;
        map.iMap.clear();
      }
    }
  }
</script>

<style>
。。。
</style>

命令组件Layer.vue

<template>
  <div class="layer-container">
    <button @click="loadLayer">加载图层</button>
    <button @click="loadCloud">卫星云图</button>
    <button @click="clear">清除</button>
  </div>
</template>

<script>
  export default {
    methods: {
      loadLayer() {
        let nodes = ...
        let servers = ...
        this.$emit("loadLayer", nodes,servers)
      },
      loadCloud(){
        let data = ...;
        this.$emit("loadCloud", data);
      },
      clear(){
        this.$emit("clear");
      }
    },
  }
</script>

<style scoped="scoped">
。。。
</style>

注意命令组件发射消息中指定的方法,在容器页面中都有相关的属性与之对应:

命令组件
loadCloud(){
  let data = ...;
  this.$emit("loadCloud", data);
},

容器页面
<Layer @loadLayer="loadLayer" @loadCloud="loadCloud" @clear="clearMap"></Layer>

五、运行结果

六、总结

其他组件要与地图组件交互,中间要通过容器页面,其他组件与地图组件并没有直接交互。这其实是一种命令模式。好处是其他组件和地图组件解耦,没有耦合在一起,意味着互不影响。这有利于地图组件本身的扩展和优化。缺点的话,每个东东都要通过容器页面转发,容器页面代码可能会有冗余,有些方法根本就是个传声筒,给人的感觉是重重复复的写,意义不太大。

以上就是开发一个封装iframe的vue组件的详细内容,更多关于封装iframe的vue组件的资料请关注我们其它相关文章!

(0)

相关推荐

  • Vue中对iframe实现keep alive无刷新的方法

    前言 最近一个需求,需要在 Vue 项目中加入 含有iframe 的页面,同时在路由切换的过程中,要求iframe的内容 不会被刷新 .一开始使用了Vue自带的keep- alive发现没有用,于是自己研究了一下解决方案...... Vue的keep-alive原理 要实现对保持iframe页的状态.我们先搞清楚为什么Vue的keep-alive不能凑效.keep-alive原理是把组件里的节点信息保留在了 VNode (在内存里),在需要渲染时候从Vnode渲染到真实DOM上.iframe页里

  • vue与iframe之间的信息交互的实现

    说一下我的使用场景:在vue中使用百度地图,需要使用离线地图 先上代码 然后细细品 第一张图 第二张图 第三张图 1.首先iframe 引入你要嵌套的地址 2 .通过vue中给出的ref 来获取 ifarme的DOM元素 如图中的 this.iframeWin = this.$refs.iframe.contentWindow [拿到iframe的window对象] 3.vue如何向iframe内传送信息 可以通过H5新属性 postmessage 注释:[postMessage是有点类似于UD

  • Vue集成Iframe页面的方法示例

    1. 项目需求 我们切换为vue框架是后面的事情,之前还有一些功能页面是用jsp页面写的,而我们的管理系统需要既支持Vue的url,又要支持这些发布之后的jsp页面 还有一个就是切换tab回来的时候之前输入的东西还要存在 系统页面截图 2. 实现思路 针对这个问题,我们最开始的实现思路是写了一个iframe的通用组件,然后把不同的http的页面的url传递进来进行切换,但是这样不满足第二条,我们发现只要切换了vue的路由,然后再切回http的页面,iframe中的src属性的页面就会从新刷新,没

  • Vue 使用iframe引用html页面实现vue和html页面方法的调用操作

    当我们需要在vue中使用其他模块或者其他地方的一些html页面功能时,我们可以使用iframe去引用html页面,实现他们的交互 首先我们可以再vue页面中使用标签引用html页面 <template> <div> <iframe name="iframeMap" id="iframeMapViewComponent" width="100%" height="470px" v-bind:src=

  • vue使用facebook twitter分享示例

    记录一次vue使用分享 固定内容的分享 参考文档 facebook 分享文档 twitter 分享文档 vue 使用 facebook 使用分享 找到index.html 添加一下代码 <!-- facebook 分享 --> <div id="fb-root"></div> <script>(function (d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.g

  • 在vue中实现嵌套页面(iframe)

    vue中嵌套iframe,将要嵌套的文件放在static下面.src可以使用相对路径,也可使用服务器根路径http:localhost:8088/- <iframe src="../../static/plusPro.html" width="1200" height="300" frameborder="0" scrolling="auto"style="position:absolute

  • vue中解决拖拽改变存在iframe的div大小时卡顿问题

    写在最前 针对于在vue中实现拖拽改变两左右个div大小的方式,请查看上一篇文章<vue中实现拖动调整左右两侧div的宽度>.此文章主要针对于实际应用中需要拖拽改变大小的组件中使用iframe框架时存在明显卡顿的问题,比如这样,右侧div中使用了一个iframe组件,导致实际操作中出现两个问题,一个是拖不动,另外一个是无法根据鼠标移动,快速响应,甚至在监听鼠标的按下和松开事件上都有明显的卡顿问题.如果去除右侧iframe框架,则没有问题. 有iframe情况 无iframe情况 问题原因&am

  • vue组件中使用iframe元素的示例代码

    本文介绍了vue组件中使用iframe元素的示例代码,分享给大家,具体如下: 需要在本页面中展示vue组件中的超链接,地址栏不改变的方法: <template> <div class="accept-container"> <div class="go-back" v-show="goBackState" @click="goBack">GoBack</div> <ul&g

  • 开发一个封装iframe的vue组件

    VUE的基本组成单元,我看应该是组件.用VUE开发前端项目,就是开发一个个组件,然后搭积木一样,将项目搭建出来.组件包含在页面,或者是更大的组件里面.在这里,组件与页面的界限,好像并不明显.事实上,对于单页应用,只有一个页面. 组件的好处,一是可以加强复用:二是能够将特定功能封装,利于调用:三是由于职责分明,组件高内聚,组件间低耦合,利于系统功能的优化.扩展和维护.好处多多. 开发组件,主要有2部分内容: 1.组件内部逻辑 2.外部接口 由于我这两天弄的组件,里面包含有一个<iframe>,那

  • VUE开发一个图片轮播的组件示例代码

    本人刚学习vue,用vue做了个图片轮播,下面我来记录一下,有需要了解VUE开发一个图片轮播的组件的朋友可参考.希望此文章对各位有所帮助. 完成效果图如下: vue开发的思路主要是数据绑定,代码如下: <template> <div ref="root" style="user-select: none;-webkit-user-select: none;overflow: hidden"> <div class="slide

  • Vue开发之封装上传文件组件与用法示例

    本文实例讲述了Vue开发之封装上传文件组件与用法.分享给大家供大家参考,具体如下: 使用elementui的 el-upload插件实现图片上传组件 每个项目存在一定的特殊性,所以数据的处理会不同 pictureupload.vue: <template> <div class="pictureupload"> <el-upload :action="baseUrl + '/api/public/image'" list-type=&q

  • Vue组件开发技巧总结

    前言 临近毕业,写了个简单个人博客,项目地址是点我访问项目地址(顺便求star),本篇是系列总结第一篇.接下来会一步一步模仿一个低配版的Element 的对话框和弹框组件. 正文 Vue 单文件组件开发 当使用vue-cli初始化一个项目的时候,会发现src/components文件夹下有一个HelloWorld.vue文件,这便是单文件组件的基本开发模式. // 注册 Vue.component('my-component', { template: '<div>A custom compo

  • webpack如何打包一个按需引入的vue组件库

    目录 前言 在项目中使用vue组件库的一般姿势 webpack实现可按需引入的组件库 接下来就是使用webpack打包 调试组件库 npm 发布 步骤非常简单,只需4步 调试组件库按需引入 总结 前言 在公司里一般有多个相同技术栈的项目,毕竟在多个项目间copy公共组件代码太繁琐,也不利于组件库的维护,所以怎么高效维护一套公共的组件代码很重要.这种情况,一般我们可以考虑封装成组件库,发布到npm上.在每个项目里只需要npm install xxx 即可使用,避免了在项目间相互copy.我们这就开

  • vue组件和iframe页面的相互传参问题及解决

    目录 vue组件和iframe页面相互传参 vue组件调用iframe页面方法和参数 iframe页面向vue组件传参 内嵌iframe页面并进行传值 vue组件和iframe页面相互传参 目前网上大多关于iframe父子传参的博客都是在叙述父页面是html文件,子iframe文件也是html文件,涉及到父页面是vue组件子iframe页面是html的博客多数讲的不是很明白: 而最近我在项目中碰到了这种需求:在vue组件中嵌入iframe页面,并实现父子传参: vue组件调用iframe页面方法

  • Vue组件中的data必须是一个function的原因浅析

    组件可以有自己的data,并且data必须是一个function. 在下面这个例子中,data 返回了一个在外部定义的对象.并且这个组件在页面中使用了3次,点击+1时出现了如下情况:data中的count属性影响到了所有实例. <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="

  • Vue组件大全包括(UI组件,开发框架,服务端,辅助工具,应用实例,Demo示例)

    Vue是一款比较流行的JS库,本文为大家介绍一些Vue组件,包括UI组件,开发框架,服务端,辅助工具,应用实例,Demo示例等开源项目 一.Vue常用UI组件 element ★11612 - 饿了么出品的Vue2的web UI工具套件 Vux ★7503 - 基于Vue和WeUI的组件库 iview ★5801 - 基于 Vuejs 的开源 UI 组件库 mint-ui ★5517 - Vue 2的移动UI元素 vue-material ★2790 - 通过Vue Material和Vue 2

  • Vue组件实现卡片动画倒计时示例详解

    目录 前言 需求拆解 组件设计思路 具体开发 animate-clock.vue animate-card 项目中使用 后记 前言 最近有朋友在做投票的项目,里面有用到一个倒计时的组件,还想要个动画效果.cv大法浸染多年的我,首先想到的是直接找个现有的组件. 通过一通搜索,看上的只有一个 vue2-flip-countdown,但是当我要修改大小和颜色的时候发现改不了,从而直接把源码拉到项目里面,改起来也挺麻烦. 而且,在搜索大法运行几个周天以后,其实心理已经有了一个倒计时开发整体思路,便决定自

  • vue组件的写法汇总

    数据驱动和组件化是vue.js两个最重要的特点.组件化是为了方便代码复用,提高开发效率.常见的vue组件写法有四种,各有特色,适用于不同的场景. 1.全局组件 结构: // 组件的注册 Vue.component( 'componentName', { template: // 组件的html结构, data(){ return{ // 组件中的属性 } }, method: { // 组件中的方法 } ...... // 组件其他的属性和方法 }) // 组件的使用 new Vue({ el:

随机推荐