contenteditable 属性
假如我们给一个标签加上 contenteditable="true" 的属性,就像这样:
<div contenteditable="true"></div>
document.execCommand 方法
// document.execCommand(命令名称,是否展示用户界面,命令需要的额外参数)
document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
Selection 和 Range 对象
我们在执行 document.execCommand 这个命令之前首先要知道对谁执行,所以这里会有一个选区的概念,也就是 Selection 对象,它用来表示用户选择的范围或光标位置(光标可以看做是范围重合的特殊状态),一个页面用户可能选择多个范围(比如 Firefox)。也就是说 Selection 包含一个或多个 Range 对象( Selection 可以说是 Range 的集合),当然对于富文本编辑器来说,一般情况下,我们只会有一个选择区域,也就是一个 Range 对象,事实上大部分情况也是如此。
所以通常我们可以用 letrange=window.getSelection().getRangeAt(0) 来获取选中的内容信息( getRangeAt 接受一个索引值,因为会有多个 Range,而现在只有一个,所以写0)。
基本操作
加错
document.execCommand('bold', false, null);
图片
document.execCommand('insertImage', false, url||base64));
p
document.execCommand('formatblock', false, ‘<p>’);
h1
document.execCommand('formatblock', false, ‘<h1>’);
有序列表
document.execCommand('insertUnorderedList', false, null);
水平线
document.execCommand('insertHorizontalRule', false, null);
参数
document.execCommand('createLink', false, url);
插入图片
document.execCommand('insertImage', false, null);
document.execCommand('insertHorizontalRule', false, null);
demo 演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrapper{
width: 100vw;
height: 100vh;
border: 1px solid red;
display: flex;
}
.wrapper div{
width: 50%;
height: 100%;
}
.editBox{
background: skyblue;
}
.preViewBox{
background: #ab956d;
}
</style>
</head>
<body>
<button onclick='preview()'>预览</button>
<div class ='wrapper'>
<div>
<button onclick='bold()'>加粗</button>
<button onclick='h("h1")'>一级标题</button>
<button onclick='h("h2")'>二级标题</button>
<button onclick='insertImg()'>插入图片</button>
<button onclick='link()'>创建连接</button>
<h1>编辑区</h1>
<div class='editBox' contenteditable="true">
</div>
</div>
<div>
<h1>预览区</h1>
<div class='preViewBox'>
</div>
</div>
</div>
<script>
document
.getElementsByClassName("editBox")[0]
.addEventListener("input", function (e) {
console.log("contenteditable element changed",e.target.innerHTML);
});
function preview(){
let content = document.getElementsByClassName('editBox')[0].innerHTML
document.getElementsByClassName('preViewBox')[0].innerHTML=content
console.log(content)
}
// 加粗
function bold(){
document.execCommand('bold',false,null)
}
// h1
function h(params){
document.execCommand('formatBlock',false,params)
}
// 插入图片
function insertImg(){
let imgurl ='https://dss2.bdstatic.com/6Ot1bjeh1BF3odCf/it/u=1935283115,3535406749&fm=74&app=80&f=JPEG&size=f121,140?sec=1880279984&t=0cedd3805f55f84207a86dffa6f24408'
document.execCommand('insertImage',false,imgurl)
}
//创建连接
function link(){
document.execCommand('createLink',false,'http://www.baidu.com')
}
</script>
</body>
</html>
参考
代码编辑器使用
npm install react-codemirror2
npm install codemirror
import { UnControlled as CodeMirror } from "react-codemirror2";
import "codemirror/lib/codemirror.css";
import "codemirror/theme/material.css";
require("codemirror/mode/javascript/javascript");
<CodeMirror
value="<h1> welcome ♥ lazy coder</h1>"
options={{
mode: "javascript",
theme: "material",
lineNumbers: true,
}}
onChange={(editor, data, value) => {
console.log(editor, data, value)
html = value
}}