前言:
首先,我這個文章不會寫非常詳細的代碼,但是我會把我目前博客開發的富文本編輯遇到的問題羅列出來。然後一點點的說明如何解決。說實在目前遇到的問題,已經想讓我放棄自己開發富文本了,真的是非誠勿擾。這個坑沒那麼簡單。(捂臉哭)
開發環境:vueCli3.X
一、HTML5的富文本
contentEditable="true"
這個屬性我不介紹了,不懂得自己百度
二、編寫頁面遇到的坑(點擊事件失去焦點)
網上大多數富文本編輯器都是iframe,很多成熟的富文本編輯器也是用的iframe。我個人不知道好壞,所以我直接用的div。也許後期會遇到無法解決的坑再換吧。
我不知道是不是我不是用的iframe的問題,但是每當我需要操作文字加粗都失敗,原因在於失去選區。
解決:a標籤和img標籤不會失去選區,改代碼。
上個人代碼:
<div class="dht-editor-operation">
<template v-for="(item, index) in operationList">
<a :key="index" @click="item.event" :title="item.title">
<img :src="item.iconUrl" :style="item.backgroundImg" alt="" />
</a>
</template>
</div>
三、我的文字不會加粗
我其實第一個寫的功能是顏色選擇器,沒寫很複雜就是用input的color屬性
第二功能是文字加粗。但是不會加粗。最後檢查得知是因爲,我自己有一個全局存在的樣式重置代碼。我把b標籤的默認樣式去除了。
到這個時候我都還是用的富文本自己的操作函數
document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
文檔地址:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand
這裏開始就踩坑很嚴重了。因爲樣式重置,我考慮到如果別人用我的東西,那麼也會這樣,那就是說我得避免這個情況。所以我選擇了另一條路,自己實現這些功能。當然不可能所有都自己實現,那就太累了,我也不是寫產品,給自己用的。
解決方式
使用:window.getSelection()和
Range()
參考教程:https://www.jianshu.com/p/5997a90aab64
MDN文檔:https://developer.mozilla.org/zh-CN/docs/Web/API/Selection
MDN文檔:https://developer.mozilla.org/zh-CN/docs/Web/API/Range
這裏文檔得好好看看,不然我下面的代碼你看不懂。
第一次解決方式
我用的代碼是這樣的(不要在意我這裏是改顏色,原理懂了就行)
代碼來自這篇博客:https://www.cnblogs.com/wyjs/articles/9733827.html
我個人一開始就是按這位的博客來寫的,很詳細
var selection = document.getSelection();
//取得選擇的文本
var selectionText = selection.toString();
//取得代表選區的範圍
var range = selection.getRangeAt(0);
//突出顯示選擇的文本
var span = document.createElement("span");
span.style.backgroundColor = "yellow";
range.surroundContents(span);
這種方式用的是range.surroundContents,意思是將你選中的文檔放在一個新的標籤中。
但是問題很嚴重
缺點:
1、無限的加入標籤中,會無限嵌套html元素(自己開發中看f12就懂了)
2、無法跨元素操作
比如這樣的,這種選擇是不能成功的,報錯。因爲他無法操作多個dom元素。
這時候已經巨坑了好吧。我原本以爲就和別人說的一樣,好簡單。你要是不考慮那麼多操作,不當初編輯器來操作確實簡單啊。
第二種解決方式(目前我測試沒什麼問題)
原理在於先刪後插,需要需要各位理解range選區(拖藍部分的代碼意思,仔細看文檔咯)
這裏還是會產生無限嵌套問題,我再找找方式,但是解決了跨元素選擇問題
代碼:
CursorAcquisition() {
let selection = window.getSelection();
let range = selection.getRangeAt(0);
return {
selection,
range
};
},
//取得代表選區的範圍
let range = this.CursorAcquisition().range;
//突出顯示選擇的文本
//let rangeClone = range.cloneRange();
//獲得選中區域dom袁術
let rangeText = range.extractContents();
//創建新的dom並且結合
let span = document.createElement("span");
span.appendChild(rangeText);
span.style.color = "red";
//先移除選中節點
range.deleteContents();
//再插入節點
range.insertNode(span);
這個代碼就能實現上述所有產生的問題。至少我暫時這麼認爲,大神則請指出。
好了第一篇踩坑到此結束,各位請先品嚐。後面我還會寫下一篇。因爲下一個坑我已經踩完了。心累。不寫博客我都不知道哪裏去發泄。網上的教程即好又缺斤少兩,少關鍵啊。
最後附上,我的顏色選擇器,不需要添加html元素。但是需要支持input color
//顏色選擇器
colorSelect() {
let input = document.createElement("input");
let that = this;
input.type = "color";
input.click();
input.addEventListener("input", watchColorPicker, false);
function watchColorPicker(event) {
//console.log(event.target.value);
let color = event.target.value;
that.operationList[0].backgroundImg = {
background: color
};
//移除監聽
input.removeEventListener("input", watchColorPicker, false);
input = "";
}
}
個人項目代碼都在git上面:
地址:https://github.com/ht-sauce/dream
本次富文本開發的路徑截圖,項目屬於持續完善,所以代碼比較亂。
項目富文本本地打開地址:http://localhost:8080/dht_blog/richTextEditor
項目的最後:
富文本肯定不是到這裏就結束了,但是從目前自己代碼的方式來寫,不亞於放棄一切,然後構建一個新的文本編輯器。考慮代碼重構,捨棄當前複雜的開發方式。從博文發出,到發現bug,再到重新百度富文本編輯器原理,經歷了3個小時。實在沒辦法,真不是兩三天能寫完的。
下面我將開後端nodejs項目,研究koa框架和阿里的egg框架。計劃開始搞自己的後端服務代碼了。畢竟一個博客不能只是前端頁面。但是,後端不會太深入,因爲要有所側重。因爲都是nodejs,所以js代碼方面不會荒廢。