我们继续来看一下如何开发一个简单的html在线编辑器,要求很简单 能够同时编辑html,css,js代码,并且运行之后可以同时预览效果


一:前置知识

        在H5中设置了一个新的标签,<iframe>, 用于在当前 HTML 文档中嵌入另一个独立的 HTML 文档。这是实现在线编辑器预览功能的关键,因为它提供了一个沙箱环境,内部的 HTML、CSS、JS 不会直接影响到父页面。所以我们来简单学习一下该标签元素的使用。

(1)核心属性和方法 (用于向 iframe 写入内容):

  iframe 比较特殊,因为它内部有自己独立的 window 对象和 document 对象。你需要先访问到它们:

  • previewFrame.contentWindow: 返回 iframe 的 window 对象。
  • previewFrame.contentDocument: 返回 iframe 的 document 对象。
    • 注意:在某些旧浏览器或特定情况下,contentDocument 可能不可用,更通用的方式是 previewFrame.contentWindow.document

假设我们先获取了一个iframe元素

const previewFriame =document.getElementByID("preview-frame")
方法一 :使用document.write()

这是讲HTML字符串斜土iframe内部文档的传统写法

    const htmlCode = "<h1>Hello from iframe</h1><p>This is a test.</p>";const iframeDoc = previewFrame.contentWindow.document;iframeDoc.open();     // 1. 打开文档流,准备写入iframeDoc.write(htmlCode); // 2. 将 HTML 字符串写入iframeDoc.close();    // 3. 关闭文档流,浏览器会解析并显示内容

通过沙箱的contentWindow获取沙箱的内部环境再通过document写入内容

 · open(): 清除 `iframe` 中当前的所有内容,并打开一个新的文档流准备接收数据。

 · write(): 将字符串写入到打开的文档流中。你可以多次调用 `write()` 来追加内容。

 · close(): 关闭文档流。这个步骤很重要,它告诉浏览器所有内容都已写入完毕,可以开始解析和渲染了。如果不调用 `close()`,`iframe` 可能会一直处于加载状态。

方法二:使用`srcdoc` 属性 (更现代,推荐)

`srcdoc` 属性允许你直接将完整的 HTML 内容作为字符串赋值给它。浏览器会将其作为 `iframe` 的源文档内容进行渲染。

  const htmlCode = "<h1>Hello via srcdoc</h1><p>Modern way!</p>";previewFrame.srcdoc = htmlCode;

使用这种方法也有一些优点:

 1.更安全:比 `document.write` 在某些情况下更安全,可以减少 XSS 风险(虽然在这个项目中你主要写入自己控制的代码,风险较低)。

2.更简洁:一行代码搞定。

3.行为更像加载一个真正的文档

方法三: 操作 `iframe` 内部 DOM (如果只需要修改部分内容,而不是整个文档)

如果你不是要替换整个 `iframe` 的内容,而是想修改它内部已有的某个元素,可以这样做:

// 假设 iframe 内部已经有一个 id 为 "title" 的 h1 元素const iframeDocument = previewFrame.contentWindow.document;const titleElementInIframe = iframeDocument.getElementById('title');if (titleElementInIframe) {titleElementInIframe.textContent = 'New Title in Iframe';}

对于在线编辑器,通常我们是替换整个预览内容,所以 `document.write()` 或 `srcdoc` 更常用。

其他属性:

1.src属性 指定iframe要加载的外部页面的url。如果你要加载一个已有的网页,会用这个。对于我们的编辑器 我们是动态生成内容 所以scrdoc或者document.write()

2.`width`, `height`: 设置 `iframe` 的宽高。

3. `sandbox`: (高级) 用于对 `iframe` 内容施加额外的限制,增强安全性。例如,阻止脚本执行、阻止表单提交等。


二 :开发过程

我们总结一下开发任务:

1.  获取 `textarea` 的引用

2.  获取 `iframe` 的引用

3.  给 `textarea` 添加 `input` 事件监听器。

