修改大佬的代码,原来是可以修改参数的,我这边要求不能手动修改参数
增加删除功能,自定义添加参数,
反向解析公式没整好,有大佬会的,可以修改一下,联系一下我,不胜感激
原文 用vue手写一个公式组件 - SegmentFault 思否
后来进行了改进 功能进行了简化 ,可详见vue公式编辑器 加强版(简化版)_你好,我叫A某人的博客-****博客_vue公式编辑器
<template>
<div >
<h1>formulaPage</h1>
<p>{{ formulaStr }}</p>
<div class="btnGroup">
<!-- <button @click="mouseRange($event)">获取光标</button> -->
<button @click="getFormula">获取公式</button>
<button
@click="
parsingFormula(
'#字段1#+plus(#字段1#+#字段3#)*abs(#字段4#/#字段2#)'
)
"
>
反向解析公式
</button>
</div>
<!-- <div class="tab">
<div class="tit">添加公式</div>
<ul>
<li @click="addItem($event, 2)">plus()</li>
<li @click="addItem($event, 2)">abs()</li>
</ul>
</div> -->
<div class="tab">
<div class="tit">添加字段</div>
<ul>
<li @click="addItem($event, 1)">字段1</li>
<li @click="addItem($event, 1)">字段2</li>
<li @click="addItem($event, 1)">字段3</li>
<li @click="addItem($event, 1)">字段4</li>
</ul>
</div>
<div class="tab">
<div class="tit">数字</div>
<ul>
<li @click="addItem($event, 3)">1</li>
<li @click="addItem($event, 3)">2</li>
<li @click="addItem($event, 3)">3</li>
<li @click="addItem($event, 3)">4</li>
<li @click="addItem($event, 3)">5</li>
<li @click="addItem($event, 3)">6</li>
<li @click="addItem($event, 3)">7</li>
<li @click="addItem($event, 3)">8</li>
<li @click="addItem($event, 3)">9</li>
<li @click="addItem($event, 3)">0</li>
</ul>
</div>
<div class="tab">
<div class="tit">数学运算符</div>
<ul>
<li @click="addItem($event, 3)">+</li>
<li @click="addItem($event, 3)">-</li>
<li @click="addItem($event, 3)">*</li>
<li @click="addItem($event, 3)">/</li>
<li @click="addItem($event, 3)">(</li>
<li @click="addItem($event, 3)">)</li>
<li @click="remove()">del</li>
</ul>
</div>
<!-- 公式编辑区域 -->
<div
class="formulaView"
ref="formulaView"
@click="recordPosition"
@keyup="editEnter($event)"
@copy="copy($event)"
@paste="paste($event)"
contentEditable="false "
></div>
</div>
</template>
<script>
export default {
name: "formulaPage",
data: function () {
return {
// 公式字符串
formulaStr: "",
// 公式编辑器最后光标位置
formulaLastRange: null,
};
},
methods: {
// 获取公式
getFormula: function () {
var nodes = this.$;
var str = "";
for (let i = 0; i < ; i++) {
var el = nodes[i];
if ( == "SPAN") {
// (el);
str += "#" + () + "#";
} else if ( == "B") {
// (el);
str += () ;
}else {
// ();
str += ? () : "";
}
}
// (str);
= str;
},
// 点选时记录光标位置
recordPosition: function () {
// 保存最后光标点
= ().getRangeAt(0);
},
// 添加字段 type 1 字段 2 公式 3 数字或者数字运算符
addItem: function (e, type) {
// 当前元素所有子节点
var nodes = this.$;
// 当前子元素偏移量
var offset =
&& ;
// 当前光标后的元素
var nextEl =
&& ;
// 创建节点片段
var fd = ();
// 创建字段节点 空白间隔节点 公式节点
var spanEl = ("span");
("contentEditable", false);
// 标识为新添加元素 用于定位光标
("new-el", true);
= ;
var spanEl2 = ("b");
// 标识为新添加元素 用于定位光标
("new-el", true);
= ;
var empty = (" ");
var formulaEl = (
" " + + " "
);
// 区分文本节点替换 还是父节点插入
if (nextEl && != "formulaView") {
// 获取文本节点内容
var content = ;
// 添加前段文本
(
((0, offset) + " ")
);
(type == 1 ? spanEl : formulaEl);
// 添加后段文本
(
(" " + (offset))
);
// 替换节点
this.$(fd, nextEl);
// 添加前段文本
// (empty);
// (type == 1 ? spanEl : spanEl2);
// (empty);
// // 如果有偏移元素且不是最后节点 中间插入节点 最后添加节点
// if ( && > offset) {
// this.$(
// fd,
// nextEl && != "formulaView"
// ? nextEl
// : nodes[offset]
// );
// } else {
// this.$(fd);
// }
} else {
// 添加前段文本
(empty);
(type == 1 ? spanEl : spanEl2);
(empty);
// 如果有偏移元素且不是最后节点 中间插入节点 最后添加节点
if ( && > offset) {
this.$(
fd,
nextEl && != "formulaView"
? nextEl
: nodes[offset]
);
} else {
this.$(fd);
}
}
// 遍历光标偏移数据 删除标志
var elOffSet = 0;
for (let i = 0; i < ; i++) {
let el = nodes[i];
// (el, == 'SPAN'&&('new-el'));
if ( == "SPAN" && ("new-el")) {
elOffSet = i;
("new-el");
}
if ( == "B" && ("new-el")) {
elOffSet = i;
("new-el");
}
}
// 创建新的光标对象
var range = ();
// 光标对象的范围界定
(
type == 1 ? this.$ : formulaEl
);
// 光标位置定位
(
type == 1
? this.$
: type == 2
? formulaEl
: formulaEl,
type == 1
? elOffSet + 1
: type == 2
? - 2
: - 1
);
// 使光标开始和光标结束重叠
(true);
// 清除选定对象的所有光标对象
().removeAllRanges();
// 插入新的光标对象
().addRange(range);
// 保存新光标
// ();
},
remove() {
var formulaView = ("formulaView");
(formulaView);
();
},
// 复制
copy: function (e) {
// 选中复制内容
();
//
var selContent = ().toString().split("\n")[0];
// 替换选中内容
("text/plain", selContent);
},
// 输入回车
editEnter: function (e) {
// (e);
();
// return '<br/>';
// return
if ( == 13) {
// 获取标签内容 并把多个换行替换成1个
var content = this.$(
/(<div><br><\/div>){2,2}/g,
"<div><br></div>"
);
// debugger;
// 记录是否第一行回车
var divCount = this.$("div");
// var tE = this.$('div');
// (this.$);
// (this.$("div"));
// 获取当前元素内所有子节点
var childNodes = this.$;
// 记录当前光标子节点位置
var rangeIndex = 0;
for (let i = 0; i < ; i++) {
var one = childNodes[i];
if ( == "DIV") {
rangeIndex = i;
}
}
// (rangeIndex);
// debugger;
// (content);
// 如果有替换则进行光标复位
if ( >= 1) {
// 替换回车插入的div标签
content = (
/<div>|<\/div>/g,
function (word) {
// (word);
if (word == "<div>") {
// 如果是第一行不在替换br
return > 1 ? " " : " <br>";
} else if (word == "</div>") {
return " ";
}
}
);
// 更新替换内容,光标复位
this.$ = content;
// 创建新的光标对象
var range = ();
// 光标对象的范围界定为新建的表情节点
(this.$);
// 光标位置定位在表情节点的最大长度
(
this.$,
rangeIndex + ( > 1 ? 0 : 1)
);
// 使光标开始和光标结束重叠
(true);
// 清除选定对象的所有光标对象
().removeAllRanges();
// 插入新的光标对象
().addRange(range);
}
}
// 保存最后光标点
= ().getRangeAt(0);
},
// 获取粘贴事件
paste: function (e) {
();
// var txt=();
// (e, ());
return "";
},
// 公式反向解析
parsingFormula: function (formulaStr) {
// 渲染视口
var view = this.$;
// 反向解析公式
var str = (/#(.+?)#/g, function (word, $1) {
// (word,$1);
return "<span contentEditable='false'>" + $1 + "</span>";
});
// (str,);
= str;
// this.$(fd);
// 创建新的光标对象
var range = ();
// 光标对象的范围界定为新建的表情节点
(view);
// 光标位置定位在表情节点的最大长度
(view, );
// 使光标开始和光标结束重叠
(true);
// 清除选定对象的所有光标对象
().removeAllRanges();
// 插入新的光标对象
().addRange(range);
// 保存新光标
// ();
},
},
};
</script>
<style lang="less">
#formulaPage {
> .tab {
> ul {
&:after {
content: "";
display: table;
clear: both;
}
> li {
margin-right: 20px;
float: left;
padding: 0 10px;
height: 25px;
line-height: 25px;
border-radius: 5px;
border: 1px solid #000;
}
}
}
> .formulaView {
margin-top: 20px;
min-height: 100px;
width: 300px;
padding: 5px;
border: 2px solid #000;
resize: both;
overflow: auto;
line-height: 25px;
span {
user-select: none;
display: inline-block;
margin: 0 3px;
height: 20px;
line-height: 20px;
letter-spacing: 2px;
background: #aaa;
border-radius: 3px;
white-space: nowrap;
color: red;
&:first-child {
margin-left: 0;
}
}
}
}
</style>