vue解析展示有组件的字符串

vue解析展示有组件的字符串

今天是()月()号?

对上面的文字做成填空题的形式,括号能够进行输入

1.解析字符串

let str = '今天是(_)月(_)号?'
let reg = /(\(_*\))/g
let res = Array.from(str.match(reg))
res.forEach((item, index) => {
    // 这里就是双向数据绑定的答案对象,有由于不知道有几个空采用$set的形式就行设置
	this.$set(this.blankAnswerObj, `blank_${index}`, '')
})

2.递归处理字符串

注意replace替换字符串只会替换匹配到的第一个,所以这里需要使用递归

  let createDivArr = str.split('(___)').map(item => `<div>${item}</div>`)
  let HTMLOhterStr = createDivArr.join('(___)')
  this.modelNumberByReg = res.length
  let count = 0
  let finalStr
  let fn = (content, count) => {
    if (count > res.length) {
      finalStr = content
      return
    }
    let htmlStr = `<div class="blank-item">(</><el-input v-model="blankAnswerObj.blank_${count}" clearable size="small" @blur="handleEmit('${count}')"></el-input>)</div>`
    let newContent = content.replace(/(\(_*\))/, htmlStr)
    count++
    fn(newContent, count)
  }
  fn(HTMLOhterStr, count)
  let result = `<div class="ques-component">${finalStr}</div>`

3.页面展示

<div v-html="str"></div>

由于是存在html标签的字符串,我们解析在页面上使用v-html

但是注意:v-html只能识别原生html标签和文字,ele的输入框属于组件,所以不能使用!!!

为了减少DOM操作,这里不使用原生的input标签(需要获取元素在赋值)

4.解决展示问题

这里我们使用Vue.extend()来进行展示和解析

// 展示题目的组件中
// js
    blankQues: {
      props: {
        html: {
          type: String,
          default: ''
        },
        // 输入空的个数
        num: {
          type: Number,
          default: 0
        },
        id: {
          type: String,
          default: ''
        }
      },
      render (h) {
        const com = Vue.extend({
          template: this.html,
          data () {
            return {
              blankAnswerObj: {

              }
            }
          },
          methods: {
            init (number) {
              for (let i = 0; i < number; i++) {
                this.$set(this.blankAnswerObj, `blank_${i}`, '')
              }
            },
            handleEmit (number) {
              // this.$emit('childInput',val)  失败   
              // this.$emit('childinput',val)  失败   
              this.$store.commit('SET_BLANK_ANSWER', Object.assign(this.blankAnswerObj, { id: this.id }))
            }
          },
          updated () {
            let keys = Object.keys(this.blankAnswerObj)
            if (keys.length === this.num) return
            // 这里是为了初始化填空题组件内部的双向数据绑定对象,匹配外面的组件的key值
            this.init(this.num)
          },
          beforeDestroy () {
            this.$store.commit('CLEAR_BLANK_ANSWER')
          }
        })
        return h(com, {})
      }
    }
<blank-ques :html="blankQuestionContentComputed" ref="blankRef" :num="modelNumberByReg" :id="currentQuesDetail.id"></blank-ques>

5.解析

5.1 使用

可以看到Vue.extend()的使用方法和我们组件的使用方法是类似的,props的属性传值方式也是一致的

5.2 传值
  • 我在子组件内输入完值之后,触发el-input的失焦事件后,想要通过this.$emit()进行传值,发现外层组件无法接收到(子组件已经触发成功)
  • 将错误百度后,说是触发的事件不能使用大写,必须纯小写,尝试后依然失败
  • 后来我使用事件总线(eventBus)进行传值时,依然是失败的
  • 最后使用vuex来解决通信问题
  • 这里只是一道填空题,正常是会有多道题目的,这里我使用的是给一个标志位来区别每个题目,在vuex中,根据id来查找是否回答过,没有就新增一道题的答案,有则进行更新
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值