Chrome扩展使用content script插入DOM元素开发Twitter插件问题咨询
问题解决步骤
1. 现有代码的已知错误修正
- MutationObserver调用逻辑完全颠倒:构造函数需要传入回调函数,
observe方法第一个参数是要监听的原生DOM节点,第二个是配置项;同时jQuery选择器返回的是jQuery对象,需要转成原生DOM节点才能传入Observer - Manifest V3的
content_scripts配置不支持html字段,你写的"html": ["save-dropdown.html"]无效,需要在content.js中动态加载/插入自定义HTML - Twitter的类名是动态生成的哈希类,依赖长串类选择器极容易失效,优先使用
data-testid属性选择器定位元素,稳定性更高
2. 完整实现方案
第一步:修正Manifest.json配置
{ "manifest_version": 3, "name": "Twitter Saver", "version": "0.0.1", "description": "Twitter Saver| Save tweets.", "permissions": ["tabs"], "host_permissions": ["https://*.twitter.com/*"], "icons": { "128": "img/icon-app-128.png", "256": "img/icon-app-128@2x.png" }, "content_scripts": [ { "js": ["js/jquery-3.6.0.min.js", "js/content.js"], "matches": ["https://*.twitter.com/*"] } ], "web_accessible_resources": [ { "resources": ["save-dropdown.html"], "matches": ["https://*.twitter.com/*"] } ] }
注:MV3中站点权限需要放在host_permissions字段,自定义HTML要加入web_accessible_resources才能在页面中加载。
第二步:编写正确的content.js逻辑
// 防抖函数,避免DOM频繁变化触发多次插入逻辑 function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // 插入自定义按钮的核心逻辑 function insertSaveBtn() { // 用data-testid定位所有推文操作栏,比类选择器稳定 const tweetActionBars = $('[data-testid="tweet"] [role="group"]:last'); tweetActionBars.each(function() { // 先判断是否已经插入过按钮,避免重复 if ($(this).find('.twitter-saver-btn').length > 0) return; // 插入自定义按钮 $("<div>",{ class: "css-1dbjc4n r-18u37iz r-1h0z5md twitter-saver-btn", text: "HELLO WORLD" }).appendTo(this); }); } // 页面加载完成先执行一次插入 $(document).ready(insertSaveBtn); // 初始化MutationObserver监听DOM变化 const observer = new MutationObserver(debounce(insertSaveBtn, 300)); // 监听react-root节点下的所有子节点变化,包括深层子节点 observer.observe($('#react-root')[0], { childList: true, subtree: true });
3. 关键逻辑说明
- 给自定义按钮增加专属类名
twitter-saver-btn,插入前做判断可以彻底避免滚动加载时重复插入按钮的问题 - 用
subtree: true配置监听react-root下所有层级的DOM变化,覆盖滚动加载、页面切换的所有场景 - 加300ms防抖可以大幅降低DOM频繁变化带来的性能消耗,不影响使用体验
内容的提问来源于stack exchange,提问作者Arfath Yahiya
相关产品推荐
相关产品推荐

