日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

Vue 中使用 Tinymce 富文本编辑器

發布時間:2024/3/26 vue 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Vue 中使用 Tinymce 富文本编辑器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考鏈接:https://www.cnblogs.com/wisewrong/p/8985471.html

Tinymce : 從 word 粘貼過來還能保持絕大部分格式的編輯器

一. 下載

?

npm install tinymce -S

?安裝之后,在 node_modules 中找到 tinymce/skins 目錄,然后將 skins 目錄拷貝到 public 目錄下

(如果是使用 vue-cli 2.x 構建的 typescript 項目,就放到 static 目錄下)

tinymce 默認是英文界面,所以還需要下載一個中文 語言包

將這個語言包放到 public 目錄下,為了結構清晰,我包了一層 tinymce 目錄

二. 初始化

import tinymce from 'tinymce/tinymce' // 初始化發現編輯器不顯示,報“theme.js:1 Uncaught SyntaxError: Unexpected token <”這個錯 // 需要手動引入tinymce主題,在init({})方法里加theme: 'silver',沒用。 import 'tinymce/themes/silver/theme' cnpm install --save tinymce/theme

三. 使用示例

<template><div name='tinymce'><div class='title'><input placeholder="請輸入文章標題" v-model="title"/></div><div :class="{fullscreen:fullscreen}" class="tinymce-container editor-container"><textarea :id="tinymceId" class="tinymce-textarea"/><div class="editor-custom-btn-container"><editorImage color="var(--main-color)" class="editor-upload-btn" @successCBK="imageSuccessCBK" /></div></div><div class="publish"><span @click="submission">提交</span><span class="cancel">取消</span></div></div> </template><script> import plainBtn from '@/components/Buttons/plainBtn'import tinymce from 'tinymce/tinymce' // import 'tinymce/themes/mobile/theme' // import 'tinymce/themes/modern/theme' // 按示例初始化發現編輯器不顯示,報“theme.js:1 Uncaught SyntaxError: Unexpected token <”這個錯 // 需要手動引入tinymce主題,在init({})方法里加theme: 'silver',沒用。 import 'tinymce/themes/silver/theme'import editorImage from './components/editorImage' import plugins from './plugins' import toolbar from './toolbar'export default {name: 'Tinymce',components: { editorImage,plainBtn },props: {id: {type: String,default: function() {return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')}},value: {type: String,default: 'Editor me ...'},toolbar: {type: Array,required: false,default() {return []}},menubar: {type: String,default: 'file edit insert view format table'},height: {type: Number,required: false,default: 360}},data() {return {hasChange: false,hasInit: false,tinymceId: this.id,fullscreen: false,languageTypeList: {'zh': 'zh_CN'},title: ''}},computed: {language() {return this.languageTypeList[this.$store.getters.language]}},watch: {value(val) {if (!this.hasChange && this.hasInit) {this.$nextTick(() =>window.tinymce.get(this.tinymceId).setContent(val || ''))}},language() {this.destroyTinymce()this.$nextTick(() => this.initTinymce())}},mounted() {// 注: 在此需要傳入一個空對象this.initTinymce({})},activated() {this.initTinymce()},deactivated() {this.destroyTinymce()},destroyed() {this.destroyTinymce()},methods: {initTinymce() {const _this = this// window.tinymce.baseURL = '/tinymces/tinymce'window.tinymce.init({language: this.language,selector: `#${this.tinymceId}`,// 安裝之后,在 node_modules 中找到 tinymce/skins 目錄,然后將 skins 目錄拷貝到 public 的 tinymce 目錄下// 必須加 skin_url 否則會報錯skin_url: '/tinymce/skins/ui/oxide',height: this.height,body_class: 'panel-body ',object_resizing: false,toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,menubar: this.menubar,plugins: plugins,end_container_on_empty_block: true,powerpaste_word_import: 'clean',code_dialog_height: 450,code_dialog_width: 1000,advlist_bullet_styles: 'square',advlist_number_styles: 'default',imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],default_link_target: '_blank',link_title: false,nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugininit_instance_callback: editor => {if (_this.value) {editor.setContent(_this.value)}_this.hasInit = trueeditor.on('NodeChange Change KeyUp SetContent', () => {this.hasChange = truethis.$emit('input', editor.getContent())})},setup(editor) {editor.on('FullscreenStateChanged', (e) => {_this.fullscreen = e.state})}})},destroyTinymce() {const tinymce = window.tinymce.get(this.tinymceId)if (this.fullscreen) {tinymce.execCommand('mceFullScreen')}if (tinymce) {tinymce.destroy()}},setContent(value) {window.tinymce.get(this.tinymceId).setContent(value)},getContent() {window.tinymce.get(this.tinymceId).getContent()},imageSuccessCBK(arr) {console.log(arr)// 處理圖片上傳const _this = thisarr.forEach(v => {window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" src="${v}" >`)// tinyMCE.editors[0].setContent(`<img class="wscnph" src="${v}" >`)})},// 點擊 提交submission() {if(this.title.trim() === ''){this.$message({message: '請輸入文章標題',type: 'warning'})return}else if(tinyMCE.activeEditor.getContent().trim() === ''){this.$message({message: '請輸入文章內容',type: 'warning'})return}// console.log(tinyMCE.activeEditor.getContent())console.log(tinyMCE.editors[0].getContent())}} } </script><style scoped lang='scss'> .tinymce-container {position: relative;line-height: normal; } .tinymce-container>>>.mce-fullscreen {z-index: 10000; } .tinymce-textarea {visibility: hidden;z-index: -1; } .editor-custom-btn-container {position: absolute;right: 4px;top: 4px;/*z-index: 2005;*/ } .fullscreen .editor-custom-btn-container {z-index: 10000;position: fixed; } .editor-upload-btn {display: inline-block; }// 標題樣式 .title{& input {margin: 20px 0;height: 36px;line-height: 36px;width: calc(100% - 10px);outline: none;border-radius: 2px;border: 1px solid #D2D2D2;font-size: 16px;padding-left: 10px;}& input:hover {border: 1px solid var(--main-color);} } // 提交,取消按鈕 .publish{margin: 20px 0px; } .publish span{display: inline-block;height: 30px;line-height: 30px;padding: 0 10px;border:1px solid var(--main-color);color: var(--main-color);cursor: pointer;border-radius: 2px;background: #ffffff;margin-right: 20px; } .publish span:hover{background: var(--main-color);color:#ffffff; } .publish .cancel{border:1px solid var(--main-font-color);color: var(--main-font-color); } .publish .cancel:hover{background: var(--main-font-color);color:#ffffff; } </style> // plugins.jsconst plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']export default plugins // toolbar.js// 加粗 斜體 下劃線 刪除線 bold italic underline strikethroug // 居左 居中 居右 兩端對齊 alignleft aligncenter alignright alignjustify // 清除 格式選擇下拉框(縮進、行高) 段落選擇下拉框(段落、標題) 字體選擇下拉框 字號選擇下拉框 alignnone styleselect formatselect fontselect fontsizeselect // 剪切 復制 粘貼 cut copy paste // 減少縮進 增加縮進 outdent indent // 引用 撤銷 恢復 清除格式 blockquote undo redo removeformat // 下標 上標 網格線 插入的集合按鈕 水平線 無序列表 有序列表 subscript superscript visualaid insert hr bullist numlist // 添加和修改鏈接 去除鏈接格式 打開選中鏈接 添加和修改圖片 特殊符號 粘貼純文本 link unlink openlink image charmap pastetext // 打印 預覽 作者 print preview anchor // 分頁符 拼寫檢查 搜索 pagebreak spellchecker searchreplace // 代碼 全屏 插入時間 插入/編輯表格 刪除表格 單元格屬性 合并單元格 拆分單元格 在當前行之前插入一個新行 在當前行之后插入一個新行 刪除當前行 行屬性 剪切選定行 復制選定行 在當前行之前粘貼行 在當前行之后粘貼行 在當前列之前插入一個列 在當前列之后插入一個列 刪除當前列 code fullscreen insertdatetime table tabledelete tablecellprops tablemergecells tablesplitcells tableinsertrowbefore tabledeleterow tablerowprops tablecutrow tablecopyrow tablepasterowbefore tablepasterowafter tableinsertcolbefore tableinsertcolafter tabledeletecol // 在當前行之前插入一個新行 const toolbar = ['bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | alignnone styleselect formatselect fontselect fontsizeselect | cut copy paste | outdent indent | blockquote undo redo removeformat | subscript superscript visualaid insert hr bullist numlist | link unlink openlink image charmap pastetext | print preview anchor | pagebreak spellchecker searchreplace | code fullscreen insertdatetime table tabledelete tablecellprops tablemergecells tablesplitcells tableinsertrowbefore tabledeleterow tablerowprops tablecutrow tablecopyrow tablepasterowbefore tablepasterowafter tableinsertcolbefore tableinsertcolafter tabledeletecol ','hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']export default toolbar

