You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于chrome-extension-boilerplate-react-vite,如何实现右键菜单触发网页JSX模态框?

基于chrome-extension-boilerplate-react-vite实现上下文菜单触发JSX模态框的修改步骤

1. 更新background.ts,添加消息通知逻辑

修改背景脚本中上下文菜单的点击事件处理,当用户点击菜单时,向当前标签页的内容脚本发送显示模态框的消息:

import reloadOnUpdate from 'virtual:reload-on-update-in-background-script';
import 'webextension-polyfill';

reloadOnUpdate('pages/background');
reloadOnUpdate('pages/content/style.scss');

chrome.runtime.onInstalled.addListener(() => {
  console.log('onInstalled....');

  chrome.contextMenus.create({
    id: 'typelessPopup',
    title: 'Add to typless',
    contexts: ['selection'],
  });
});

chrome.contextMenus.onClicked.addListener((info, tab) => {
  if (tab?.id && info.menuItemId === 'typelessPopup') {
    // 存储选中文本(可选,也可通过消息直接传递)
    chrome.storage.local.set({ selectedText: info.selectionText });
    // 向当前标签页发送消息触发模态框
    chrome.tabs.sendMessage(tab.id, {
      type: 'SHOW_MODAL',
      payload: { selectedText: info.selectionText }
    });
  }
});

console.log('background loaded', chrome);

2. 修改内容脚本(pages/content/index.tsx),监听消息并渲染模态框

内容脚本负责在页面中注入React模态框,需要创建挂载容器并监听来自背景脚本的消息:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './style.scss';
import Modal from '../../components/Modal';

// 创建模态框挂载容器
const createModalContainer = () => {
  const container = document.createElement('div');
  container.id = 'typeless-modal-container';
  document.body.appendChild(container);
  return container;
};

const container = createModalContainer();
const root = ReactDOM.createRoot(container);

// 初始状态不渲染模态框
root.render(null);

// 监听背景脚本的消息
chrome.runtime.onMessage.addListener((message) => {
  if (message.type === 'SHOW_MODAL') {
    root.render(
      <Modal 
        selectedText={message.payload.selectedText} 
        onClose={() => root.render(null)} 
      />
    );
  }
});

3. 创建React模态框组件(components/Modal.tsx)

编写自定义模态框组件,展示选中的文本并提供交互功能:

import React from 'react';

interface ModalProps {
  selectedText: string;
  onClose: () => void;
}

const Modal = ({ selectedText, onClose }: ModalProps) => {
  return (
    <div className="typeless-modal-overlay">
      <div className="typeless-modal">
        <button className="modal-close-btn" onClick={onClose}>×</button>
        <h3>选中的文本</h3>
        <p>{selectedText}</p>
        <button className="modal-submit-btn">添加到Typless</button>
      </div>
    </div>
  );
};

export default Modal;

4. 添加模态框样式(pages/content/style.scss)

为模态框编写基础样式,确保在页面顶部正确显示:

.typeless-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding-top: 50px;
  z-index: 999999;
}

.typeless-modal {
  background: #fff;
  padding: 24px;
  border-radius: 8px;
  width: 420px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.2);
  position: relative;
}

.modal-close-btn {
  position: absolute;
  top: 12px;
  right: 16px;
  border: none;
  background: transparent;
  font-size: 20px;
  cursor: pointer;
  color: #666;
}

.modal-close-btn:hover {
  color: #000;
}

.modal-submit-btn {
  margin-top: 16px;
  padding: 10px 20px;
  background: #2563eb;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.modal-submit-btn:hover {
  background: #1d4ed8;
}

5. 检查Manifest配置(确保内容脚本注入范围正确)

确认项目中自动生成的Manifest配置里,content_scripts的matches字段包含你需要注入的网站,比如<all_urls>表示所有网站:

{
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["pages/content/index.js"],
      "css": ["pages/content/style.css"]
    }
  ]
}

内容的提问来源于stack exchange,提问作者Rooban

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:35:57