render函数的一个应用

152 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

需求:显示填空题,数据为string格式,一道填空题内包含多个小题、多个填空,小括号表示代填空格,需将小括号转化为输入框,并能够记录输入答案用';'分割。项目使用的vue2.0.如何实现呢?
为了实现这个需求,我用了vue中的render函数。

什么是render函数呢?

在vue脚手架的main.js中就用到了render函数。
使用render函数可以用js构建dom。当使用render函数描述虚拟DOM时,vue提供一个函数,这个函数是就构建虚拟DOM所需要的工具。官网上给他起了个名字叫createElement。还有约定的简写叫h。
render函数的语法:

render: (h,context)=>{return h(‘el’,{‘css’},vnodeArr)}

render函数的具体用法这里不做赘述,下面对实现思路进行阐述。

方法一

  1. 正则匹配小括号
let reg = new RegExp("([\s]*)|[(][\s]*[)]|([\s]*[)]|[(][\s]*)", "g");
  1. 将填空题里的小括号转化为_
let fillText=text.replace(reg,'_')
  1. 将转化后的字符串遍历每个字符,当遇到_时添加input并添加change监听事件
return h("span", {}, fillText
        .map((d) => {
          if (d == "_") {
            return h("input", {
              //相当于给input上的属性
              attrs: {
                value: value[id++],
                autofocus: true,
                class: "text",
                name: that.value.questionId,
                id: id,
              },
              //input框的监听事件
              on: {
                change: that.change,
              },
            });
          }else {
            return h("span", {
              domProps: {
                innerHTML: d,
              }
            }, []);
          }
        }));

此种方法基本可以实现要求,但存在一个致命的问题,就是若原有字符串里含有标签将无法正常显示,比如包含表格。 发现此问题后,整个字符串就不能被分割,只能以整体的形式存在,以innerHTML的形式对整个字符串进行显示。

方法二

  1. 正则匹配小括号
  2. 将填空题的小括号转化为input标签的字符串
let fillText = that.text.replace(reg, function () {
        // id += 1;
        let inputDom
        // let inputDom = `<input autofocus="true" class="text" style="text-align: center" value="${value[id]}" id="${id++}">`

        if (value[id]) {
          inputDom = `<input autofocus="true" class="text" style="text-align: center" value="${value[id]}" id="${id++}">`
        } else {
          inputDom = `<input autofocus="true" class="text" style="text-align: center" value="" id="${id++}">`
        }
        return inputDom
      });
  1. 添加虚拟dom,用innerHTML(取代v-html)添加内容,onchange监听输入变化
return h("span", {
        domProps: {
          innerHTML: fillText,
          onchange: that.change
        }
      }, [])

此种方法,不管填空题里包含什么样的标签都可以正常显示。
以前从没用过render函数,这是第一次使用,若有其它实现思路,请评论区告诉我,谢谢。