四. 實現上傳圖片到七云牛

1.下載

cnpm install qiniu-js var qiniu = require('qiniu-js')// orimport * as qiniu from 'qiniu-js'

2. upToken的生成

一般都是后端給的,但是前端也可以實現,我們就在這里以前端的方法實現它

@/utils/quillToken.js

import CryptoJS from 'crypto-js'const utf16to8 = function (str) {/** Interfaces:* utf8 = utf16to8(utf16)* utf16 = utf8to16(utf8)*/var out, i, len, cout = ''len = str.lengthfor (i = 0 ; i < len; i++) {c = str.charCodeAt(i)if ((c >= 0x0001) && (c <= 0x007F)) {out += str.charAt(i)} else if (c > 0x07FF) {out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F))out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F))out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F))} else {out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F))out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F))}}return out }const base64encode = function (str) {/** Interfaces:* b64 = base64encode(data)* data = base64decode(b64)*/var out, i, lenvar c1, c2, c3len = str.lengthi = 0out = ''var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';while (i < len) {c1 = str.charCodeAt(i++) & 0xffif (i == len) {out += base64EncodeChars.charAt(c1 >> 2)out += base64EncodeChars.charAt((c1 & 0x3) << 4)out += '=='break}c2 = str.charCodeAt(i++)if (i == len) {out += base64EncodeChars.charAt(c1 >> 2)out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4))out += base64EncodeChars.charAt((c2 & 0xF) << 2)out += '='break}c3 = str.charCodeAt(i++)out += base64EncodeChars.charAt(c1 >> 2)out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4))out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6))out += base64EncodeChars.charAt(c3 & 0x3F)}return out }const base64decode = function (str) {var c1, c2, c3, c4var i, len, outlen = str.lengthi = 0out = ''var base64DecodeChars = new Array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1)while (i < len) {/* c1 */do {c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]} while (i < len && c1 == -1)if (c1 == -1) break/* c2 */do {c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff]} while (i < len && c2 == -1)if (c2 == -1) breakout += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4))/* c3 */do {c3 = str.charCodeAt(i++) & 0xffif (c3 == 61) return outc3 = base64DecodeChars[c3]} while (i < len && c3 == -1)if (c3 == -1) breakout += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2))/* c4 */do {c4 = str.charCodeAt(i++) & 0xffif (c4 == 61) return outc4 = base64DecodeChars[c4]} while (i < len && c4 == -1)if (c4 == -1) breakout += String.fromCharCode(((c3 & 0x03) << 6) | c4)}return out }const safe64 = function (base64) {base64 = base64.replace(/\+/g, '-')base64 = base64.replace(/\//g, '_')return base64 }const genUpToken = function () {// 參數 accessKey,secretKey,putPolicyvar accessKey = 'q5Oqby268SGSsWEBrkwGW9oQ20qzi2-fXl6Xm1zL'var secretKey = 'B7IQmIhh38gIHXEDccW8YN4Yath8vHpwf_aifeDW'var putPolicy = {'scope':'lyajuan','deadline':Math.round(new Date().getTime() / 1000) + 3600}// SETP 2var putPolicy1 = JSON.stringify(putPolicy)// SETP 3var encoded = base64encode(utf16to8(putPolicy1))// SETP 4var hash = CryptoJS.HmacSHA1(encoded, secretKey)var encodedSigned = hash.toString(CryptoJS.enc.Base64)// SETP 5var uploadToken = accessKey + ':' + safe64(encodedSigned) + ':' + encodedreturn uploadToken } export {utf16to8,base64encode,base64decode,safe64 ,genUpToken }

在需要生成 Token 的 .vue 文件中引入

import {genUpToken} from '@/utils/qiniuToken.js'

安裝:crypto-js 加密: https://www.jianshu.com/p/a47477e8126a

cnpm install crypto-js --save <template><div class="chooseImage" @click="choose"><svg-icon icon-class='upload'/>選擇圖片<input type="file" class="pickFile" @change="uploadFile" ref='chooseFile' title="上傳文件" multiple :style="{background:color,borderColor:color}"/></div> </template><script> // 引入七云牛js文件 import * as qiniu from 'qiniu-js' // 生成token的文件 import {genUpToken} from '@/utils/qiniuToken.js' import store from '@/store'export default {name: 'chooseImage',props: {color: {type: String,default: 'var(--main-color)'}},data() {return {fileList: []}},methods: {choose() {this.$refs.chooseFile.click()},// 上傳文件uploadFile($event) {store.dispatch('SetLoading',true)const file = $event.target.filesfor(var i=0;i<file.length; i++) {// 限制上傳文件的大小為200M// console.log(file[i])if (file[i].size > 209715200) {const cur_size = Math.floor(file.size * 100 / 1024 / 1024) / 100this.$notify.info({title: '消息',message: '上傳文件大小不得超過200M 當前文件' + cur_size + 'M '})return false}// this.showProgress = trueconst token = genUpToken();const fileName = file[i].nameconst suffix = fileName.substring(fileName.lastIndexOf('.')) // 后綴名const prefix = fileName.substring(0, fileName.lastIndexOf('.'))const key = prefix + token + suffix // 上傳文件名const observer = {next: response => {// 上傳進度'+Math.floor(response.total.percent)+'%'// total.loaded: number,已上傳大小,單位為字節。// total.total: number,本次上傳的總量控制信息,單位為字節,注意這里的 total 跟文件大小并不一致。// total.percent: number,當前上傳進度,范圍:0~100。this.uploadProgress = Math.floor(response.total.percent)if(this.uploadProgress == 100){this.$message('上傳成功!')}},error: err => {// 上傳失敗觸發this.$message.error('上傳失敗' + err.message)console.log(err)},complete: response => {this.uploadProgress = 0this.showProgress = falsethis.fileList.push('http://poxcqlozi.bkt.clouddn.com/' + response.key)}}// 可通過 subscription.unsubscribe() 停止當前文件上傳 const putExtra = {// 文件原文件名fname: '',// 用來放置自定義變量params: {},// 用來限制上傳文件類型,為 null 時表示不對文件類型限制// 限制類型放到數組里,如 mimeType: mimeType: ['image/png', 'image/jpeg', 'image/gif']}const config = {// 是否使用 cdn 加速域名,默認falseuseCdnDomain: true,// 上傳域名區域,當為 null 或 undefined 時,自動分析上傳域名區域region: qiniu.region.z1}/*file: Blob 對象,上傳的文件key: 文件資源名token: 上傳驗證信息,前端通過接口請求后端獲得config: object*/// 關鍵代碼let options = {quality: 0.92,noCompressIfLarger: true,maxWidth: 800,maxHeight: 618}qiniu.compressImage(file[i], options).then(data => {// data : {// dist: 壓縮后輸出的 blob 對象,或原始的 file,具體看下面的 options 配置// width: 壓縮后的圖片寬度// height: 壓縮后的圖片高度// }var observable = qiniu.upload(data.dist, key, token, putExtra, config)var subscription = observable.subscribe(observer) // 上傳開始});}this.$emit('successCBK', this.fileList)this.fileList = []}} } </script><style lang="scss" scoped> .chooseImage{text-align: center;background: var(--main-color);color: #ffffff;border-radius: 5px;padding: 5px 10px;& input{display: none;}& .svg-icon{margin-right: 10px;} } </style>

?

總結

以上是生活随笔為你收集整理的Vue 中使用 Tinymce 富文本编辑器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲乱仑| 亚洲最大在线视频 | 国产91免费在线观看 | 欧美撒尿777hd撒尿 | 国产裸体无遮挡 | 国产午夜在线一区二区三区 | 欧美激情视频在线播放 | 国产男女自拍 | 久久久久久久久久久国产 | 欧美性生活一区二区 | 久久精品99国产精品日本 | 亚洲精品美女在线观看 | 手机看片1024久久 | 黄色工厂这里只有精品 | 中文字幕一区二区三区av | 一久久久 | 久久亚洲综合 | 三级a视频 | 精品在线观看一区二区 | 激情五月开心婷婷 | 成人做爰www免费看视频网站 | 黄色片免费视频 | 亚洲欧美日韩国产精品 | 成人网免费| 24小时日本在线www免费的 | 看av的网址 | 美女赤身免费网站 | 日韩网站在线 | 黄色成人av在线 | 911福利视频 | 男女搞网站 | 国产无码精品一区二区 | 国产最新av | 乱lun合集小可的奶水 | 国产黄色激情视频 | 激情文学亚洲 | 884aa四虎影成人精品一区 | 亚洲视频h | 99久久久无码国产精品免费蜜柚 | 叼嘿视频在线免费观看 | 男女做激情爱呻吟口述全过程 | 国产永久在线 | 91在线无精精品白丝 | 国产91久久婷婷一区二区 | 动漫涩涩免费网站在线看 | 亚洲少妇一区二区 | 成人涩涩视频 | 91老师国产黑色丝袜在线 | 男人天堂综合网 | 337p粉嫩大胆噜噜噜亚瑟影院 | 少妇久久久久久久久久 | 国产精品综合一区二区 | 91免费看国产 | 六月激情婷婷 | 久久国产激情视频 | 亚洲第一天堂av | 亚洲www. | 暗呦丨小u女国产精品 | 特级西西人体4444xxxx | 国产区视频在线 | www.蜜桃av.com | 色xxxx| 日操操| 2018自拍偷拍 | sese国产 | 欧美aa | 黑丝少妇喷水 | 不卡的av电影 | 国产精品果冻传媒 | 久久99草 | 无码人妻精品一区二区三区99不卡 | a资源在线观看 | 色亚洲视频 | 中文字幕系列 | 97精品国产| 6090伦理 | 日韩激情四射 | 91日日夜夜 | 进去里在线观看 | 91精品国产91| 一区二区麻豆 | 成人影视免费观看 | 免费毛片一区二区三区 | 91羞羞网站 | 亚洲a人 | 黄色不卡av | 亚洲国产精一区二区三区性色 | 亚洲人视频在线观看 | 欧美美女啪啪 | 精品黑人一区二区三区国语馆 | 免费高清欧美大片在线观看 | 人妻 日韩 欧美 综合 制服 | 91亚洲视频 | 日韩a在线观看 | 看毛片视频 | 国产情侣呻吟对白高潮 | 国产极品在线观看 | 九色91popny蝌蚪 | 91新网站 |