如何为自制在线Web编辑器启用文件与图片链接功能?
解决在线Web编辑器无法加载外部CSS/图片的问题
我跟着YouTube教程做了个在线Web编辑器,改了CSS加了个性化设置,运行正常,但链接同目录的外部CSS和图片时,标签失效,加载不了外部文件,试了CodeMirror也没解决,代码如下:
// Creating Dragging functionality const left=document.querySelector(".left"), right=document.querySelector(".right"), bar=document.querySelector(".bar"), editor=document.querySelector(".editor"), run=document.querySelector(".btn-run"), iframe=document.querySelector(".iframe"), darkMode=document.querySelector(".btn-dark"), lightMode=document.querySelector(".btn-light"); const drag=(e)=>{ e.preventDefault(); document.selection ? document.selection.empty() : window.getSelection().removeAllRanges(); left.style.width=(e.pageX-bar.offsetWidth/3)+"px"; editor.resize(); } bar.addEventListener("mousedown", ()=>{ document.addEventListener("mousemove", drag); }) bar.addEventListener("mouseup", ()=>{ document.removeEventListener("mousemove", drag); }) // Run Btn event listner run.addEventListener("click", ()=>{ const html=editor.textContent; iframe.src="data:text/html;charset=utf-8," + encodeURI(html); }) // setting dark mode darkMode.addEventListener("click", ()=>{ editor.style.backgroundColor="#282A35" editor.style.color="white" }) // setting light mode lightMode.addEventListener("click", ()=>{ editor.style.backgroundColor="white" editor.style.color="black" }) // live code document.getElementById("live").onclick=function(){ if (this.checked){ editor.addEventListener("keyup", ()=>{ const html=editor.textContent; iframe.src="data:text/html;charset=utf-8," + encodeURI(html); }) } }
问题原因
你的核心问题出在iframe的加载方式上:用data:text/html;charset=utf-8,...这种Data URI格式加载HTML时,内容的基准URL是空的。浏览器解析相对路径(比如./style.css)时,没有对应的根目录作为参考,自然找不到同目录下的外部文件。
解决方案
推荐第二种更灵活的方案,适配多数场景:
方案一:将外部资源转为Data URI嵌入(适合小资源)
把CSS文件内容、图片转成Base64编码的Data URI,直接写入HTML,比如:
<style>/* 把style.css的内容直接复制到这里 */</style> <!-- 图片转Data URI示例 --> <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAAAAAAAD..." alt="">
这种方式无需依赖外部文件,但资源较大时会让HTML内容臃肿。
方案二:设置iframe的srcdoc并注入base标签(推荐)
通过srcdoc属性加载HTML内容,同时在HTML开头添加<base href="当前页面根URL">,让浏览器以当前页面所在目录为基准解析相对路径。修改后的代码如下:
// Creating Dragging functionality const left=document.querySelector(".left"), right=document.querySelector(".right"), bar=document.querySelector(".bar"), editor=document.querySelector(".editor"), run=document.querySelector(".btn-run"), iframe=document.querySelector(".iframe"), darkMode=document.querySelector(".btn-dark"), lightMode=document.querySelector(".btn-light"); const drag=(e)=>{ e.preventDefault(); document.selection ? document.selection.empty() : window.getSelection().removeAllRanges(); left.style.width=(e.pageX-bar.offsetWidth/3)+"px"; editor.resize(); } bar.addEventListener("mousedown", ()=>{ document.addEventListener("mousemove", drag); }) bar.addEventListener("mouseup", ()=>{ document.removeEventListener("mousemove", drag); }) // Run Btn event listener run.addEventListener("click", ()=>{ const html = editor.textContent; // 获取当前页面的根目录URL,作为相对路径基准 const baseUrl = window.location.href.replace(window.location.pathname, '/'); // 注入base标签到HTML开头 const htmlWithBase = `<base href="${baseUrl}">${html}`; iframe.srcdoc = htmlWithBase; }) // setting dark mode darkMode.addEventListener("click", ()=>{ editor.style.backgroundColor="#282A35" editor.style.color="white" }) // setting light mode lightMode.addEventListener("click", ()=>{ editor.style.backgroundColor="white" editor.style.color="black" }) // live code let liveKeyupListener; document.getElementById("live").onclick=function(){ if (this.checked){ liveKeyupListener = ()=>{ const html = editor.textContent; const baseUrl = window.location.href.replace(window.location.pathname, '/'); const htmlWithBase = `<base href="${baseUrl}">${html}`; iframe.srcdoc = htmlWithBase; }; editor.addEventListener("keyup", liveKeyupListener); } else { // 取消勾选时移除监听,避免重复绑定 editor.removeEventListener("keyup", liveKeyupListener); } }
补充说明
window.location.href.replace(window.location.pathname, '/')会获取当前页面的根目录URL(比如编辑器页面是http://localhost:8000/editor.html,会得到http://localhost:8000/),确保相对路径以该目录为基准,同目录下的文件能正常加载。- live模式新增了移除监听的逻辑,避免多次勾选后绑定多个事件导致性能问题。
内容的提问来源于stack exchange,提问作者Shaurya Yadav
相关产品推荐
相关产品推荐

