Develop a vue component that encapsulates iframe

Develop a vue component that encapsulates iframe

I think the basic building block of VUE should be a component. To develop a front-end project with VUE is to develop components one by one, and then build the project like building blocks. Components are contained within pages, or within larger components. Here, the boundary between components and pages does not seem to be obvious. In fact, with a single-page application, there is only one page.

The benefits of components are: first, they can enhance reuse; second, they can encapsulate specific functions for easy calling; third, due to clear responsibilities, high component cohesion and low coupling between components, it is conducive to the optimization, expansion and maintenance of system functions. There are many benefits.

Development components mainly include two parts:
1. Component internal logic
2. External interface Since the component I made these two days contains an <iframe>, there is another part of the work content:
3. iframe interface

1. Component Introduction

This is a map plugin. Its function is to display maps, accept external commands, load layers, draw graphics and other related operations. The map is implemented using ArcGIS for JS. Due to the projects we developed in the past, we have some experience in map operations, but there is no separation between the front-end and the back-end, and we do not use VUE or REACT, but only traditional WEB pages. Because of the tight time schedule and the desire to reuse previous work, I considered using <iframe> to host the map page, encapsulating it in a VUE component, and having the component connect to external commands and interact with the map page in the iframe.

2. Component internal structure and logic

1. Code organization structure

2. Map Component

Map.vue

<template>
 <div class="map-container">
 	<!-- Hosting map page -->
  <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' // contains path information let iframeWin = null; // private variables export default {
  props:['size'], //Pure test, useless, corresponding to <Map id="map" ref="map" size="100"></Map>
  data() {
   return {
    src: '', //Map page address isLoaded: false, //Is the map page loaded? iMap: null, //Object exposed by the map page for external access require: null //ArcGIS require function, used to reference custom plug-ins. We have written quite a few custom map plugins in the past}
  },
  created() {
   this.src = config.publicPath + 'map.html'
  },
  mounted() {
  	//Listen for iframe messages window.addEventListener('message', this.handleMessage)
   iframeWin = this.$refs.iframe.contentWindow
  },
  methods: {
   iframeLoad() {
    this.isLoaded = true;
    window.console.log("map is ready")
   },   
   async handleMessage() {//Receive messages from iframe this.require = iframeWin.require;
    this.iMap = iframeWin.iMap;
   },
   loadLayer(nodes,servers){
    this.iMap.layerHandler.load(nodes,servers);
   },
   isReady(){
    return this.isLoaded;
   }
  }
 }
</script>

The structure of the components, such as

export default {
 props:, // attributes in the tag data() { // public variables },
 created() {//When loading?
 },
 mounted() {//When loading is complete},
 methods: {//public methods}
}

Export means this is for external use. Therefore, the properties, variables, and methods inside can be accessed externally. If you want it to be private, you should define it outside of export. As in this example:

Such a simple introduction cannot be found on the Internet. Vue's Chinese site is outdated, with fragmented content, which is extremely unfriendly to beginners and increases the cost of learning.

3. iframe interface

How does the component Map.vue communicate with the iframe inside it?
Through system messages and direct access to the iframe object. There is a prerequisite for directly accessing objects in an iframe, which is that it cannot cross domains.

The map page map.html hosted by the iframe

<!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 = {}; //External reference interface 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 = ...

  /* External interface */
  iMap = {
   map: map,
   legend: legend,
   home: home,
   tipDialog: tipDialog,
   toggle: toggle,
   overviewMap: overviewMap
  };
  iMap.drawHandler = ...
  iMap.layerHandler = ...;
  iMap.centerAt = ...;
  iMap.clear = ...;
  iMap.restoreView = ...;

  //Send loading completion signal to the parent Vue page window.parent.postMessage({
   cmd: 'mapIsReady',
   params: {
    success: true,
    data: true
   }
  }, '*');
  /* end of external interface*/

 });
</script>

The map component Map.vue corresponds to the iframe part, see the code in 1.2 for details

