聲明:此文僅為工作筆記,僅供參考,大神請繞道
背景
APP中需要內(nèi)嵌一個(gè)富文本編輯器,經(jīng)過一翻考究,最方便快捷的方法就是用webview去處理,所以就有了這篇工作筆記,JS部分的代碼可能會(huì)有不規(guī)范的情況,本人不是前端工程師還請多多指教
關(guān)于富文本編輯器,我用的是Quill-
需求
- 可以編輯富文本然后發(fā)送到Backend
- 獲取Backend返回的數(shù)據(jù),顯示在富文本編輯器中,進(jìn)行再編輯
-
需求分析
我們在JS里面需要完成兩個(gè)方法,一個(gè)是獲取富文本,一個(gè)是顯示富文本
我將他們理解成一個(gè)是get,一個(gè)是set
在完成JS的get/set后,在iOS項(xiàng)目中調(diào)用方法進(jìn)行交互-
JS部分
- 獲取編輯后的富文本
function getContents() { return editor.root.innerHTML }- 將獲取到的HTML顯示為富文本
這里需要講一下,我并沒有調(diào)用官方的setContents方法,因?yàn)锽ackend返回的是富文本轉(zhuǎn)換成HTML后的數(shù)據(jù),所以直接設(shè)置innerHTML就可以解決問題
function setHTMLs(html) { editor.root.innerHTML = html }到這里,對JS的加工就完成了,可以在運(yùn)行debug一下
-
與WKwebview交互
- iOS調(diào)用JS方法
open func evaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil)如果需要在WKWebView中調(diào)用JS方法,我們可以調(diào)用這個(gè)方法,JavaScriptString指的是JS方法名,這里傳的是字符串所以一定要確保方法名是正確無誤的
func getJSContents() { let js = "getContents()" webview.evaluateJavaScript(js) { (response, error) in guard let response = response as? String? else { return } print(response?.description ?? "") } }- JS調(diào)用iOS方法
網(wǎng)上有許多JS調(diào)用iOS的實(shí)現(xiàn)方法,這里采用的是比較簡單的,通過webkit的messageHandlers進(jìn)行傳遞,此處的trackAppEvent是iOS代碼中的名字,注意區(qū)分大小寫區(qū)分,如果需要傳參數(shù),需要對參數(shù)進(jìn)行拼接
HTML代碼 //無參數(shù) function clickImage() { webkit.messageHandlers.trackAppEvent.postMessage("null") } //有參數(shù) function clickImage() { propertiesJson = '{"dsaf":"dfdf", "content_id":"123456"}' webkit.messageHandlers.trackAppEvent.postMessage("eventNameACE" + "+" + propertiesJson) }iOS代碼 //無參數(shù) func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "trackAppEvent" { // your logic } } //有參數(shù) func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "trackAppEvent" { // 對參數(shù)進(jìn)行拼接 guard let messageBody = message.body as? String, let eventName = messageBody.components(separatedBy: "+").first, let propertiesJson = messageBody.components(separatedBy: "+").last else { return } trackAppEvent(eventName: eventName, propertiesJson: propertiesJson) } }
-
到這里整個(gè)功能需求也基本完成了,剩下就是與現(xiàn)有項(xiàng)目整合了
- Tips
- 如果添加超鏈接,一定要帶上https,否則編輯器會(huì)認(rèn)定url無效,設(shè)置不了地址的
以防用戶漏掉輸入https,可以在html文件里加入一下代碼
Link.sanitize = function(url) { // 處理邏輯 lowerCaseURL = url.toLowerCase() if (lowerCaseURL.startsWith('https')) { return lowerCaseURL } else { return 'https://' + lowerCaseURL } }- 如果發(fā)現(xiàn)toolbar選擇狀態(tài)有問題,請把版本升級到1.3.0以上,他們在這個(gè)版本fix了這個(gè)問題,但是有些嵌套的<p>便簽在1.1.6以后會(huì)無法顯示,所以可以使用覆蓋css的方法,將一下代碼加在style里面
@media (pointer: coarse) { .ql-snow.ql-toolbar button:hover:not(.ql-active), .ql-snow .ql-toolbar button:hover:not(.ql-active) { color: #444; } .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill, .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill, .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill, .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill { fill: #444; } .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke, .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke, .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter, .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter { stroke: #444; } } - 如果添加超鏈接,一定要帶上https,否則編輯器會(huì)認(rèn)定url無效,設(shè)置不了地址的
如果大家有其他解決方案歡迎留言交流
支持原創(chuàng),版權(quán)所有
未經(jīng)授權(quán)請勿轉(zhuǎn)載