面试官:如何在老项目中使用新框架,并实现通信?

写在前面

假设有这样一个场景,你接到一个项目,需要在这个项目上完成一次迭代,但是你发现这个项目已经是 10 年前的老项目了。框架、组件库都非常老。。。。你无从下手,不知所措,如果这时去阅读项目老代码并在这个基础上进行开发,无疑是非常崩溃的,而且效率非常低下。

众所周知,现在的网页开发都是用的最新的框架,例如 Vue、React 开发起来都非常顺手,而且节约时间,这个时候你就在想,有没有可能自己用新框架开发,然后再在老项目上去使用,这样是不是就快很多了,这时你又重燃希望了,又可以开心的写代码了。

但这个时候又有一个新问题,就是如何把自己的新框架嵌入到老框架里面呢,这个简单,只需要把打包的js、css 资源引入到老框架不就行了。

于是你感觉问题就这么简单的解决了,但是你又发现了一个新问题,就是如何让两者可以实现通信, 新框架的资源只是引入进去了,但是两者并没有产生实际的交互之间的关系。

这时你又陷入了沉思,于是经过一番调研你发现了一个好东西,window.postMessage 可以实现这个需求!

上面说了这么多废话其实就是为了更清晰的描述这个需求,那么接下来就进入正题,一起来看看到底该如何利用 postmessage 实现这个需求吧!

什么是 postMessage

window.postMessage()方法提供了一种安全的跨域通信机制。在浏览器的安全策略中,不同源(协议、域名、端口不同)的页面之间通常是限制相互访问的。但是通过window.postMessage(),一个窗口(可以是一个iframe、一个新打开的窗口等)可以向另一个窗口发送消息,只要目标窗口正确地设置了消息接收的事件监听器。

说白了 postMessage 的主要作用是实现不同窗口(包括跨域的iframe、新打开的窗口等)之间安全地发送和接收消息,从而进行跨窗口通信。

基本语法

发送方

js 复制代码
window.postMessage(message, targetOrigin);

接收方

js 复制代码
window.addEventListener('message', function (event) {
    var messageData = JSON.parse(event.data);
    console.log(messageData.key); 
});

演示一下

上面我们已经介绍了怎么使用,接下来我们就实战一下怎么使用。

老框架中

老框架中我们使用 jquery,在 jquery 中使用 react 框架。

我们现在老框架中进行发送通信,然后在新框架中接收通信即可。

下面这块代码很简单,我们给按钮绑定点击事件,点击的时候发送 postmessage 通信。

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>jQuery to React Modal Communication</title>
  </head>
  <body>
    <button id="openModal">Open React Modal</button>
     
     <!-- 挂载新框架 -->
    <div id="root"></div>
     <!-- jquery -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
     <!-- 新框架js资源 -->
    <script src="build/static/js/main.eb6f11e8.js"></script>
     <!-- 新框架css资源 -->
    <link rel="stylesheet" href="build/static/css/main.8da51b4f.css" />

    <script>
      $(document).ready(function () {
        $('#openModal').on('click', function () {
          // 通过 postMessage 触发 React modal 显示
          const data = {
            userId: 123,
            username: 'johndoe',
          }
          window.postMessage({ type: 'openModal', data }, '*')
        })
      })
    </script>
  </body>
</html>

发送通信已经搞定了,但是我们需要在老框架中引入新项目的资源,也打包后的就是 css、js 资源。

js 复制代码
    <script src="build/static/js/main.eb6f11e8.js"></script

    <link rel="stylesheet" href="build/static/css/main.8da51b4f.css" />

因为新框架需要有一个 root 节点挂载元素,我们将 root 节点也一并引入。

js 复制代码
    <div id="root"></div>

新框架

老框架的工作已经做好了,新框架其实就是需要在页面中接受 postmessage 事件即可。

我们在 useEffect 中监听 postmessage 事件,并且在规定 type 为 openModal 时设置相应的数据,非常简单的一段代码,主要还是为了解释 postmessage 的用法。

js 复制代码
import React, { useEffect, useState } from 'react'
import './Modal.css'

const Modal = () => {
  const [data, setData] = useState(null)
  const [isVisible, setIsVisible] = useState(false)

  useEffect(() => {
    const handleMessage = (event) => {
      if (event.data.type === 'openModal') {
        console.log('event', event)
        setData(event.data.data) // 设置数据
        setIsVisible(true)
      }
    }

    window.addEventListener('message', handleMessage)
    return () => window.removeEventListener('message', handleMessage)
  }, [])

  const handleClose = () => {
    setIsVisible(false)
    setData(null)
  }
  return isVisible ? (
    <div className="modal">
      <div className="modal-content">
        <h2>React Modal1111</h2>
        <p>User ID: {data?.userId}</p>
        <p>Username: {data?.username}</p>
        <button onClick={handleClose}>Close Modal</button>
      </div>
    </div>
  ) : null
}

export default Modal

效果

好了准备工作都好了,现在来看一下效果

首先运行老代码,然后点击按钮,我们先要的效果时打开一个弹窗,并且把老项目的数据带过来并且展示在弹窗上面。

自己动手试试

现在还留了一个小的作业,就是点击 close modal 的时候,需要新框架向老框架发送通信,通知老框架,关闭了弹窗,然后弹出一个弹窗,大家感兴趣可以自己试试哈,如下:

相关推荐
拾年2751 小时前
React Hooks 保姆级教程:把组件想象成失忆的打工人,4 个 Hook 带你原地起飞
前端·javascript·react.js
mmsx1 小时前
一个 Bug 修了 12 轮,根因只有一句话:AI 编程时代,日志才是唯一的真相
前端
默_笙1 小时前
😝 5 亿次循环卡死页面?我用 Web Worker 把它扔进后台线程,页面丝滑如初
前端·javascript
CAD老兵1 小时前
一行代码集成 DWG/DXF 图纸查看:测量批注,数据不出站
前端·javascript·github
小林ixn1 小时前
单例模式:从弹窗管理到全局状态,一个模式搞定
前端·javascript·设计模式
AI编程实验室1 小时前
Node.js Agent Handoff 仓库扫描 MVP:忽略规则、include 通配与稳定输出实现
前端·ai编程
猫不易1 小时前
从 Virtual DOM 到 Vapor:Vue 3.6 的另一条路
前端·vue.js
光影少年1 小时前
react navite性能优化 & 常见坑
前端·react native·掘金·金石计划
八角丶1 小时前
Node.js Cluster 详解
前端·node.js