编写一个Tampermonkey脚本,将内联表单插入到不能直接编辑的网页中。表单与单独的后端进行通信。
使用jQuery构建原型,但希望将React投入使用以支持更好的UX。为了与其他工作保持一致,我也想使用webpack和jsx。
一次执行一件事,脚本很简单:
import React from 'react';
import ReactDOM from 'react-dom';
GM_addStyle(require(__dirname + '/styles/app.css'));
console.log("webpacked script is working!");
const Hello = () => <div>hello</div>
const graph = document.querySelector('a[href*="url_here"]');
console.log(graph);
ReactDOM.render(<Hello />, graph)
我尝试使用byTagName的querySelectorAll,以防万一两者有所不同。
但是,在多次调用之后,生成的脚本失败并显示“最大更新深度成功”:
“网络打包脚本正在运行!”会打印到控制台,并且将目标元素从dom中删除,但是<Hello />
div不会在其位置呈现。
该打包,转译但未压缩但以fakeNode
开头的违规行在这里:
if ("undefined" != typeof window && "function" == typeof window.dispatchEvent && "undefined" != typeof document && "function" == typeof document.createEvent) {
var fakeNode = document.createElement("react");
invokeGuardedCallbackImpl = function(name, func, context, a, b, c, d, e, f) {
"undefined" == typeof document && invariant(!1, "The `document` global was defined when React was initialized, but is not defined anymore. This can happen in a test environment if a component schedules an update from an asynchronous callback, but the test has already finished running. To solve this, you can either unmount the component at the end of your test (and ensure that any asynchronous operations get canceled in `componentWillUnmount`), or you can change the test itself to be asynchronous.");
var evt = document.createEvent("Event"), didError = !0, windowEvent = window.event, windowEventDescriptor = Object.getOwnPropertyDescriptor(window, "event"), funcArgs = Array.prototype.slice.call(arguments, 3);
var error = void 0, didSetError = !1, isCrossOriginError = !1;
function handleWindowError(event) {
if (error = event.error, didSetError = !0, null === error && 0 === event.colno && 0 === event.lineno && (isCrossOriginError = !0),
event.defaultPrevented && null != error && "object" == typeof error) try {
error._suppressLogging = !0;
} catch (inner) {}
}
var evtType = "react-" + (name || "invokeguardedcallback");
window.addEventListener("error", handleWindowError), fakeNode.addEventListener(evtType, function callCallback() {
fakeNode.removeEventListener(evtType, callCallback, !1), void 0 !== window.event && window.hasOwnProperty("event") && (window.event = windowEvent),
func.apply(context, funcArgs), didError = !1;
}, !1), evt.initEvent(evtType, !1, !1), fakeNode.dispatchEvent(evt), windowEventDescriptor && Object.defineProperty(window, "event", windowEventDescriptor),
didError && (didSetError ? isCrossOriginError && (error = new Error("A cross-origin error was thrown. React doesn't have access to the actual error object in development. See ... for more information.")) : error = new Error("An error was thrown inside one of your components, but React doesn't know what it was. This is likely due to browser flakiness. React does its best to preserve the \"Pause on exceptions\" behavior of the DevTools, which requires some DEV-mode only tricks. It's possible that these don't work in your browser. Try triggering the error in production mode, or switching to a modern browser. If you suspect that this is actually an issue with React, please file an issue."),
this.onError(error)), window.removeEventListener("error", handleWindowError);
};
}
在我看来,ReactDOM无法访问其期望的窗口对象,可能是Tampermonkey代理的某个地方。
是这种情况,还是另外一个问题?
有没有办法让我在此Tampermonkey脚本中正确渲染ReactDOM?
答案 0 :(得分:1)
快速解决方案:tampermonkey脚本顶部的window = unsafeWindow
,可以轻松添加到webpack的BannerPlugin.
其他选项/背景:Why is window (and unsafeWindow) not the same from a userscript as from a <script> tag?