当前位置:   article > 正文

uniapp自定义富文本编辑器+内容渲染回显功能(多端可用)_uniapp 富文本

uniapp 富文本

这个编辑器app端、H5端、小程序端都可以用,这里以小程序为例

先上效果图文本编辑、样式调整、图片上传等各项功能皆可满足。

一、整体介绍

 使用富文本编辑并且可以渲染内容这个功能,主要涉及到两个页面。

①触发编辑的页面(按钮+接收富文本内容)②编辑器页面(效果图页面)

二、完整代码 
 页面①:

写一个按钮点击事件跳转到编辑器页面(这部分代码很简单就不展示了)

接收富文本内容的代码如下,

  1. // 接收富文本
  2. uni.$on('getContents', data => {
  3. console.log("接收到的内容:", data); // 输出接收到的内容
  4. });

可以在页面初始化的时候接收富文本内容,我是放在生命周期created()阶段进行接收的。接收到的data可以自定义变量进行赋值,想在哪里展示都可以。

页面②:

 比较重要的是,在失去焦点的时候,触发的方法。也是在这里获取富文本内容

  1. // 获取富文本编辑器的内容
  2. uni.$emit('getContents', res)

为了方便回显,可以将富文本内容缓存一下。然后再次进入编辑器页面的时候,获取一下缓存就可以回显了,但是要及时清除上一次的缓存(需要的时候要在页面①清除) 

  1. // 存储富文本内容 方便下次显示
  2. wx.setStorageSync('getContents', res);
  3. //获取缓存的内容
  4. var lastContent = wx.getStorageSync('getContents');
  5. //移除富文本缓存内容
  6. wx.removeStorageSync('getContents')
   重点!!!下面是编辑器的完整代码: 
  1. <template>
  2. <view class="container">
  3. <view class="page-body">
  4. <view class='wrapper'>
  5. <view class='toolbar' @tap="format">
  6. <view :class="formats.bold ? 'ql-active' : ''" class="iconfont icon-zitijiacu" data-name="bold">
  7. </view>
  8. <view :class="formats.italic ? 'ql-active' : ''" class="iconfont icon-zitixieti" data-name="italic">
  9. </view>
  10. <view :class="formats.underline ? 'ql-active' : ''" class="iconfont icon-zitixiahuaxian"
  11. data-name="underline"></view>
  12. <view :class="formats.strike ? 'ql-active' : ''" class="iconfont icon-zitishanchuxian"
  13. data-name="strike"></view>
  14. <view :class="formats.align === 'left' ? 'ql-active' : ''" class="iconfont icon-zuoduiqi"
  15. data-name="align" data-value="left"></view>
  16. <view :class="formats.align === 'center' ? 'ql-active' : ''" class="iconfont icon-juzhongduiqi"
  17. data-name="align" data-value="center"></view>
  18. <view :class="formats.align === 'right' ? 'ql-active' : ''" class="iconfont icon-youduiqi"
  19. data-name="align" data-value="right"></view>
  20. <view :class="formats.align === 'justify' ? 'ql-active' : ''" class="iconfont icon-zuoyouduiqi"
  21. data-name="align" data-value="justify"></view>
  22. <view :class="formats.lineHeight ? 'ql-active' : ''" class="iconfont icon-line-height"
  23. data-name="lineHeight" data-value="2"></view>
  24. <view :class="formats.letterSpacing ? 'ql-active' : ''" class="iconfont icon-Character-Spacing"
  25. data-name="letterSpacing" data-value="2em"></view>
  26. <view :class="formats.marginTop ? 'ql-active' : ''" class="iconfont icon-722bianjiqi_duanqianju"
  27. data-name="marginTop" data-value="20px"></view>
  28. <view :class="formats.previewarginBottom ? 'ql-active' : ''"
  29. class="iconfont icon-723bianjiqi_duanhouju" data-name="marginBottom" data-value="20px"></view>
  30. <!-- <view :class="formats.fontFamily ? 'ql-active' : ''" class="iconfont icon-font"
  31. data-name="fontFamily" data-value="Pacifico"></view> -->
  32. <view :class="formats.fontSize === '24px' ? 'ql-active' : ''" class="iconfont icon-fontsize"
  33. data-name="fontSize" data-value="24px"></view>
  34. <view :class="formats.color === '#0000ff' ? 'ql-active' : ''" class="iconfont icon-text_color"
  35. data-name="color" data-value="#0000ff"></view>
  36. <view :class="formats.backgroundColor === '#00ff00' ? 'ql-active' : ''"
  37. class="iconfont icon-fontbgcolor" data-name="backgroundColor" data-value="#00ff00"></view>
  38. <view class="iconfont icon--checklist" data-name="list" data-value="check"></view>
  39. <view :class="formats.list === 'ordered' ? 'ql-active' : ''" class="iconfont icon-youxupailie"
  40. data-name="list" data-value="ordered"></view>
  41. <view :class="formats.list === 'bullet' ? 'ql-active' : ''" class="iconfont icon-wuxupailie"
  42. data-name="list" data-value="bullet"></view>
  43. <view class="iconfont icon-outdent" data-name="indent" data-value="-1"></view>
  44. <view class="iconfont icon-indent" data-name="indent" data-value="+1"></view>
  45. <view :class="formats.header === 1 ? 'ql-active' : ''" class="iconfont icon-format-header-1"
  46. data-name="header" :data-value="1"></view>
  47. <view :class="formats.script === 'sub' ? 'ql-active' : ''" class="iconfont icon-zitixiabiao"
  48. data-name="script" data-value="sub"></view>
  49. <view :class="formats.script === 'super' ? 'ql-active' : ''" class="iconfont icon-zitishangbiao"
  50. data-name="script" data-value="super"></view>
  51. <!-- <view :class="formats.direction === 'rtl' ? 'ql-active' : ''" class="iconfont icon-direction-rtl"
  52. data-name="direction" data-value="rtl"></view> -->
  53. <view class="iconfont icon-fengexian" @tap="insertDivider"></view>
  54. <!-- <view class="iconfont icon-clearedformat" @tap="removeFormat"></view> -->
  55. <view class="iconfont icon-charutupian" @tap="insertImage"></view>
  56. <view class="iconfont icon-date" @tap="insertDate"></view>
  57. <view class="iconfont icon-shanchu" @tap="clear"></view>
  58. <view class="iconfont icon-undo" @tap="undo"></view>
  59. <view class="iconfont icon-redo" @tap="redo"></view>
  60. </view>
  61. <editor id="editor" class="ql-container" placeholder="开始输入..." showImgSize showImgToolbar showImgResize
  62. @statuschange="onStatusChange" :read-only="false" @ready="onEditorReady" @input="getContents">
  63. </editor>
  64. </view>
  65. </view>
  66. </view>
  67. </template>
  68. <script>
  69. export default {
  70. data() {
  71. return {
  72. formats: {},
  73. timer: null,
  74. editorDetail: "",
  75. }
  76. },
  77. mounted() {
  78. this.onEditorReady();
  79. console.log('-------------this',this)
  80. // 将数据渲染到富文本内
  81. this.timer = setInterval(() => {
  82. if (this.editorDetail) {
  83. clearInterval(this.timer)
  84. //延时0.5秒 方便接收缓存的上次内容
  85. setTimeout(res => {
  86. this.editorCtx.setContents({
  87. html: this.editorDetail,
  88. success(res) {
  89. console.log('--------',res);
  90. }
  91. })
  92. },500)
  93. }
  94. }, 100)
  95. },
  96. created() {
  97. //获取缓存的内容
  98. var lastContent = wx.getStorageSync('getContents');
  99. if (lastContent && lastContent.html) {
  100. this.editorDetail = lastContent.html
  101. }
  102. },
  103. methods: {
  104. // 失去焦点时触发,获取富文本的内容
  105. getContents() {
  106. let _this = this
  107. this.editorCtx.getContents({
  108. success(res) {
  109. // let content = res;
  110. // 获取富文本编辑器的内容
  111. uni.$emit('getContents', res)
  112. // 存储富文本内容 方便下次显示
  113. wx.setStorageSync('getContents', res);
  114. }
  115. })
  116. },
  117. //编辑框初始化时触发
  118. onEditorReady() {
  119. uni.createSelectorQuery().select('#editor').context((res) => {
  120. this.editorCtx = res.context;
  121. }).exec()
  122. },
  123. //撤销
  124. undo() {
  125. this.editorCtx.undo()
  126. },
  127. //恢复
  128. redo() {
  129. this.editorCtx.redo()
  130. },
  131. format(e) {
  132. let {
  133. name,
  134. value
  135. } = e.target.dataset
  136. if (!name) return
  137. this.editorCtx.format(name, value)
  138. },
  139. //通过 Context 方法改变编辑器内样式时触发,返回选区已设置的样式
  140. onStatusChange(e) {
  141. this.formats = e.detail
  142. console.log(e);
  143. },
  144. //插入分隔符
  145. insertDivider() {
  146. this.editorCtx.insertDivider({
  147. success: function() {
  148. console.log('insert divider success')
  149. }
  150. })
  151. },
  152. //清空全部内容
  153. clear() {
  154. this.editorCtx.clear({
  155. success: function(res) {
  156. console.log("clear success")
  157. }
  158. })
  159. },
  160. //清除样式
  161. removeFormat() {
  162. this.editorCtx.removeFormat()
  163. },
  164. //插入当前日期
  165. insertDate() {
  166. const date = new Date()
  167. const formatDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`
  168. this.editorCtx.insertText({
  169. text: formatDate
  170. })
  171. },
  172. //插入图片
  173. insertImage() {
  174. uni.chooseImage({
  175. count: 1,
  176. success: (res) => {
  177. let file = res.tempFiles[0]
  178. var img = {
  179. fgn: file.path.substring(file.path.lastIndexOf('/')+1)
  180. }
  181. uni.uploadFile({
  182. url: "url", //你的图片上传接口
  183. filePath: file.path, // 随便填,不为空即可
  184. name: 'img', // 随便填,不为空即可
  185. // header: header, // 可以加access_token等
  186. formData: img, // 接口参数,json格式,底层自动转为FormData的格式数据
  187. success: (res)=>{
  188. this.editorCtx.insertImage({
  189. src: JSON.parse(res.data).data.src,
  190. alt: '图像',
  191. success: function() {
  192. console.log('insert image success')
  193. }
  194. })
  195. }
  196. })
  197. }
  198. })
  199. }
  200. },
  201. }
  202. </script>
  203. <style>
  204. @import '@/style/editor-icon.css';
  205. .wrapper {
  206. padding: 5px;
  207. }
  208. .iconfont {
  209. display: inline-block;
  210. padding: 15px;
  211. width: 24px;
  212. height: 24px;
  213. cursor: pointer;
  214. font-size: 20px;
  215. }
  216. .toolbar {
  217. box-sizing: border-box;
  218. border-bottom: 0;
  219. font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
  220. background-color: #ffffff;
  221. position: -webkit-sticky;
  222. position: sticky;
  223. top: var(--window-top);
  224. z-index: 99;
  225. height: 95px;
  226. }
  227. .ql-container {
  228. box-sizing: border-box;
  229. padding: 12px 15px;
  230. width: 100%;
  231. min-height: 30vh;
  232. height: auto;
  233. background: #fff;
  234. margin-top: 10px;
  235. font-size: 16px;
  236. line-height: 1.5;
  237. }
  238. .ql-active {
  239. color: #06c;
  240. }
  241. </style>

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读