4.  在事件处理函数中:

       获取 `textarea` 的 `.value` (用户输入的 HTML 代码)。

       使用 `iframe.contentWindow.document.open()`, `.write()`, `.close()` **或者** `iframe.srcdoc` 将这段 HTML 代码设置到 `iframe` 中,让它显示出来。

先从这两个元素最核心的用法开始,等把 HTML 预览功能实现了,我们再考虑 CSS 和 JavaScript 的集成,那会涉及到更多 `iframe` 内部的操作。

(1)前端页面:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Html在线编译器</title><link rel="stylesheet" href="./css/index.css"><link rel="stylesheet" href="./css/base.css">
</head>
<body class="body1"><div class="left"><div class="html"><button class="run-html">运行</button><div class="title">html编辑器</div><textarea name="html" id="1" class="htmlInput"></textarea></div><div class="css"><div class="title">css编辑器</div><textarea name="css" id="2" class="cssInput"></textarea></div><div class="js"><div class="title">js编辑器</div><textarea name="js" id="3" class="jsInput"></textarea></div></div><div class="right"><div class="show"><div class="title">在线预览</div><!-- iframe标签用于嵌入一个小的html文档窗口 --><!-- iframe里面的内容和外部的相互独立的 互不影响 --><iframe src="about:blank" frameborder="0">1</iframe><!-- frameborder :这个属性用来指定是否显示 <iframe> 的边框。 0 表示没有边框, 1 表示显示边框 --></div></div><script src="./js/index.js"></script>
</body>
</html>

(2)css

