资讯专栏INFORMATION COLUMN

使用Vue渲染可配置表单--记一次问卷平台项目

mcterry / 3099人阅读

摘要:相当于可以编辑问卷并提供问卷展示,数据统计的这么一个平台。极大的节省了需要进行表单样式修改的时间,同时,让动态渲染表单成为一件可能且容易的事情。表单动态渲染刚好在项目之前,有过一次动态配置表单的尝试通过字段自动生成表单及验证。

近几天来了个紧急项目,想要做一个内部版本的问卷星。相当于可以编辑问卷并提供问卷展示,数据统计的这么一个平台。整个项目耗时不长,本着积淀和积累的原则,将过程中的思路和收获进行一下沉淀。由于公司原因,代码尚未开源。

不过沉淀了个动态配置表单的尝试: github,用于后台快速开发表单等需求,搭配element-ui进行使用,同时可通过后台进行配置生成表单等。

功能和效果

问卷编辑功能大概需要一下几点:

根据不同题型添加问题

区分问题的必选性

问题排序,删除,复制功能

选择题的选项编辑,排序,删除功能

问卷渲染

生成问卷二维码

效果


or
预览

技术方案 Vue + VueRouter + ElementUI

使用element进行后台以及问卷表单渲染是再合适不过的了。极大的节省了需要进行表单样式修改的时间,同时,让动态渲染表单成为一件可能且容易的事情。

表单动态渲染

刚好在项目之前,有过一次动态配置表单的尝试: github 通过字段自动生成表单及验证。但此时的数据格式相当于在后台已经确定好的,针对可变切频繁变动的表单结构,确定数据结构如下:

数据结构
data: {
  title: 问卷名称
  desc: 问卷描述
  questionList: [
    {
      type: 问题类型,
      label: 问题描述,
      required: 必选性,
      options: [ //选项
        {
          label: 选项内容,
          value: 选项值
        }
        ...
      ] 
    }
    ...
  ]
}
表单渲染

最简单的 v-if 模式来满足我们的需求,之前有想过使用is进行渲染,但是不同表单配置项相差很大,很难进行通用。因此采用类似以下这种方式,配置详情可见element官网。


很简单就可以将表单根据配置渲染出来啦:

实现过程

思路理清楚了,就可以动手实践啦!

添加问题

首先,我需要各个问题的基本配置模板,以便于每次直接向questionList中直接添加相应的内容,为了方便存储及使用,将其放在store中,当

const state = {
  baseSet: {
    radio: {
      type: "radio",
      label: "单选题",
      required: true,
      options: [...]
    },
    checkbox: ...
    input: ...
  }
}

//添加问题时,直接push进数组即可
const mutations = [
  //添加问题
  ADDQUESTIONLIST(state, data) {
    state.qss.questionList.push(data);
  }
]

//添加问题方法
addQuestion(type) {
  this.addQuestionList(this. baseSet[type]);
},
注意

使用getter获取到我们对应的baseSet对象时,此对象为引用类型,并且,对象的属性,如options也同样为引用类型。我们若不进行处理,则会出现,创建两个相同类型的问题时,对其中某一问题选项进行修改,另一个选项也会进行修改。 因此我们需要对base对象进行简单的拷贝(只进行到数组内容即可)

export const clone = function(obj) {
  var newObj = {};

  for (let key in obj) {
    var target = obj[key];

    if (Object.prototype.toString.call(target) === "[object Object]") {
      newObj[key] = clone(target);
    } else {
      if (Object.prototype.toString.call(target) === "[object Array]") {
        newObj[key] = target.slice(0);
      } else {
        newObj[key] = target;
      }
    }
  }

  return newObj;
}

addQuestion(type) {
  this.addQuestionList(clone(this. baseSet[type]));
},
排序/删除/复制

这三点基本就是简单的数组操作啦,此时的问题数据依旧是引用类型,直接对引用数组进行操作即可。简单的上移,下移排序,使用splice即可实现。其实这三点都是用splice实现的哈。

deleteQuestion(index) {
  this.data.questionList.splice(index, 1);
},

copyQuestion(index) {
  let list = this.data.questionList;
  //复制时,同样需要对引用对象进行深拷贝
  list.splice(index, 1, list[index], clone(list[index]));
},

