实现自定义组件的 v-model数据绑定

This commit is contained in:
张珏敏 2019-07-21 02:14:57 +08:00
parent 9ac3606f83
commit fcd4673279
3 changed files with 58 additions and 31 deletions

View File

@ -4,7 +4,13 @@
<h1>vue-markdown编辑器组件</h1> <h1>vue-markdown编辑器组件</h1>
<a target="_blank" href="https://github.com/zhaoxuhui1122/vue-markdown">使用文档</a> <a target="_blank" href="https://github.com/zhaoxuhui1122/vue-markdown">使用文档</a>
<div class="content"> <div class="content">
<mark-down @on-paste-image="handlePasteImage" @on-save="save" :theme="theme" :initialValue="initialValue" :markedOptions="{baseUrl:'http://smalleyes.oss-cn-shanghai.aliyuncs.com/'}"></mark-down> <mark-down @on-paste-image="handlePasteImage"
@on-save="save"
v-model="value"
:theme="theme"
:interval="5000"
:initialValue="initialValue"
:markedOptions="{baseUrl:'http://smalleyes.oss-cn-shanghai.aliyuncs.com/'}"></mark-down>
</div> </div>
</div> </div>
</div> </div>
@ -12,10 +18,9 @@
<script> <script>
import MarkDown from './markdown/index' // import MarkDown from './markdown/index' //
// import MarkDown from "../build"; //
// import MarkDown from 'vue-meditor';
import doc from './doc'; import doc from './doc';
export default { export default {
name: "app", name: "app",
components: { components: {
@ -23,6 +28,7 @@
}, },
data() { data() {
return { return {
value: '',
initialValue: "", initialValue: "",
theme: 'OneDark' theme: 'OneDark'
}; };
@ -30,6 +36,7 @@
methods: { methods: {
save(res) { save(res) {
console.log(res); console.log(res);
this.value = 'edit ...'
}, },
handlePasteImage(res) { handlePasteImage(res) {
console.log(res); console.log(res);

View File

@ -116,7 +116,8 @@
<li v-for="(item,index) in indexLenth">{{index+1}}</li> <li v-for="(item,index) in indexLenth">{{index+1}}</li>
</ul> </ul>
<textarea <textarea
v-model="value" :value="values"
@input="$emit('input', $event.target.value)"
@keydown.tab="tab" @keydown.tab="tab"
@keyup.enter="enter" @keyup.enter="enter"
@keyup.delete="onDelete" @keyup.delete="onDelete"

View File

@ -23,8 +23,21 @@ marked.setOptions({
export default { export default {
name: 'markdown', name: 'markdown',
model: {
/**
* 自定义组件的 v-model
*/
prop: 'value',
event: 'input'
},
props: { props: {
initialValue: String, // 初始化内容 initialValue: String, // 初始化内容
value: {
type: String,
default() {
return ''
}
}, // 自定义组件的 v-model
theme: { // 默认主题 theme: { // 默认主题
type: String, type: String,
default: 'Light' default: 'Light'
@ -39,7 +52,7 @@ export default {
}, // 宽度 }, // 宽度
toolbars: { // 工具栏 toolbars: { // 工具栏
type: Object, type: Object,
default () { default() {
return {}; return {};
} }
}, },
@ -57,14 +70,14 @@ export default {
}, },
markedOptions: { markedOptions: {
type: Object, type: Object,
default () { default() {
return {}; return {};
} }
} }
}, },
data() { data() {
return { return {
value: '', // 输入框内容 values: '', // 输入框内容
timeoutId: null, timeoutId: null,
indexLenth: 100, indexLenth: 100,
html: '', html: '',
@ -119,7 +132,7 @@ export default {
}, },
methods: { methods: {
init() { init() {
this.value = this.initialValue; this.values = this.initialValue;
this.themeName = this.theme; this.themeName = this.theme;
this.editorHeight = this.height; this.editorHeight = this.height;
this.editorWidth = this.width; this.editorWidth = this.width;
@ -190,9 +203,9 @@ export default {
} }
this.lastInsert = initStr; this.lastInsert = initStr;
const point = this.getCursortPosition(); const point = this.getCursortPosition();
const lastChart = this.value.substring(point - 1, point); const lastChart = this.values.substring(point - 1, point);
const lastFourCharts = this.value.substring(point - 4, point); const lastFourCharts = this.values.substring(point - 4, point);
if (lastChart !== '\n' && this.value !== '' && lastFourCharts !== ' ') { if (lastChart !== '\n' && this.values !== '' && lastFourCharts !== ' ') {
const str = '\n' + initStr; const str = '\n' + initStr;
this.insertAfterText(str); this.insertAfterText(str);
} else { } else {
@ -205,7 +218,7 @@ export default {
if (document.selection) { if (document.selection) {
textDom.focus(); textDom.focus();
let selectRange = document.selection.createRange(); let selectRange = document.selection.createRange();
selectRange.moveStart('character', -this.value.length); selectRange.moveStart('character', -this.values.length);
cursorPos = selectRange.text.length; cursorPos = selectRange.text.length;
} else if (textDom.selectionStart || parseInt(textDom.selectionStart, 0) === 0) { } else if (textDom.selectionStart || parseInt(textDom.selectionStart, 0) === 0) {
cursorPos = textDom.selectionStart; cursorPos = textDom.selectionStart;
@ -233,7 +246,7 @@ export default {
textDom.value += value; textDom.value += value;
textDom.focus(); textDom.focus();
} }
this.$set(this, 'value', textDom.value); this.$set(this, 'values', textDom.value);
}, },
setCaretPosition(position) { // 设置光标位置 setCaretPosition(position) { // 设置光标位置
const textDom = this.$refs.textarea; const textDom = this.$refs.textarea;
@ -274,9 +287,9 @@ export default {
}, },
insertCode() { // 插入code insertCode() { // 插入code
const point = this.getCursortPosition(); const point = this.getCursortPosition();
const lastChart = this.value.substring(point - 1, point); const lastChart = this.values.substring(point - 1, point);
this.insertContent('\n```\n\n```'); this.insertContent('\n```\n\n```');
if (lastChart !== '\n' && this.value !== '') { if (lastChart !== '\n' && this.values !== '') {
this.setCaretPosition(point + 5); this.setCaretPosition(point + 5);
} else { } else {
this.setCaretPosition(point + 5); this.setCaretPosition(point + 5);
@ -284,9 +297,9 @@ export default {
}, },
insertStrong() { // 粗体 insertStrong() { // 粗体
const point = this.getCursortPosition(); const point = this.getCursortPosition();
const lastChart = this.value.substring(point - 1, point); const lastChart = this.values.substring(point - 1, point);
this.insertContent('****'); this.insertContent('****');
if (lastChart !== '\n' && this.value !== '') { if (lastChart !== '\n' && this.values !== '') {
this.setCaretPosition(point + 2); this.setCaretPosition(point + 2);
} else { } else {
this.setCaretPosition(point + 2); this.setCaretPosition(point + 2);
@ -294,9 +307,9 @@ export default {
}, },
insertItalic() { // 斜体 insertItalic() { // 斜体
const point = this.getCursortPosition(); const point = this.getCursortPosition();
const lastChart = this.value.substring(point - 1, point); const lastChart = this.values.substring(point - 1, point);
this.insertContent('**'); this.insertContent('**');
if (lastChart !== '\n' && this.value !== '') { if (lastChart !== '\n' && this.values !== '') {
this.setCaretPosition(point + 1); this.setCaretPosition(point + 1);
} else { } else {
this.setCaretPosition(point + 1); this.setCaretPosition(point + 1);
@ -304,9 +317,9 @@ export default {
}, },
insertBg() { // 背景色 insertBg() { // 背景色
const point = this.getCursortPosition(); const point = this.getCursortPosition();
const lastChart = this.value.substring(point - 1, point); const lastChart = this.values.substring(point - 1, point);
this.insertContent('===='); this.insertContent('====');
if (lastChart !== '\n' && this.value !== '') { if (lastChart !== '\n' && this.values !== '') {
this.setCaretPosition(point + 5); this.setCaretPosition(point + 5);
} else { } else {
this.setCaretPosition(point + 5); this.setCaretPosition(point + 5);
@ -314,9 +327,9 @@ export default {
}, },
insertUnderline() { // 下划线 insertUnderline() { // 下划线
const point = this.getCursortPosition(); const point = this.getCursortPosition();
const lastChart = this.value.substring(point - 1, point); const lastChart = this.values.substring(point - 1, point);
this.insertContent('<u></u>'); this.insertContent('<u></u>');
if (lastChart !== '\n' && this.value !== '') { if (lastChart !== '\n' && this.values !== '') {
this.setCaretPosition(point + 3); this.setCaretPosition(point + 3);
} else { } else {
this.setCaretPosition(point + 5); this.setCaretPosition(point + 5);
@ -324,9 +337,9 @@ export default {
}, },
insertOverline() { // overline insertOverline() { // overline
const point = this.getCursortPosition(); const point = this.getCursortPosition();
const lastChart = this.value.substring(point - 1, point); const lastChart = this.values.substring(point - 1, point);
this.insertContent('~~~~'); this.insertContent('~~~~');
if (lastChart !== '\n' && this.value !== '') { if (lastChart !== '\n' && this.values !== '') {
this.setCaretPosition(point + 2); this.setCaretPosition(point + 2);
} else { } else {
this.setCaretPosition(point + 2); this.setCaretPosition(point + 2);
@ -383,13 +396,13 @@ export default {
} }
}, },
onDelete() { // 删除时,以回车为界分割,如果数组最后一个元素为''时,将行一次插入的共嗯那个置为空,避免回车时再次插入 onDelete() { // 删除时,以回车为界分割,如果数组最后一个元素为''时,将行一次插入的共嗯那个置为空,避免回车时再次插入
const lines = this.value.split('\n'); const lines = this.values.split('\n');
if (lines[lines.length - 1] === '') { if (lines[lines.length - 1] === '') {
this.lastInsert = ''; this.lastInsert = '';
} }
}, },
exportMd() { // 导出为.md格式 exportMd() { // 导出为.md格式
saveFile(this.value, this.exportFileName + '.md'); saveFile(this.values, this.exportFileName + '.md');
}, },
importFile(e) { // 导入本地文件 importFile(e) { // 导入本地文件
const file = e.target.files[0]; const file = e.target.files[0];
@ -408,7 +421,7 @@ export default {
encoding: 'utf-8' encoding: 'utf-8'
}); });
reader.onload = () => { reader.onload = () => {
this.value = reader.result; this.values = reader.result;
e.target.value = ''; e.target.value = '';
} }
}, },
@ -445,21 +458,27 @@ export default {
this.previewImgSrc = src; this.previewImgSrc = src;
this.previewImgModal = true; this.previewImgModal = true;
} }
},
getValue() {
return this.value
} }
}, },
watch: { watch: {
initialValue() { initialValue() {
this.value = this.initialValue; this.values = this.initialValue;
}, },
value() { value() {
this.values = this.value
},
values() {
clearTimeout(this.timeoutId); clearTimeout(this.timeoutId);
this.timeoutId = setTimeout(() => { this.timeoutId = setTimeout(() => {
this.html = marked(this.value, { this.html = marked(this.values, {
sanitize: false, sanitize: false,
...this.markedOptions ...this.markedOptions
}); });
}, 30) }, 30)
this.indexLenth = this.value.split('\n').length; this.indexLenth = this.values.split('\n').length;
const height1 = this.indexLenth * 22; const height1 = this.indexLenth * 22;
const height2 = this.$refs.textarea.scrollHeight; const height2 = this.$refs.textarea.scrollHeight;
const height3 = this.$refs.preview.scrollHeight; const height3 = this.$refs.preview.scrollHeight;