vue中实现div可编辑,并插入指定元素,样式

前言:

        vue中实现一个既可以编辑内容,有可以动态编辑内容插入一个带有样式的内容,改变默认内容后,这个样式消失的效果,这里来整理下调研与解决实现问题之路。

实现最终效果:图2为默认内容

1、可以光标点击任意地方,然后点击按钮,插入带有span的内容

2、默认span是有样式,但是一旦内容与我们的默认内容不同就取消样式

3、获取的时候,可以拿到带有标签的内容,也可以拿到纯文本内容

4、默认内容,支持带标签内容

vue中实现div可编辑,并插入指定元素,样式_第1张图片

 vue中实现div可编辑,并插入指定元素,样式_第2张图片

 探索之路:

1、刚开始从网上查找了很多资料,但是都有不同的缺陷,下面是我根据网上资料实现的效果

1)封装一个  inputDiv.vue





2)父级中使用:

结果:{{editInputVal}}-{{mrEditInputVal}}
    {{addBtnText}}
    
js部分:

import inputDiv from './components/inputDiv'
components: {
    inputDiv,
  },
data() {
    return {
      mrEditInputVal:'',
      editInputVal:'',
      addBtnText:'插入员工昵称',
      abc:'',
      teamContent: "

幸福 人和 测试增加数据 在加1111222

" } }, methods: { onblurChange(val){ // debugger }, getFocus(val){ // debugger }, onPaste(val){ // debugger }, contentedInput(val){ if(val.indexOf('') let arr3 = arr2[0].split('>') let arr4 = arr3[1].split('<') if(arr4[0] != this.addBtnText){ let val = this.editInputVal = arr1[0]+arr4[0]+arr2[1] this.mrEditInputVal = JSON.parse(JSON.stringify(val)) return } } this.editInputVal = val }, contentedKeySpace(val){ // debugger }, contentedKeyEnter(val){ // debugger }, changeKeyup(val){ // debugger }, addStrBtnFun(){ let index = this.getCursorPosition() let insertStr = (soure,start, newStr) => { return soure.slice(0, start) + newStr + soure.slice(start) } let newStr = insertStr(this.editInputVal,index,''+this.addBtnText+'') this.mrEditInputVal = newStr }, getCursorPosition(){ const selection = window.getSelection(); const range = selection.getRangeAt(0); const cursorPos = range.startOffset; return cursorPos },

3)最终实现效果

1、实现了不同内容的时候可以正常监听

2、点击按钮,可以正常插入并修改样式

缺点:

1、点击多个插入,位置有问题

2、每次输入第二个字符的时候,光标都移动到了最后一位

vue中实现div可编辑,并插入指定元素,样式_第3张图片

 2、继续努力实现效果,效果图实现步骤:

注意:

        不能实时获取它的数据,它的光标位置会出现问题,目前官方提供的方法,默认是回到第一个,可以修改到回到最后一个,但是我们如果是中间输入内容,光标会异常,故而不建议实时获取数据

1、div+contenteditable="true"  来实现div的可编辑,v-html来实现对他默认值的修改

 

2、初始化方法

// 这一步是保留住edit编辑框中的选区的范围对象。否则失焦后,getSelection()方法返回的选区对象已经不再是编辑框了,已经获取不到编辑框中的范围对象了。

initEditFun(){
      editDiv = document.getElementsByClassName("edit")[0]

      editDiv.addEventListener("blur", () => {
        // 这一步是保留住edit编辑框中的选区的范围对象。否则失焦后,getSelection()方法返回的选区对象已经不再是编辑框了,已经获取不到编辑框中的范围对象了。
        range = window.getSelection().getRangeAt(0)
      })

    },

3、点击按钮时候,给可编辑区域中增加一个带有颜色的span

记得在你的功能样式中添加,可在app.vue,也可以在你项目其他公共区域

.selColor{
  color: red;
}
点击事件:

window.getSelection()  获取他的光标选取

 selection.selectAllChildren(editDiv) // selectAllChildren把指定元素的所有子元素设为选中区域,并取消之前的选中区域。不包括node节点本身。

 selection.collapseToEnd()   //Selection.collapseToEnd() 方法的作用是取消当前选区,并把光标定位在原选区的最末尾处,如果此时光标所处的位置是可编辑的,且它获得了焦点,则光标会在原地闪烁。(想查看更多属性,点击链接,去看官方api)

range = window.getSelection().getRangeAt(0) // 保存当前编辑框的选区对象

 let sel = window.getSelection()
range.insertNode(span)  // insertNode方法,在range选区开头插入一个节点

 sel.removeAllRanges()  //removeAllRanges方法:删除之前的所有选区。
sel.addRange(range)    // 这一步就是添加当前区域对象到选区对象中

addStrBtnFun(){
      const span = document.createElement("span")
      span.innerText = this.addBtnText
      span.className = 'selColor'
      // 如果在页面刷新再点击编辑框之前就点击了按钮,此时range中并没有选区范围对象
      if (range === "") {
        let selection = window.getSelection()
        selection.selectAllChildren(editDiv) // selectAllChildren把指定元素的所有子元素设为选中区域,并取消之前的选中区域。不包括node节点本身。
        /*
          Selection.collapseToEnd() 方法的作用是取消当前选区,并把光标定位在原选区的最末尾处,如果此时光标所处的位置是可编辑的,且它获得了焦点,则光标会在原地闪烁。
          以上selectAllChildren方法,将div中子节点全部选中,collapseToEnd方法将选中区域取消,并且将光标定位到原区的末尾。
        */
        selection.collapseToEnd()
        range = window.getSelection().getRangeAt(0) // 无论哪一步都需要保存当前编辑框的选区对象
      }
      let sel = window.getSelection()
      range.insertNode(span) // insertNode方法,在range选区开头插入一个节点
      /*
      removeAllRanges方法:删除之前的所有选区。
      这一步的意义:因为当我们点击其他区域时,选区对象已经改变,不再是编辑框中的选区对象,这时候我们接下来的操作都不会符合我们想象中的样子
     */
      sel.removeAllRanges()
      sel.addRange(range) // 这一步就是添加当前区域对象到选区对象中,所以选区对象会再次指向编辑框中的选区,不会出现别的错误操作。
      sel.collapseToEnd()
    },

4、我们修改span内容,让他的样式消失方法

1)首先要用到  他的@input事件
@input="editInput"
 editInput(e) {
      console.log(e);
      console.log(e.target.children);
},
这是它的默认拿到的数据 

vue中实现div可编辑,并插入指定元素,样式_第4张图片

如果插入span以后,可以看到e.target.children多了span信息

vue中实现div可编辑,并插入指定元素,样式_第5张图片

 拿我们页面的edit  div下面所有的span,如果哪个内容被改变,就去掉它的class
editInput(e) {
      console.log(e);
      console.log(e.target.children);
      if(e.target.children.length>0){
        this.editSpanClass()
      }
    },
    editSpanClass(){
      let spanAll = document.querySelectorAll('.edit span')
      spanAll.forEach(item=>{
        if(item.innerHTML != this.addBtnText){
          item.className = ''
        }
      })
    },

源码分享:tinymce.vue





你可能感兴趣的:(vue.js,javascript,前端,光标位置,可编辑div)