前言:开发App时遇到富文本编辑,我首先的思路在uniapp官网找一下,确实官网给提供了内置组件editor。相信测试过案例时,都会发现没有工具栏。我也想如果有现成可以直接使用该多好,不过插件市场用起来也比方便,更不利于理解,所以自己写一个简单的工具栏。
注意:不要在editor的同级元素设置固定高度(用flex或padding或margin),会导致editor内容不自动向上弹起,键盘输入时看不到光标位置。
一、效果图:真机调试的时候,HBuilderX 3.7.3
实现基础功能
粗体、标题(1,2)、字体颜色、数字列表、圆点列表、勾选列表

二、代码如下
解决问题思想:
(1)重点放在editor功能上,关于图标引入先忽略,我直接用button按钮来代替。
(2)分步解决该问题,简化问题本身难度
<template>
<view class="box">
<view class="toolbar">
<button @click="handleInsertImage">插入图片</button>
<button @click="handleSetBlod">粗体</button>
<button @click="handleSetHeader('H1')">h1</button>
<button @click="handleSetHeader('H2')">h2</button>
<button @click="handlePreviousStep">撤销</button>
<button @click="handleNextStep">恢复</button>
<button @click="handleSetColor">字体颜色</button>
<button @click="handleList('ordered')">数字列表</button>
<button @click="handleList('bullet')">圆点列表</button>
<button @click="handleList('check')">勾选列表</button>
</view>
<editor id="editor" class="ql-container container" placeholder="开始输入..." @ready="onEditorReady"></editor>
</view>
</template>
<script setup>
import {ref,reactive} from "vue";
import {onNavigationBarButtonTap} from '@dcloudio/uni-app';
let editorCtx;
const onEditorReady = ()=>{
// #ifdef APP-PLUS || H5 ||MP-WEIXIN
uni.createSelectorQuery().select('#editor').context((res) => {
editorCtx = reactive(res.context);
}).exec()
// #endif
}
//插入图片
const handleInsertImage = ()=>{
uni.chooseImage({
count: 1, //插图图片数量
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album','camera'], //从相册选择和拍照
success: function (res) {
//获得插入图片的临时路径(提交前,要将临时路径更换为网络路径)
let imageSrc = res.tempFilePaths[0];
editorCtx.insertImage({
src: imageSrc,
width: "100%",
height: "100%",
success: function(res){
console.log("成功插入图片");
},
fail: function(res){
console.log("插入图片失败");
}
});
}
});
}
//设置粗体
const handleSetBlod = ()=>{
editorCtx.format("bold");
}
//设置标题
const handleSetHeader = (value)=>{
editorCtx.format("header",value);
}
//设置颜色
const handleSetColor = ()=>{
editorCtx.format("color","red");
}
//设置list
const handleList = (value)=>{
editorCtx.format("list",value);
}
//撤销上一步
const handlePreviousStep = ()=>{
editorCtx.undo()
}
//恢复上一步
const handleNextStep = ()=>{
editorCtx.redo();
}
//点击完成时,提交内容
onNavigationBarButtonTap(()=>{
//第一,提交图片,将网络路径拿回来(tempSrc假设为拿回来的网络路径)
let tempSrc = "https://img2.baidu.com/it/u=1010328615,2032873142&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=790";
editorCtx.getContents({
success: function(res){
console.log(res);
let contentArr = res.delta.ops;
contentArr.forEach((item)=>{
if(item.insert.image){
item.insert.image = tempSrc;
}
})
console.log("重新看一下");
console.log(res);
editorCtx.setContents({
delta: res.delta,
success: function(res){
console.log("设置完成");
}
});
}
});
})
</script>
<style scoped lang="scss">
.box{
width: 100vw;
height: 100vh;
display: flex;
flex: 1;
flex-direction: column;
background-color: #F0EFF4;
.toolbar{
// background-color: #F0EFF4;
padding: 0 $teng-padding;
display: flex;
flex-wrap: wrap;
padding-top: 16rpx;
button{
min-width: 96rpx;
font-size: 28rpx;
margin-bottom: 16rpx;
}
}
.container {
display: flex;
flex: 0.97;
background-color: #fff;
padding: 0 $teng-padding;
padding-top: 8rpx;
}
}
</style>
三、注意
关于插入的图片路径替换为网络路径的逻辑思路 ?
https://blog.youkuaiyun.com/tengyuxin/article/details/131765670
我写的另一篇文章