<续> 简易版本富文本编辑器

522 阅读2分钟
  • 在之前的基础上,添加鼠标选中文字,编辑框失焦,再点击加粗的功能

实现思路:编辑失焦时,获取当前的 range 对象,点击加粗按钮时,根据 range 对象提供的 setStart setEnd 等一些核心 API 以及 selection对象的addRange配合选中之前的文字,从而达到效果。

刚开始对以上提到的 API 不太了解,想的是,把当前这个选中状态存一份,那失焦的时候就不愁拿不到啦,emmm ....,网上去各种搜索,看 MDN 等,知道 range 对象是会保存上一次的选中状态的,那就好办啦!但是但是,失焦事件在内容区content组件中,而功能实现在toolbar组件中,这不就是兄弟组件之间的传值吗???突然想念 vuex 和 event bus ...,这里没有咋办呢???不慌,想想办法!传值有很多中办法嘛!H5的本地存储(localStoragesessionStorage)等,全局变量,或者写个发布订阅...

我就先图个方便,把状态放到 window 下面了 ^_^

  • 首先不管是失焦加粗还是直接选中文字加粗,都要获取通过 selectionrange 这两个对象配合来获取鼠标选中文字,所以把这样方法封装一下为 getSelectObj ,返回当前的 range 对象和选中的文本信息:(其中的 createSelection 是一个考虑了兼容性的创建 selection 对象的方法)
getSelectObj = (): object => {
  const selObj:Selection = createSelection()

  const rangeObj = selObj.getRangeAt(0) // range 被赋予一个 Range 对象
  const { collapsed } = rangeObj

  return {
    rangeObj,
    isSelected: collapsed ? false : true,
    txt: selObj.toString(),
  }
}
  • 在 content 组件中定义并注册编辑框的失焦事件,他所做的就是获取当前选中状态,然后把它保存到 window

  • 在 toolbar 组件中的 funcBtnEvent 做一些改变:

    • 如果选中文字,立即点加粗,就直接取当前状态,继而完成加粗功能
    • 如果是失焦状态下点击了加粗,那就要从全局变量 window 下获取刚刚选中的状态,从其中的 range 对象中获取 startOffsetendOffset ,然后利用 selectionaddRange 将状态自动选取,继而完成加粗功能,核心代码如下:
    const win: any = window
    const { startOffset, endOffset } = win.xxxx.rangeObj
    const contentElem = document.getElementById('editContentIdName') as Element
    const textNode = contentElem.firstChild as Node
    const selection:Selection = createSelection()
    const rangeObj:Range = new Range()
    rangeObj.setStart(textNode, startOffset)
    rangeObj.setEnd(textNode, endOffset)
    selection.removeAllRanges()		// 所有内容变为非选取状态
    selection.addRange(rangeObj)	// 然后自动选取某个区域
    
  • 一点小总结:遇事不要慌,完全没有思路的时候,去看看博客,官网的 API 说明,可能会有点想法,慢慢地就上道了!

  • 其实还是有 bug,接着完善吧 ..... 代码仓库