export default {
		. . .
  mounted() {
	  //Listen for iframe messages window.addEventListener('message', this.handleMessage)
   //Get the iframe's window object iframeWin = this.$refs.iframe.contentWindow
  },
  methods: {
   iframeLoad() {
    this.isLoaded = true;
    window.console.log("map is ready")
   },   
   async handleMessage() {//Receive messages from iframe this.require = iframeWin.require;
    this.iMap = iframeWin.iMap;
   },
   loadLayer(nodes,servers){
   	//Load layer this.iMap.layerHandler.load(nodes,servers);
   }
  }
 }

4. External Interface

Map.vue is a component that needs to communicate with the component or page it is in.

Now, Map.vue is placed in a container page Home.vue (i.e. test page), which also contains a command component Layer.vue. Click the button in the command component and the map will respond accordingly. The principle is as follows:

When the command component's button is clicked, information is emitted to the container page, and then the container page calls the map component's method.

Test page Home.vue

<template>
 <div id="app1">
  <div id="map-container">
   <div>Map component</div>
   <Map id="map" ref="map" size="100"></Map>
  </div>
  <div id="layer-container">
   <div>Other components</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){//Load layer let map = this.$refs.map;
    map.loadLayer(nodes,servers);
   },
   loadCloud(data){//Load satellite cloud map 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(){//Clear let map = this.$refs.map;
    map.iMap.clear();
   }
  }
 }
</script>

<style>
. . .
</style>

Command component Layer.vue

<template>
 <div class="layer-container">
  <button @click="loadLayer">Load layer</button>
  <button @click="loadCloud">Satellite Cloud Image</button>
  <button @click="clear">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>

Note that the method specified in the command component's emitted message has corresponding properties in the container page:

Command component loadCloud(){
 let data = ...;
 this.$emit("loadCloud", data);
},

Container page <Layer @loadLayer="loadLayer" @loadCloud="loadCloud" @clear="clearMap"></Layer>

5. Operation Results

VI. Conclusion

Other components need to interact with the map component through the container page. Other components do not interact directly with the map component. This is actually a command mode. The advantage is that other components and map components are decoupled and not coupled together, which means they do not affect each other. This is conducive to the expansion and optimization of the map component itself. As for the disadvantages, each thing must be forwarded through the container page, the container page code may be redundant, and some methods are simply a mouthpiece, giving people the feeling that they are repetitive and meaningless.

The above is the details of developing a vue component that encapsulates iframe. For more information about vue components that encapsulate iframe, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Sample code for using iframe elements in vue components
  • Vue uses iframe to reference html page to implement the calling operation of vue and html page methods
  • Implementing nested pages (iframe) in vue
  • Solve the problem of freezing when dragging and changing the size of the div in the iframe in Vue
  • Implementation of information interaction between Vue and iframe
  • How to keep iframe alive without refreshing in Vue
  • Vue sample code using iframe to embed a web page
  • Example of how to integrate Iframe page in Vue

<<:  How to quickly log in to MySQL database without password under Shell

>>:  Linux CentOS6.5 yum install mysql5.6

Recommend

Advantages and disadvantages of common MySQL storage engines

Table of contents View all storage engines InnoDB...

Pay attention to the use of HTML tags in web page creation

HTML has attempted to move away from presentation...

MySql Group By implements grouping of multiple fields

In daily development tasks, we often use MYSQL...

mysql 5.7.18 winx64 free installation configuration method

1. Download 2. Decompression 3. Add the path envi...

How to split and merge multiple values ​​in a single field in MySQL

Multiple values ​​combined display Now we have th...

MySQL knowledge points for the second-level computer exam mysql alter command

Usage of alter command in mysql to edit table str...

Solve the problem that await does not work in forEach

1. Introduction A few days ago, I encountered a p...

js uses the reduce method to make your code more elegant

Preface In actual projects, the most common proce...

Implementation of Nginx configuration https

Table of contents 1: Prepare https certificate 2:...

HTML table tag tutorial (26): cell tag

The attributes of the <TD> tag are used to ...

15 Best Practices for HTML Beginners

Here are 30 best practices for HTML beginners. 1....

Vant Uploader implements the component of uploading one or more pictures

This article shares the Vant Uploader component f...

Two ways to specify the character set of the html page

1. Two ways to specify the character set of the h...