替换document.write()实现表单嵌入:解决异步脚本写入报错
问题描述
嵌入表单时出现报错:
Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.
原嵌入代码:
<script src=https://courses.nooor.me/forms/2148061262/embed.js></script>
原脚本内容:
(function() { // write the form document.write("<link href='//fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>\n<link rel=\"stylesheet\" media=\"all\" href=\"https://kajabi-app-assets.kajabi-cdn.com/assets/form_embed-70ab594381937fc46cadbbaab29c12b724dc077086662f2bbd495c08e46bb08d.css\" />\n<script src=\"https://kajabi-app-assets.kajabi-cdn.com/assets/form_embed-fd7a5360fe56f0a332f934492d89f18c2202d65871804504adca6fd4b6e78ceb.js\"><\/script>\n\n<div id=\"kajabi-form\" class=\"kajabi-form--inline\">\n <form data-parsley-validate=\"true\" data-kjb-disable-on-submit=\"true\" action=\"https://courses.nooor.me/forms/2148061262/form_submissions\" accept-charset=\"UTF-8\" method=\"post\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" /><input type=\"hidden\" name=\"authenticity_token\" value=\"jCZsvmdl6JVqAAh+p7QdKNDiBgrYxMUJIjX/El9vUKHhUVU+BeaAYYhRCHp5rLDDGS1//6FYFmbbbbQSfeQ+9g==\" />\n <style id=\"form-embed-style\" type=\"text/css\">\n\n <\/style>\n\n\n<div class=\"kajabi-form__content\">\n <div class=\"kajabi-form__title\">JOIN THE NEWSLETTER<\/div>\n <div class=\"kajabi-form__subtitle\">\n <p style=\"text-align: center;\">Subscribe to get our latest content by email.<\/p>\n <\/div>\n <fieldset>\n <div class=\"text-field kajabi-form__form-item\"><input type=\"text\" name=\"form_submission[name]\" id=\"form_submission_name\" value=\"\" required=\"required\" placeholder=\"Name\" /><\/div>\n <div class=\"email-field kajabi-form__form-item\"><input required=\"required\" placeholder=\"Email\" data-parsley-remote=\"true\" data-parsley-remote-validator=\"kjb_email_validator\" type=\"email\" name=\"form_submission[email]\" id=\"form_submission_email\" /><\/div>\n <div class=\"phone-field kajabi-form__form-item\"><input placeholder=\"WhatsApp Number\" type=\"tel\" name=\"form_submission[phone_number]\" id=\"form_submission_phone_number\" /><\/div>\n <button class=\"kajabi-form__btn kajabi-form__btn--block-mobile\" type=\"submit\">Subscribe<\/button>\n <\/fieldset>\n<\/div>\n\n<\/form><\/div>\n"); })();
提问:能否修改该脚本,不使用document.write实现表单正常嵌入网站?
解决方案
完全可以替代document.write,改用DOM操作动态创建和插入元素,规避异步加载脚本的写入限制。修改后的脚本如下:
(function() { // 创建临时容器存放所有要插入的内容 const container = document.createElement('div'); // 将原HTML内容注入容器的innerHTML container.innerHTML = `<link href='//fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'> <link rel="stylesheet" media="all" href="https://kajabi-app-assets.kajabi-cdn.com/assets/form_embed-70ab594381937fc46cadbbaab29c12b724dc077086662f2bbd495c08e46bb08d.css" /> <script src="https://kajabi-app-assets.kajabi-cdn.com/assets/form_embed-fd7a5360fe56f0a332f934492d89f18c2202d65871804504adca6fd4b6e78ceb.js"><\/script> <div id="kajabi-form" class="kajabi-form--inline"> <form data-parsley-validate="true" data-kjb-disable-on-submit="true" action="https://courses.nooor.me/forms/2148061262/form_submissions" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="jCZsvmdl6JVqAAh+p7QdKNDiBgrYxMUJIjX/El9vUKHhUVU+BeaAYYhRCHp5rLDDGS1//6FYFmbbbbQSfeQ+9g==" /> <style id="form-embed-style" type="text/css"> <\/style> <div class="kajabi-form__content"> <div class="kajabi-form__title">JOIN THE NEWSLETTER<\/div> <div class="kajabi-form__subtitle"> <p style="text-align: center;">Subscribe to get our latest content by email.<\/p> <\/div> <fieldset> <div class="text-field kajabi-form__form-item"><input type="text" name="form_submission[name]" id="form_submission_name" value="" required="required" placeholder="Name" /><\/div> <div class="email-field kajabi-form__form-item"><input required="required" placeholder="Email" data-parsley-remote="true" data-parsley-remote-validator="kjb_email_validator" type="email" name="form_submission[email]" id="form_submission_email" /><\/div> <div class="phone-field kajabi-form__form-item"><input placeholder="WhatsApp Number" type="tel" name="form_submission[phone_number]" id="form_submission_phone_number" /><\/div> <button class="kajabi-form__btn kajabi-form__btn--block-mobile" type="submit">Subscribe<\/button> <\/fieldset> <\/div> <\/form><\/div>`; // 将容器内元素插入到当前脚本标签的位置 const scriptTag = document.currentScript; while (container.firstChild) { scriptTag.parentNode.insertBefore(container.firstChild, scriptTag); } })();
修改说明
- 替换
document.write:用innerHTML将HTML内容注入临时div容器,避免直接写入文档流的限制。 - 保持插入位置一致:通过
document.currentScript获取当前执行的脚本标签,将容器内元素插入到脚本标签前方,和原document.write的插入效果一致。 - 自动处理资源加载:动态插入的
<link>和<script>标签会被浏览器正常解析加载,无需额外处理。
使用时,直接将修改后的脚本替换原embed.js内容,或保存为新脚本文件引入即可。
内容的提问来源于stack exchange,提问作者Youssef Tarek
相关产品推荐
相关产品推荐

