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来查找是否回答过,没有就新增一道题的答案,有则进行更新