*{margin: 0;padding: 0;box-sizing: border-box;font-family: Arial, Helvetica, sans-serif;
}
html, body {height: 100%;
}body{background-color: #454545;display: flex;
}
/* 左 */
.left{width: 50vw;height: 100%;/* background-color: pink; */padding: 5vh;
}
.left .html{width: 100%;height: 30vh;border-radius: 5px;background-color: #fff;margin-bottom: 1vh;display: flex;flex-direction: column;position: relative;
}
.run-html{transform: translate(-110%, -110%);top: 100%;left: 100%;position: absolute;width: 10vh;border-radius: 2vh;background-color: #95e330;
}
.run-html:hover{background-color: #88d228;
}
.run-html:active{background-color: #78c220;
}
.left .css{width: 100%;height: 30vh;border-radius: 5px;background-color: #fff;margin-bottom: 1vh;display: flex;flex-direction: column;}
.left .js{width: 100%;height: 30vh;border-radius: 5px;background-color: #fff;margin-bottom: 1vh;display: flex;flex-direction: column;}
.left .title{width: 100%;text-align: center;border: 0.5px solid #ccc;
}
.left textarea{padding: 2px;width: 100%;height: 100%;border: 0;box-sizing: border-box;flex-grow: 1;background-color: #ccc;
}.left textarea:focus {/* 点击输入框不会出现黑边 */outline: none;
}
/* 右 */
.right{width: 50vw;height: 100%;/* background-color: skyblue; */padding: 5vh;
}.right .show{width: 100%;height: 92vh;background-color: #fff;
}.right .title{width: 100%;text-align: center;border: 0.5px solid #ccc;
}.right iframe{width: 100%;height: 100%;
}

(3)js

const html=document.querySelector('.htmlInput');
const css=document.querySelector('.cssInput');
const js=document.querySelector('.jsInput');const btnhtml=document.querySelector('.run-html');
const output=document.querySelector('.show iframe');
function run(){output.contentDocument.body.innerHTML = html.value + '<style>' + css.value + '</style>';const script = output.contentDocument.createElement('script');script.textContent = js.value;output.contentDocument.body.appendChild(script);
}
btnhtml.addEventListener('click',run);

就这样吧 实现这个功能如果利用这个iframe标签的话就非常简单了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87283.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87283.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/87283.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Bluedroid】蓝牙启动之核心模块(startProfiles )初始化与功能源码解析

本文深入解析Android蓝牙协议栈中 start_profiles 函数及其调用的核心模块初始化逻辑,涵盖 BNEP、PAN、A2DP、AVRC、HID Host、BTA_AR 等关键配置文件和应用层模块。通过代码分析与流程梳理,阐述各模块如何通过全局控制块、状态机、回调机制实现功能初始化、连接管理及数据交…

RK3576 Android14 DMIC调制

一、背景 近期项目中有个DMIC调试的需求&#xff0c;搁置了较长时间&#xff0c;现今着手调试&#xff0c;遂作记录。 二、开发环境 OS&#xff1a;Android14 Platform&#xff1a;RK3576 Linux Version&#xff1a;6.1.99 SDK Version&#xff1a;android-14.0-mid-rkr6 …

使用 Prometheus 监控 Spring Boot 应用

SpringBoot+Prometheus+Grafana实现监控 逻辑如图 应用程序在生产环境中运行时,监控其运行状况是非常必要的。通过实时了解应用程序的运行状况,才能在问题出现之前得到警告,也可以通监控应用系统的运行状况,优化性能,提高运行效率。 一、监控 Spring Boot 应用 下面我们…

简易计算器 Python 实现

目录 一、代码逐步分析&#xff08;适合刚入门的朋友看&#xff09; 1.定义了一个名为simple_calculator的函数&#xff0c;封装了整个计算器的逻辑。 二、深入分析代码块&#xff0c;用更加官方的语词来说&#xff08;适合想要深入学习的朋友&#xff09; 主循环结构 退出…

开源编译器介绍

文章目录 基本构成传统编译器编译器的发展历史&#xff08;History of Compiler&#xff09;GCC 编译过程与原理&#xff08;GCC Process and Principle&#xff09;LLVM/Clang 编译过程与原理&#xff08;LLVM/Clang Process and Principle&#xff09;GCC与与 LLVM/Clang 的对…

C++ String知识点

当然可以&#xff01;下面我将以系统全面、通俗易懂、深入浅出的方式&#xff0c;为你讲解 C 中非常核心但也容易被低估的内容 —— std::string。 &#x1f31f; C std::string 全面详解 &#x1f4cc; 一、string 是什么&#xff1f; C 的 std::string 是 C 标准库中封装好…

全新NVIDIA Llama Nemotron Nano视觉语言模型在OCR基准测试中准确率夺冠

全新NVIDIA Llama Nemotron Nano视觉语言模型在OCR基准测试中准确率夺冠 PDF、图表、图形和仪表板等文档是丰富的数据源&#xff0c;当这些数据被提取和整理后&#xff0c;能够为决策制定提供有价值的洞察。从自动化财务报表处理到改进商业智能工作流程&#xff0c;智能文档处…

gradle的 build时kaptDebugKotlin 处理数据库模块

gradle的 build时输出&#xff1a; Task :app:kaptDebugKotlin 注: Processing class HDCoinBean 注: Processing class HDCurrencyBean 注: Processing class HDSelfAddCoin 注: Processing class MN 注: Creating DefaultRealmModule <—> 80% EXECUTING [7m 56s] IDLE…

二叉树的节点操作算法

235. 二叉搜索树的最近公共祖先 力扣题目链接(opens new window) 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大…

【ubuntu驱动安装】安装nvidia驱动和cuda环境

1、安装驱动 首先查看环境和显卡&#xff1a; 更新apt 查看nouveau是否禁用 如果有返回值禁用nouveau(nouveau是通用的驱动程序)&#xff08;必须&#xff09;&#xff0c;两种文件&#xff0c;22.04是下面那个 添加如下&#xff1a; 终端输入后更新 重启电脑sudo reboo…

力扣HOT100之终章:一些随笔

今天终于把力扣HOT100系列给刷完了&#xff0c;每一道题都记录了自己的思考过程和解题过程中参考的一些题解和视频&#xff0c;方便自己以后再刷的时候快速复习&#xff0c;从2025年3月4日写下第一篇博客&#xff0c;到2025年6月12日完成最后一题并写下最后一篇博客&#xff0c…

榕壹云家政系统:基于Spring Boot与UniApp的智能家政服务解决方案

在数字化浪潮下&#xff0c;传统家政行业正面临效率与服务质量的升级挑战。榕壹云公司依托前沿技术&#xff0c;推出了一款用户端与师傅端二合一的家政服务小程序&#xff0c;通过整合预约上门、分销、储值、优惠券等功能&#xff0c;为家政服务行业提供了一套高效、灵活的数字…

CSRF扩展 JSONP劫持

介绍&#xff1a;JOSNP&#xff08;JSONP with Override Security Negotiation Protocol&#xff09;劫持是一种利用JSONP &#xff08;JSON with Padding&#xff09;跨域数据获取机制的安全漏洞&#xff0c;攻击者通过篡改或伪造JSONP回调函数窃 取用户敏感数据。由于JSONP…

HTTP/HTTPS 协议解析

前言 在当今互联网时代&#xff0c;HTTP/HTTPS 协议作为 Web 通信的基石&#xff0c;承载着几乎所有的网络内容传输。对于我们而言&#xff0c;深入理解这些协议不仅是技术素养的体现&#xff0c;更是构建高性能、安全、可靠 Web 应用的必要条件。 为什么我们需要深入了解 HT…

Flask-login 处理授权逻辑

认证 vs 授权&#xff1a; 在 Web 应用程序的安全机制中&#xff0c;认证&#xff08;Authentication&#xff09; 和 授权&#xff08;Authorization&#xff09; 是两个核心概念&#xff0c;它们虽然紧密相关&#xff0c;但职责和作用不同。 认证&#xff08;Authenticatio…

xenomai3+linux构建linux实时操作系统-基于X86_64和arm

简介&#xff1a; Xenomai是一个实时性解决方案&#xff0c;通过在Linux上添加实时内核Cobalt来增强实时性能。它有三个主要部分&#xff1a;libcobalt&#xff08;用户空间实时库&#xff09;、Cobalt&#xff08;内核空间实时内核&#xff09;和硬件架构特定层&#xff08;ip…

Linux核心文件(core file)详解

一、核心文件&#xff08;core file&#xff09;概述 1.1 什么是核心文件 核心文件&#xff08;core file&#xff09;是Linux操作系统在程序崩溃时生成的一种转储文件。它包含了程序崩溃时的内存内容、寄存器状态和执行状态。通过分析核心文件&#xff0c;开发者可以找到程序…

java中跨域问题及解决方案

1. 什么是跨域 从不同的地址访问另外一个地址就是跨域 2.跨域一定会有异常吗 跨域异常只会在前端发生&#xff0c;后端跨域不会产生异常 因为浏览器有一个叫做同源策略的东西&#xff0c;它发现不同域之间的访问是不安全的行为&#xff0c;会禁止&#xff0c;所以会抛出异常…

网络层协议 IP 协议介绍 -- IP 协议,网段划分,私有 IP 和 公网 IP,路由

目录 1 IP 协议 1.1 IP 协议格式 2. 网段划分 2.1 网络号和主机号 2.2 传统 IP 地址分类和 CIDR 技术 2.3 特殊的 IP 地址 2.4 IP 地址的数量限制 2.5 私有 IP 和公网 IP 3. 路由 网络层主要作用是实现不同局域网之间的通信连接&#xff0c;并为数据在复杂网络环境中的…

【案例分享】KMDA-7611-S001--高性能嵌入式电脑助力双臂轮式人形机器人应用

智能制造时代&#xff0c;双臂轮式机器人需求浮出水面 随着制造业、物流业和电子商务的飞速发展&#xff0c;智能搬运机器人正成为行业降本增效的核心工具。它们不仅解决了传统物流中效率低、成本高、安全性差等痛点&#xff0c;更通过智能化与可扩展性设计&#xff0c;通过自主…