vue中怎么把ui组件转成dom对象 codemirror

有个需求, 需要从codemirror绑定的value中 , 匹配正则 :{{}}, 把里面的内容换成dom, 比如tag标签,问题,类似于: https://stackoverflow.com/que...
比如value为:

data:()=({value:'sasas{{标签}}{{sada}}' })

最终效果图为:
image.png

codemirror提供的相关api为:
image.png

此问题有两个难点:
一是replacedWith需要dom对象, 而vue并没有提供把ui组件转dom对象的api, react就有这种api : this.$createElement, vue的render函数中,也有提供createElement参数, 后来了解到vue也有同名api且挂载在原型上,以便在render函数外使用, 但vue的, return的结果里找不到dom对象, 徒有虚名的api
二是: 正则匹配到的{{}},是一个数组,意味着每次循环数组,需要传入新的dom.
解决思路: 1,只能考虑使用原生的document.createElement(), 把ui组件拆成原生dom结构,但是也会有一个问题,新建的oDiv绑定不了事件

  createTagNode(innerText) {
      const oDiv = document.createElement('div')
      oDiv.innerHTML = `<span class="tag is-primary" style="cursor:pointer">
                        <span>${innerText}</span>
                    </span>`

      oDiv.addEventListener('click', this.onTagClick) // 这里绑定不上事件,不知道为什么
      return oDiv.childNodes[0]
    },

2, 把dom模板写在template中, 这样可以直接写ui组件,使用refs,
但是循环时,用的是同一个ref, 会有对象的引用问题,
目前解决方法是,找到ref,使用node.cloneNode,再手动绑定上事件
(cloneNode不会克隆事件,所以事件没办法写在template里)

问题已解决,提供给大家一个思路

<template>
    <b-tag ref="tag" class="is-primary" style="display:none" />
</template>
methods:{
    tagCodeMirror(cursorPosition) {
      const positions = this.getTagPositions(this.code)
      const baseTagNode = this.$refs.tag.$el

      const tagOps = () => {
        positions.forEach((pos, index) => {
          const dupNode = baseTagNode.cloneNode(true)
          dupNode.style.display = 'inline-flex'
          dupNode.addEventListener('click', this.onTagClick)
          dupNode.childNodes[0].innerText = pos.tag
          this.codeMirror.markText({
            line: pos.line,
            ch: pos.start
          }, {
            line: pos.line,
            ch: pos.stop
          }, {
           replacedWith:dupNode // replacedWith:this.createTagNode(pos.tag),
            handleMouseEvent: true
          })
        })
      }

      this.$nextTick(() => {
        tagOps
        this.codeMirror.operation(tagOps)
        this.codeMirror.setCursor(cursorPosition)
      })
    },
}
  
待解决 悬赏分:10 - 离问题结束还有 53天13小时44分40秒
反对 0举报 0 收藏 0

我来回答

回答5