- Editor 富文本编辑器
- 介绍
- 使用方法
- Editor 组件属性列表
- EditorContext 实例
- 使用方法
- EditorContext.blur(Object object)
- EditorContext.clear(Object object)
- EditorContext.format(String name, String value)
- EditorContext.getContents(Object object)
- EditorContext.getSelectionText(Object object)
- EditorContext.insertDivider(Object object)
- EditorContext.insertImage(Object object)
- EditorContext.insertText(Object object)
- EditorContext.removeFormat(Object object)
- EditorContext.setContents(Object object)
- EditorContext.scrollIntoView()
- EditorContext.redo(Object object)
- EditorContext.undo(Object object)
- 示例
Editor 富文本编辑器
介绍
Editor 富文本编辑器动态库提供了支持富文本编辑的editor
组件和操作editor
组件的createEditorContext
方法,通过使用该动态库,用户可以对图片、文本进行编辑。编辑器导出内容支持带标签的html
和纯文本的text
,编辑器内部采用delta
格式进行存储。
富文本编辑器组件中设置了一些基本样式使得内容可以正确展示,在开发过程中可以进行覆盖,在其他组件或者环境中使用富文本编辑器导出的html
时,需要额外维护以下DOM
结构:
<ql-container>
<ql-editor></ql-editor>
</ql-container>
使用方法
1. 在项目中引用动态库
参考使用动态库中提供的方法,在app.json
中增添一项dynamicLib
,与pages
同级。
- JSON
"dynamicLib": {
"editorLib": {
"provider": "swan-editor"
}
},
2. 在使用到富文本编辑器组件的页面配置动态库
在每个使用到富文本编辑器组件的页面,配置*.json
文件如:
- JSON
{
"usingSwanComponents": {
"editor": "dynamicLib://editorLib/editor"
}
}
3. 编写*.swan
文件
- SWAN
<editor
read-only="{{readOnly}}"
placeholder="{{placeholder}}"
/>
这是一种最基本的使用方式,其中readOnly
和placeholder
的值可以在*.js
文件中设置。
- JS
Page({
data: {
readOnly: false,
placeholder: '请输入...'
}
});
Editor 组件属性列表
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
read-only | Boolean | false | 否 | 设置编辑器为只读 |
placeholder | String | 否 | 编辑器提示信息 | |
show-img-size | Boolean | false | 否 | 点击图片时显示图片大小控件 |
show-img-resize | Boolean | false | 否 | 点击图片时显示图片缩放控件 |
show-img-toolbar | Boolean | false | 否 | 点击图片时显示图片工具栏控件 |
bindready | EventHandle | 否 | 编辑器初始化完成时触发 | |
bindfocus | EventHandle | 否 | 编辑器聚焦时触发,event.detail = { html, text, delta } | |
bindblur | EventHandle | 否 | 编辑器失去焦点时触发,event.detail = { html, text, delta } | |
bindinput | EventHandle | 否 | 编辑器内容改变时触发,event.detail = { html, text, delta } | |
bindstatuschange | EventHandle | 否 | 编辑器内容或样式通过EditorContext 中的方法改变时触发,返回选区已设置的样式 |
编辑器内支持部分HTML
标签和内联样式,但不支持class
和id
。
支持的标签
不满足的标签会被忽略,
div
标签会被转换为p
标签存储。
类型 | 节点 |
---|---|
行内元素 | <span><strong> <b> <em> <i> <u> <a> <s> <sub> <sup> <img> |
块级元素 | <br> <hr> <ol> <ul> <li> <h1> <h2> <h3> <h4> <h5> <h6> |
支持的内联样式
内联样式仅支持设置在行内元素或块级元素上,不能同时设置,如
text-align
归类为块级样式,在span
标签上设置是无效的。
类型 | 样式 |
---|---|
块级样式 | text-align、direction |
行内样式 | color、background-color |
EditorContext 实例
Editor 富文本编辑器动态库提供了createEditorContext
的方法来获取某个editor
组件的实例,EditorContext
通过id
和一个editor
组件绑定,操作对应的editor
组件。
使用方法
- JS
Page({
onEditorReady() {
this.editorCtx = requireDynamicLib('editorLib').createEditorContext('editorId');
}
});
EditorContext.blur(Object object)
解释:编辑器失焦。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
EditorContext.clear(Object object)
解释:清空编辑器内容。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
EditorContext.format(String name, String value)
解释:修改格式。
对已经应用样式的选区设置会取消样式。
参数
String name:属性
String value:值
支持设置的样式列表
name | value |
---|---|
bold | |
italic | |
underline | |
strike | |
ins | |
script | sub / super |
header | H1 / H2 / H3 / H4 / H5 / H6 |
align | center / right / justify |
direction | rtl |
indent | -1 / +1 |
list | ordered / bullet / check |
color | hex color |
backgroudColor | hex color |
EditorContext.getContents(Object object)
解释:获取编辑器内容。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
object.success 回调函数
参数:Object res
属性 | 类型 | 说明 |
---|---|---|
html | String | 带标签的html 内容 |
text | String | 纯文本内容 |
delta | Object | 描述内容的delta 对象 |
EditorContext.getSelectionText(Object object)
解释:获取编辑器内选区的纯文本内容。当编辑器失焦或未选中一段区间时,返回内容为空。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
object.success 回调函数
参数:Object res
属性 | 类型 | 说明 |
---|---|---|
text | String | 纯文本内容 |
EditorContext.insertDivider(Object object)
解释:插入分隔符。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
EditorContext.insertImage(Object object)
解释:插入图片。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
src | String | 是 | 图片地址,目前仅支持 http(s)、base64、本地图片 | |
alt | String | 否 | 图片无法显示时的替代文本 | |
extClass | String | 否 | 添加到图片 img 标签上的类名 | |
data | Object | 否 | data 会被序列化为name1=value1&name2=value2 的格式挂在属性 data-custom 上 | |
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
EditorContext.insertText(Object object)
解释:覆盖当前选区,设置一段文本。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
text | String | 否 | 文本内容 | |
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
EditorContext.removeFormat(Object object)
解释:清除当前选区的样式。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
EditorContext.setContents(Object object)
解释:初始化编辑器内容,html
和delta
同时存在时仅delta
生效。
需要注意的是,通过
setContents
设置编辑器内容时,由于支持的html
标签和内联样式有限,建议开发者在小程序内通过delta
进行插入。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
html | String | 否 | 带标签的html 内容 | |
delta | Object | 否 | 描述内容的delta 对象 | |
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
EditorContext.scrollIntoView()
解释:将编辑器光标处滚动到窗口可视区域内。
EditorContext.redo(Object object)
解释:恢复。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
EditorContext.undo(Object object)
解释:撤销。
参数:Object object
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
success | Function | 否 | 接口调用成功的回调函数 | |
fail | Function | 否 | 接口调用失败的回调函数 | |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
示例
扫码体验
代码示例
请使用百度APP扫码
图片示例
- SWAN
- JS
- CSS
<view class="toolbar" catchtouchend="format">
<view class="iconfont icon-image" catchtouchend="insertImage"></view>
<view class="iconfont icon-format-header-1 {{formats.header === 1 ? 'ql-active' : ''}}" data-name="header" data-value={{1}}></view>
<view class="iconfont icon-format-header-2 {{formats.header === 2 ? 'ql-active' : ''}}" data-name="header" data-value={{2}}></view>
<view class="iconfont icon-format-bold {{formats.bold ? 'ql-active' : ''}}" data-name="bold"></view>
<view class="iconfont icon-format-italic {{formats.italic ? 'ql-active' : ''}}" data-name="italic"></view>
<view class="iconfont icon-format-list {{formats.list === 'checked' ? 'ql-active' : ''}}" data-name="list" data-value="checked"></view>
<view class="iconfont icon-divider" catchtouchend="insertDivider"></view>
<view class="iconfont icon-clear" catchtouchend="clear"></view>
</view>
<view class="editor-wrap">
<editor
id="editorId"
class="editor"
placeholder="开始输入..."
bindready="onEditorReady"
bindstatuschange="onStatusChange"
show-img-size
show-img-resize
show-img-toolbar
/>
</view>
const INIT_CONTENT_HTML = `
<p>支持插入图片</p>
<br>
<p>
<img src="https://b.bdstatic.com/searchbox/icms/searchbox/img/editor-image-demo.png" data-custom="id=abcd&role=god" alt="image-alt" class="imageCls" width="100%">
</p>
<hr>
<p>支持以下字符样式</p>
<p>
<b>bold粗体</b>
<em>italic斜体</em>
<u>underline下划线</u>
</p>
<p>
<sub>sub下标</sub>
<sup>super上标</sup>
</p>
<hr>
<p>支持以下列表样式</p>
<ol>
<li>有序列表</li>
<li>有序列表</li>
</ol>
<ul>
<li>无序列表</li>
</ul>
<ul>
<li>无序列表</li>
</ul>
<ul data-checked="true">
<li>选框列表</li>
</ul>
<ul data-checked="false">
<li>选框列表</li>
</ul>
<hr>
<p>支持以下字符大小</p>
<h1>H1 一级标题</h1>
<h2>H2 二级标题</h2>
<h3>H3 三级标题</h3>
<h4>H4 四级标题</h4>
<h5>H5 五级标题</h5>
<h6>H6 六级标题</h6>
<hr>
<p>支持以下对齐方式</p>
<p style="text-align:center">center中间对齐</p>
<p style="text-align:right">right 右对齐</p>
<p style="text-align:justify">justify 自动对齐</p>
<hr>
<span style="color:#00bc89;background-color:#333">color 支持设置字体及背景颜色</span>`;
Page({
data: {
formats: {}
},
// 编辑器初始化完成时触发的事件,用于加载编辑器初始内容
onEditorReady() {
this.editorCtx = requireDynamicLib('editorLib').createEditorContext('editorId');
this.initContent();
},
// 设置编辑器初始内容
initContent() {
this.editorCtx.setContents({
html: INIT_CONTENT_HTML
});
},
// 编辑器内插入图片函数
insertImage() {
const editorCtx = this.editorCtx;
swan.chooseImage({
count: 1,
success: res => {
editorCtx.insertImage({
src: res.tempFilePaths[0],
alt: '插入图片',
data: {
id: 'insert-image',
role: 'user'
},
success: () => {
swan.showToast({
title: '插入图片成功'
});
},
fail: err => {
swan.showToast({
title: '插入图片失败',
icon: 'none'
});
}
});
}
});
},
/**
* 更改编辑器选区为不同格式
*
* @param {Object} e.target.dataset 获取 swan 页面的传参:name、value
*
*/
format(e) {
const {name, value} = e.target.dataset;
if (!name) {
return;
}
this.editorCtx.format(name, value);
},
/**
* 编辑器内容或样式通过方法改变时触发的事件,返回选区已设置的样式
*
* @param {Object} e.detail 事件对象
*
*/
onStatusChange(e) {
const formats = e.detail;
this.setData({
formats
});
},
// 编辑器中插入分隔符
insertDivider() {
this.editorCtx.insertDivider();
},
// 清除编辑器中内容,与工具栏的垃圾桶图标对应
clear() {
const editorCtx = this.editorCtx;
swan.showModal({
title: '清空编辑器',
content: '确定清空编辑器全部内容?',
success: res => {
if (res.confirm) {
editorCtx.clear();
}
}
});
}
});
@font-face {
font-family: "iconfont"; /* project id 2000141 */
src: url(http://at.alicdn.com/t/font_2000141_vma36b09h9.wof) format("woff"),
url(http://at.alicdn.com/t/font_2000141_vma36b09h9.ttf) format("truetype"),
url(http://at.alicdn.com/t/font_2000141_vma36b09h9.svg#iconfont) format("svg");
}
.iconfont {
display: inline-block;
font-size: 22px;
width: 30px;
height: 30px;
font-family: "iconfont" !important;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-image:before {
content: "\e60e";
}
.icon-format-header-1:before {
content: "\e610";
}
.icon-format-header-2:before {
content: "\e60f";
}
.icon-format-bold:before {
content: "\e60a";
}
.icon-format-list:before {
content: "\e60b";
}
.icon-divider:before {
content: "\e609";
}
.icon-clear:before {
content: "\e60c";
}
.icon-format-italic:before {
content: "\e60d";
}
.editor-wrap {
width: 100%;
height: 100vh;
}
.editor {
display: block;
box-sizing: border-box;
width: 100%;
height: 100%;
margin-top: 50px;
padding: 38.043rpx 30.797rpx;
}
swan-editor {
display: block;
}
.ql-editor {
height: 100%;
}
.toolbar {
position: fixed;
box-sizing: border-box;
padding: 17px 17px;
width: 100%;
height: 45px;
top: 30;
left: 0;
border-top: .906rpx solid #e6e6e6;
border-bottom: .906rpx solid #e6e6e6;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #fff;
z-index: 99;
}
.ql-active {
color: #3388ff;
}