uniapp - editor 富文本的使用

目录

[editor 组件](#editor 组件)

属性说明

editorContext

uni.createSelectorQuery()

SelectorQuery

selectorQuery.in(component)

selectorQuery.select(selector)

selectorQuery.selectAll(selector)

selectorQuery.selectViewport()

selectorQuery.exec(callback)

NodesRef

nodesRef.fields(object,callback)

[editorContext.format(name, value)](#editorContext.format(name, value))

editorContext.insertDivider(OBJECT)

editorContext.insertImage(OBJECT)

editorContext.getContents(OBJECT)

完整例子


editor 组件

富文本编辑器,可以对图片、文字格式进行编辑和混排。

在web开发时,可以使用contenteditable来实现内容编辑。但这是一个dom API,在非H5平台无法使用。于是微信小程序和uni-app的App-vue提供了editor组件来实现这个功能,并且在uni-app的H5平台也提供了兼容。从技术本质来讲,这个组件仍然运行在视图层webview中,利用的也是浏览器的contenteditable功能。

编辑器导出内容支持带标签的 html和纯文本的 text,编辑器内部采用 delta 格式进行存储。

通过setContents接口设置内容时,解析插入的 html 可能会由于一些非法标签导致解析错误,建议开发者在应用内使用时通过 delta 进行插入。

富文本组件内部引入了一些基本的样式使得内容可以正确的展示,开发时可以进行覆盖。需要注意的是,在其它组件或环境中使用富文本组件导出的html时,需要额外引入这段样式,并维护<ql-container><ql-editor></ql-editor></ql-container>的结构,参考:使用 editor 组件导出的 html

图片控件仅初始化时设置有效。

相关 api:editorContext

属性说明

属性 类型 默认值 必填 说明
read-only boolean false 设置编辑器为只读
placeholder string 提示信息
show-img-size boolean false 点击图片时显示图片大小控件
show-img-toolbar boolean false 点击图片时显示工具栏控件
show-img-resize boolean false 点击图片时显示修改尺寸控件
@ready eventhandle 编辑器初始化完成时触发
@focus eventhandle 编辑器聚焦时触发,event.detail = {html, text, delta}
@blur eventhandle 编辑器失去焦点时触发,detail = {html, text, delta}
@input eventhandle 编辑器内容改变时触发,detail = {html, text, delta}
@statuschange eventhandle 通过 Context 方法改变编辑器内样式时触发,返回选区已设置的样式

editorContext

editor 组件对应的 editorContext 实例,可通过 uni.createSelectorQuery 获取。

uni.createSelectorQuery()

返回一个 SelectorQuery 对象实例。可以在这个实例上使用 select 等方法选择节点,并使用 boundingClientRect 等方法选择需要查询的信息。

Tips:

  • 使用 uni.createSelectorQuery() 需要在生命周期 mounted 后进行调用。
  • 默认需要使用到 selectorQuery.in 方法。

SelectorQuery

查询节点信息的对象

selectorQuery.in(component)

将选择器的选取范围更改为自定义组件 component 内,返回一个 SelectorQuery 对象实例。(初始时,选择器仅选取页面范围的节点,不会选取任何自定义组件中的节点)。

代码示例

const query = uni.createSelectorQuery().in(this);
query
  .select("#id")
  .boundingClientRect((data) => {
    console.log("得到布局位置信息" + JSON.stringify(data));
    console.log("节点离页面顶部的距离为" + data.top);
  })
  .exec();

注意

  • 支付宝小程序不支持 in(component),使用无效果

selectorQuery.select(selector)

在当前页面下选择第一个匹配选择器 selector 的节点,返回一个 NodesRef 对象实例,可以用于获取节点信息。

selector 说明:

selector 类似于 CSS 的选择器,但仅支持下列语法。

  • ID 选择器:#the-id
  • class 选择器(可以连续指定多个):.a-class.another-class
  • 子元素选择器:.the-parent > .the-child
  • 后代选择器:.the-ancestor .the-descendant
  • 跨自定义组件的后代选择器:.the-ancestor >>> .the-descendant (H5 暂不支持)
  • 多选择器的并集:#a-node, .some-other-nodes

selectorQuery.selectAll(selector)

在当前页面下选择匹配选择器 selector 的所有节点,返回一个 NodesRef 对象实例,可以用于获取节点信息。

selectorQuery.selectViewport()

选择显示区域,可用于获取显示区域的尺寸、滚动位置等信息,返回一个 NodesRef 对象实例。

selectorQuery.exec(callback)

执行所有的请求。请求结果按请求次序构成数组,在 callback 的第一个参数中返回。

NodesRef

用于获取节点信息的对象

nodesRef.fields(object,callback)

获取节点的相关信息。第一个参数是节点相关信息配置(必选);第二参数是方法的回调函数,参数是指定的相关节点信息。

object 参数说明

字段名 类型 默认值 必填 说明 平台差异说明
id Boolean false 是否返回节点 id
dataset Boolean false 是否返回节点 dataset App、微信小程序、H5
rect Boolean false 是否返回节点布局位置(left right top bottom
size Boolean false 是否返回节点尺寸(width height
scrollOffset Boolean false 是否返回节点的 scrollLeft scrollTop,节点必须是 scroll-view 或者 viewport
properties Array<string> [] 指定属性名列表,返回节点对应属性名的当前属性值(只能获得组件文档中标注的常规属性值,id class style 和事件绑定的属性值不可获取) 仅 App 和微信小程序支持
computedStyle Array<string> [] 指定样式名列表,返回节点对应样式名的当前值 仅 App 和微信小程序支持
context Boolean false 是否返回节点对应的 Context 对象 仅 App 和微信小程序支持

editorContext.format(name, value)

修改样式

参数 类型 说明
name String 属性
value String

支持设置的样式列表

name value 平台差异说明
bold
italic
underline
strike
ins
script sub / super
header H1 / H2 / h3 / H4 / h5 / H6
align left / center / right / justify left百度小程序不支持
direction rtl
indent -1 / +1
list ordered / bullet / check
color hex color
backgroundColor hex color
margin/marginTop/marginBottom/marginLeft/marginRight css style 百度小程序不支持
padding/paddingTop/paddingBottom/paddingLeft/paddingRight css style 百度小程序不支持
font/fontSize/fontStyle/fontVariant/fontWeight/fontFamily css style 百度小程序不支持
lineHeight css style 百度小程序不支持
letterSpacing css style 百度小程序不支持
textDecoration css style 百度小程序不支持
textIndent css style 百度小程序不支持
wordWrap css style 百度小程序不支持
wordBreak css style 百度小程序不支持
whiteSpace css style 百度小程序不支持

对已经应用样式的选区设置会取消样式。css style 表示 css 中规定的允许值。

editorContext.insertDivider(OBJECT)

插入分割线

OBJECT 参数说明

属性 类型 默认值 必填 说明
success Function 接口调用成功的回调函数
fail Function 接口调用失败的回调函数
complete Function 接口调用结束的回调函数(调用成功、失败都会执行)

editorContext.insertImage(OBJECT)

插入图片。

微信小程序平台地址为临时文件时,获取的编辑器html格式内容中 <img> 标签增加属性 data-local,delta 格式内容中图片 attributes 属性增加 data-local 字段,该值为传入的临时文件地址。 开发者可选择在提交阶段上传图片到服务器,获取到网络地址后进行替换。替换时对于html内容应替换掉 <img> 的 src 值,对于 delta 内容应替换掉 insert { image: abc } 值。

OBJECT 参数说明

属性 类型 默认值 必填 说明
src String 图片地址,仅支持 http(s)、base64、本地图片
alt String 图像无法显示时的替代文本
width String 图片宽度(pixels/百分比),2.6.5+ 支持,百度小程序不支持
height String 图片高度 (pixels/百分比),2.6.5+ 支持,百度小程序不支持
extClass String 添加到图片 img 标签上的类名,2.6.5+ 支持
data Object data 被序列化为 name=value;name1=value2 的格式挂在属性 data-custom 上,2.6.5+ 支持
success Function 接口调用成功的回调函数
fail Function 接口调用失败的回调函数
complete Function 接口调用结束的回调函数(调用成功、失败都会执行)

editorContext.getContents(OBJECT)

获取编辑器内容

OBJECT 参数说明

属性 类型 默认值 必填 说明
success Function 接口调用成功的回调函数
fail Function 接口调用失败的回调函数
complete Function 接口调用结束的回调函数(调用成功、失败都会执行)

object.success 回调函数

属性 类型 说明
html string 带标签的 HTML 内容
text string 纯文本内容
delta Object 表示内容的 delta 对象

完整例子

<template>
	<view class="edit">
		<view class="title">
			<input type="text" v-model="artData.title" placeholder="请输入完整的标题" placeholder-class="placeholderClass" />
		</view>
		<view class="content">
			<editor
				class="myEdit"
				placeholder="写点什么吧~~"
				show-img-resize
				show-img-toolbar
				show-img-size
				@ready="onEditReady"
				@focus="OnFocus"
				@statuschange="statuschange"
			></editor>
		</view>
		<view class="btnGroup">
			<u-button type="primary" text="确认发表" @click="onSubmit" :disabled="!artData.title"></u-button>
		</view>
		<view class="tools" v-show="toolsShow">
			<!-- 标题 -->
			<view class="item" @click="headChange">
				<text class="iconfont icon-zitibiaoti" :class="headShow ? 'active' : ''"></text>
			</view>
			<!-- 加粗 -->
			<view class="item" @click="boldChange">
				<text class="iconfont icon-zitijiacu" :class="boldShow ? 'active' : ''"></text>
			</view>
			<!-- 斜体 -->
			<view class="item" @click="italicChange">
				<text class="iconfont icon-zitixieti" :class="italicShow ? 'active' : ''"></text>
			</view>
			<!-- 分割线 -->
			<view class="item" @click="insertDivider"><text class="iconfont icon-fengexian"></text></view>
			<view class="item" @click="insertImage"><text class="iconfont icon-charutupian"></text></view>
			<!-- 完成 -->
			<view class="item" @click="editOk"><text class="iconfont icon-duigou_kuai"></text></view>
		</view>
	</view>
</template>

<script>
export default {
	data() {
		return {
			toolsShow: false,
			editorContent: null,
			headShow: false,
			boldShow: false,
			italicShow: false,
			artData: {
				title: '',
				content: ''
			}
		};
	},
	methods: {
		// 初始化
		onEditReady() {
			// 查询节点信息的对象
			// 将选择器的选取范围更改为自定义组件 component 内,返回一个 SelectorQuery 对象实例。(初始时,选择器仅选取页面范围的节点,不会选取任何自定义组件中的节点)。
			// 在当前页面下选择第一个匹配选择器 selector 的节点,返回一个 NodesRef 对象实例,可以用于获取节点信息。
			// 获取节点的相关信息。第一个参数是节点相关信息配置(必选);第二参数是方法的回调函数,参数是指定的相关节点信息。
			// 执行所有的请求。请求结果按请求次序构成数组,在 callback 的第一个参数中返回。
			uni.createSelectorQuery()
				.in(this)
				.select('.myEdit')
				.fields(
					{
						size: true, //是否返回节点尺寸(width height)
						context: true //是否返回节点尺寸(width height)
					},
					(res) => {
						console.log(res);
						this.editorContent = res.context;
					}
				)
				.exec();
		},
		// 离开焦点
		OnFocus() {
			this.toolsShow = true;
		},
		// 添加分割线
		insertDivider() {
			this.editorContent.insertDivider();
		},
		// 添加大标题
		headChange() {
			this.headShow = !this.headShow;
			this.editorContent.format('header', this.headShow ? 'H2' : false);
		},
		// 加粗
		boldChange() {
			this.boldShow = !this.boldShow;
			this.editorContent.format('bold');
		},
		// 斜体
		italicChange() {
			this.italicShow = !this.italicShow;
			this.editorContent.format('italic');
		},
		// 用于检查对象detail是否包含名为name的属性
		checkStatus(name, detail, key) {
			if (detail.hasOwnProperty(name)) {
				this[key] = true;
			} else {
				this[key] = false;
			}
		},
		// 通过 Context 方法改变编辑器内样式时触发,返回选区已设置的样式(解决标题标签回弹问题)
		statuschange(e) {
			let detail = e.detail;
			console.log(detail);
			this.checkStatus('header', detail, 'headShow');
			this.checkStatus('bold', detail, 'boldShow');
			this.checkStatus('italic', detail, 'italicShow');
		},
		// 添加图像
		insertImage() {
			// 打开相机
			uni.chooseImage({
				count: 3, //默认9
				sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有
				success: async (res) => {
					let tempFiles = res.tempFiles;
					for (let item of tempFiles) {
						uni.showLoading({
							mask: true,
							title: '上传中...'
						});
						try {
							let res = await uniCloud.uploadFile({
								filePath: item.path, //要上传的文件对象
								cloudPath: item.name //cloudPath为云端文件名,
							});
							// 设置图片地址 图片地址,仅支持 http(s)、base64、本地图片
							this.editorContent.insertImage({
								src: res.fileID
							});
							uni.hideLoading();
						} catch (e) {
							uni.hideLoading();
							uni.showModal({
								content: '上传失败',
								title: '提示'
							});
						}
					}
				}
			});
		},
		// 确认
		editOk() {
			this.toolsShow = false;
		},
		onSubmit() {
			console.log(11);
			this.editorContent.getContents({
				success: (res) => {
					console.log(res);
					this.artData.content = res.html;
				}
			});
		}
	}
};
</script>

<style lang="scss">
/deep/ .ql-blank::before {
	font-style: normal;
	color: #e0e0e0;
}

.edit {
	padding: 30rpx;
	.title {
		input {
			height: 120rpx;
			font-size: 46rpx;
			border-bottom: 1px solid #e4e4e4;
			margin-bottom: 30rpx;
			color: #000;
		}
		.placeholderClass {
			color: #e0e0e0;
		}
	}
	.content {
		.myEdit {
			height: calc(100vh - 500rpx);
			margin-bottom: 30rpx;
		}
	}
	.tools {
		width: 100%;
		height: 80rpx;
		background: #fff;
		border-top: 1rpx solid #f4f4f4;
		position: fixed;
		left: 0;
		bottom: 0;
		display: flex;
		justify-content: space-around;
		align-items: center;
		.iconfont {
			font-size: 36rpx;
			color: #333;
			// 选择按钮的高亮
			&.active {
				color: #0199fe;
			}
		}
	}
}
</style>
相关推荐
用户48062260414152 小时前
使用uniapp开发微信小程序-框架搭建
微信小程序·uni-app
TttHhhYy4 小时前
uniapp+vue开发app,蓝牙连接,蓝牙接收文件保存到手机特定文件夹,从手机特定目录(可自定义),读取文件内容,这篇首先说如何读取,手机目录如何寻找
开发语言·前端·javascript·vue.js·uni-app
Funky_oaNiu4 小时前
uniapp实现按钮防重复点击(防抖)完整解决方案
uni-app
原克技术5 小时前
uniapp验证码
uni-app
web150850966411 天前
在uniapp Vue3版本中如何解决webH5网页浏览器跨域的问题
前端·uni-app
何极光1 天前
uniapp小程序样式穿透
前端·小程序·uni-app
User_undefined2 天前
uniapp Native.js 调用安卓arr原生service
android·javascript·uni-app
流氓也是种气质 _Cookie2 天前
uniapp blob格式转换为video .mp4文件使用ffmpeg工具
ffmpeg·uni-app
爱笑的眼睛112 天前
uniapp 极速上手鸿蒙开发
华为·uni-app·harmonyos
小刘鸭!2 天前
notepad++快捷键-多行编辑中如何使所有行的光标都向后移动一个单词的长度(每行单词长度不一定一致)
前端·javascript·notepad++