moveQuestion(index, direct) {
  let list = this.data.questionList;

  if(direct === "up") {
    if(index < 1) {
      this.$toast("已经是第一项!");
      return;
    }

    list.splice(index - 1, 2, list[index], list[index - 1]);
  } else {
    if(index >= list.length - 1) {
      this.$toast("已经是最后一项!");
      return;
    }

    list.splice(index, 2, list[index + 1], list[index]);
  }
}
生成二维码

使用qrcode.js,感谢大佬们为小辈们造出这么多好用的轮子,让我们站在巨人的肩膀上前行!

其他点 对于Vuex,使用computed获取getters or state,如何配合v-model使用?

我们都知道,针对Vue2.0后,使用computed获取getters or state,而针对计算属性,我们是无法进行写操作的,像这样

computed: {
  ...mapState({
    qss: state => state.qss,
    base: state => state.base
  })
},

//以下代码是无效的
this.qss = 2;

因此,我们更无法将qss属性直接绑定在v-model上,很是苦恼。同事的一般处理方式是在data中书写相同的属性,在路由进入时对其进行初始化,当其修改时再写回store。这样写起来未免有点麻烦且不妥当。那么,该如何解决呢?

其实很简单,可以交给父组件呀。

我们常常会听到一个词,单向数据流,大概意思就是让数据单一方向流动,我们只对数据源进行修改,再让数据从数据源依次流动到子组件进行UI渲染。

其实就像我们使用ajax获取数据时,统一交给父组件一样,我们将统一获取到的数据,使用props进行向下分发即可,使用vuex亦是如此。子组件值进行对应值的修改。而针对props,v-model可以很方便的对其进行修改了。当然这些只是我的一点理解,如果有异议,可以一起讨论哈。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82509.html

相关文章

  • Vue.js实现一个简易问卷平台(项目中遇到的问题总结)

    摘要:项目地址源码地址预览地址没有做响应式,请在电脑上打开使用了我自制的日历组件初学时做的,有些糙任务描述参考设计图实现一个简易版的问卷管理系统,有如下功能问卷管理列表有一个头部可以显示,不需要实现登录等操作问卷管理列表页面默认为首页有一个表格 项目地址 源码地址 预览地址(没有做响应式,请在电脑上打开) 使用了我自制的日历组件(初学vue时做的,有些糙)calendar-input 任...

    Scott 评论0 收藏0
  • Vue.js实现一个简易问卷平台(项目中遇到的问题总结)

    摘要:项目地址源码地址预览地址没有做响应式,请在电脑上打开使用了我自制的日历组件初学时做的,有些糙任务描述参考设计图实现一个简易版的问卷管理系统,有如下功能问卷管理列表有一个头部可以显示,不需要实现登录等操作问卷管理列表页面默认为首页有一个表格 项目地址 源码地址 预览地址(没有做响应式,请在电脑上打开) 使用了我自制的日历组件(初学vue时做的,有些糙)calendar-input 任...

    kbyyd24 评论0 收藏0
  • 一次Vue项目优化及思路

    摘要:记录一个前端项目优化的路程,效果如上图。第二步优化结果再次运行查看项目打包情况可以看到项目体积已经优化到,中也看不到的踪影了。本文主要想提供一些优化思路及手段,即如何定位通过,查看页面加载时间问题,然后再解决这些问题。 showImg(https://segmentfault.com/img/bVbq282?w=381&h=384); 记录一个前端项目优化的路程,效果如上图。 接下来我...

    keithxiaoy 评论0 收藏0
  • 一次Vue项目优化及思路

    摘要:记录一个前端项目优化的路程,效果如上图。第二步优化结果再次运行查看项目打包情况可以看到项目体积已经优化到,中也看不到的踪影了。本文主要想提供一些优化思路及手段,即如何定位通过,查看页面加载时间问题,然后再解决这些问题。 showImg(https://segmentfault.com/img/bVbq282?w=381&h=384); 记录一个前端项目优化的路程,效果如上图。 接下来我...

    nanchen2251 评论0 收藏0

发表评论

0条评论

mcterry

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<