electron+vue實(shí)現(xiàn)div contenteditable截圖功能
最近在學(xué)習(xí)基于electron + electron-vue開發(fā)聊天客戶端項目時,需要用到編輯器插入表情功能。一般通過input或textarea也能實(shí)現(xiàn),通過插入[笑臉]、(:12 這些標(biāo)簽,展示的時候解析標(biāo)簽就行。
如下圖效果:
在網(wǎng)上找到的jq插件實(shí)現(xiàn)在textarea光標(biāo)處插入表情符標(biāo)簽
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col col-sm-12">
<button class="btn btn-success" data-emoj="[笑臉]">[笑臉]</button>
<button class="btn btn-success" data-emoj="[奮斗]">[奮斗]</button>
<button class="btn btn-success" data-emoj="[:17]">[:17]</button>
</div>
<div class="col col-sm-12">
<textarea class="form-control" id="content" rows="10"></textarea>
</div>
</div>
</div>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
(function ($) {
$.fn.extend({
insertEmojAtCaret: function (myValue) {
var $t = $(this)[0];
if (document.selection) {
this.focus();
sel = document.selection.createRange();
sel.text = myValue;
this.focus();
} else if ($t.selectionStart || $t.selectionStart == '0') {
var startPos = $t.selectionStart;
var endPos = $t.selectionEnd;
var scrollTop = $t.scrollTop;
$t.value = $t.value.substring(0, startPos) + myValue + $t.value.substring(endPos, $t.value.length);
this.focus();
$t.selectionStart = startPos + myValue.length;
$t.selectionEnd = startPos + myValue.length;
$t.scrollTop = scrollTop;
} else {
this.value += myValue;
this.focus();
}
}
});
})(jQuery);
$("button").on("click", function() {
$("#content").insertEmojAtCaret($(this).attr("data-emoj"));
});
</script>
</body>
</html>
可是這種方法并不是我想要的類似微信編輯框插入表情效果。
如是就想到了div模擬 設(shè)置 contenteditable="true" 實(shí)現(xiàn)富文本編輯器效果,這種方法是可以實(shí)現(xiàn),不過在vue中不能綁定v-model,最后參考一些技術(shù)貼實(shí)現(xiàn)了這個功能,一頓操作下來采坑不少,于是就做一些分享記錄吧。
vue中通過給div添加contenteditable=true屬性實(shí)現(xiàn)富文本功能
實(shí)現(xiàn)方式:
單獨(dú)聲明一個vue組件,chatInput.vue,通過監(jiān)聽數(shù)據(jù)變化并返回父組件。
1、父組件添加v-model
<template> ... <chatInput ref="chatInput" v-model="editorText" @focusFn="handleEditorFocus" @blurFn="handleEditorBlur" /> </template>
import chatInput from './chatInput'
export default {
data () {
return {
editorText: '',
...
}
},
components: {
chatInput,
},
...
}
2、v-model中傳入的值在子組件prop中獲取
export default {
props: {
value: { type: String, default: '' }
},
data () {
return {
editorText: this.value,
...
}
},
watch: {
value() {
...
}
},
}
3、通過監(jiān)聽獲取到的prop值,并將該值賦值給子組件中的v-html參數(shù),雙向綁定就ok了。
chatInput.vue組件
<!-- vue實(shí)現(xiàn)contenteditable功能 -->
<template>
<div
ref="editor"
class="editor"
contenteditable="true"
v-html="editorText"
@input="handleInput"
@focus="handleFocus"
@blur="handleBlur">
</div>
</template>
<script>
export default {
props: {
value: { type: String, default: '' }
},
data () {
return {
editorText: this.value,
isChange: true,
}
},
watch: {
value() {
if(this.isChange) {
this.editorText = this.value
}
}
},
methods: {
handleInput() {
this.$emit('input', this.$el.innerHTML)
},
// 清空編輯器
handleClear() {
this.$refs.editor.innerHTML = ''
this.$refs.editor.focus()
},
// 獲取焦點(diǎn)
handleFocus() {
this.isChange = false
this.$emit('focusFn')
},
// 失去焦點(diǎn)
handleBlur() {
this.isChange = true
this.$emit('blurFn')
},
/**
* 光標(biāo)處插入內(nèi)容
* @param html 需要插入的內(nèi)容
*/
insertHtmlAtCaret(html) {
let sel, range;
if(!this.$refs.editor.childNodes.length) {
this.$refs.editor.focus()
}
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
let el = document.createElement("div");
el.appendChild(html)
var frag = document.createDocumentFragment(), node, lastNode;
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
this.handleInput()
}
}
}
</script>
<style>
</style>
組件功能已經(jīng)親測,直接一次性拿走使用。
以下是一些參考:
1、vue官方描敘, 自定義組件的v-model:
一個組件上的 v-model 默認(rèn)會利用名為 value 的 prop 和名為 input 的事件,v-model的值將會傳入子組件中的prop
https://cn.vuejs.org/v2/guide/components-custom-events.html#自定義組件的-v-model
2、vue中div可編輯光標(biāo)處插入內(nèi)容
http://chabaoo.cn/article/177989.htm
http://chabaoo.cn/article/146257.htm


electron+vue中實(shí)現(xiàn)截圖功能
主要使用的是微信截圖dll,通過node執(zhí)行即可
screenShot() {
return new Promise((resolve) => {
const { execFile } = require('child_process')
var screenWin = execFile('./static/PrintScr.exe')
screenWin.on('exit', function(code) {
let pngs = require('electron').clipboard.readImage().toPNG()
let imgData = new Buffer.from(pngs, 'base64')
let imgs = 'data:image/png;base64,' + btoa(new Uint8Array(imgData).reduce((data, byte) => data + String.fromCharCode(byte), ''))
resolve(imgs)
})
})
},
總結(jié)
以上所述是小編給大家介紹的electron+vue實(shí)現(xiàn)div contenteditable截圖功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
Vue2.x配置路由導(dǎo)航守衛(wèi)實(shí)現(xiàn)用戶登錄和退出
之前在Vue的學(xué)習(xí)中通過路由導(dǎo)航守衛(wèi)控制實(shí)現(xiàn)了用戶登錄模塊的功能,本文基于Vue2.x進(jìn)行實(shí)現(xiàn),在此將實(shí)現(xiàn)過程進(jìn)行記錄與總結(jié),感興趣的可以了解一下2021-08-08
vue.js將時間戳轉(zhuǎn)化為日期格式的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue.js將時間戳轉(zhuǎn)化為日期格式的實(shí)現(xiàn)代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-06-06
vue elementUI 表單校驗的實(shí)現(xiàn)代碼(多層嵌套)
這篇文章主要介紹了vue elementUI 表單校驗的實(shí)現(xiàn)代碼(多層嵌套),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
Vue基礎(chǔ)學(xué)習(xí)之項目整合及優(yōu)化
這篇文章主要給大家介紹了關(guān)于Vue基礎(chǔ)學(xué)習(xí)之項目整合及優(yōu)化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06

