d2-crud动态修改表单中的组件

最近在用d2-crud开发后台,d2-crud是一套基于Vue.js 2.2.0+Element UI 2.0.0+的表格组件。D2-CrudElement 的功能进行了封装,并增长了表格的增删改查、数据校验、表格内编辑等经常使用的功能。大部分功能可由配置 json 实现,在实现并扩展了 Element 表格组件功能的同时,下降了开发难度,减小了代码量,大大简化了开发流程。html

可是在开发中仍然会遇到不少问题,好比说我遇到的这个问题:动态切换表单中的组件。下面说下个人需求,我在开发一个我的博客的后台,在这里面添加文章时,想经过两种模式添加文章,一种是富文本,一种是Markdown,下图是最终实现的效果vue

可是,d2-crud对于这种操做并无提供相应的API。下面是个人辛苦历程git

建立表单

首先,把页面结构给搭建出来。代码以下:github

// template
<d2-crud ref="d2Crud" :columns="columns" :data="data" :options="options" index-row :loading="loading" :loading-options="loadingOptions" add-title="新增文章" :add-rules="formRules" :edit-rules="formRules" :form-options="formOptions" :row-handle="rowHandle" @dialog-open="handleDialogOpen" @row-add="handleRowAdd" @row-edit="handleRowEdit" @row-remove="handleRowRemove" @dialog-cancel="handleDialogCancel" @custom-edit="handleCustomEdit" @form-data-change="handleFormDataChange">
    <el-button slot="header" style="margin-bottom: 5px" @click="addArticle">新增文章</el-button>
</d2-crud>
复制代码

其中新增文章表单模板是:json

this.$refs.d2Crud.showDialog({
      mode: 'add',
      template: {
        title: { title: '标题', value: '' },
        category: {
          title: '分类',
          value: '',
          component: { name: 'el-select', options: categoryOptions }
        },
        type: {
          title: '文章类型',
          value: '',
          component: {
            name: 'el-select',
            options: [
              { label: '普通文章', value: 'normal' },
              { label: 'markdown', value: 'markdown' }
            ]
          }
        },
        content: { title: '文章内容', value: '', component: { name: 'd2-quill' } }
      }
    })
复制代码

这里默认显示的是富文本编辑器d2-quill组件。markdown

监听type变化

由于content对应的组件想要变化,须要监听type的变化,是选择的普通文章,仍是选择的markdown。 这里d2-crud提供了一个API来监听表单中的数据变化form-data-change。可是这里存在个bug,就是form-data-change对于el-select这类组件,监听到的是上一次的值。编辑器

因此在 handleFormDataChange ({ key, value }) {...}中,咱们就不能直接使用 d2-crud传给咱们的 value,那就须要本身找到表单数据。这里能够经过源码找到。

这里就知道了在 d2-crud组件中使用的是 formData存储的数据。而组件对应的vue实例则能够经过ref获取到。

handleFormDataChange ({ key, value }) {
    if (key === 'type') {
      const { type } = this.$refs.d2Crud.formData
      let editorType = type === 'markdown' ? 'd2-mde' : 'd2-quill'
    }
  }
复制代码

这里获取到的type就是最新的表单数据中type的值,这里就实现了监听type的的变化ui

最终实现

到这一步,已经知道type的变化,只须要修改组件,就大功告成了。 这里只要将配置中的componentname修改就能够了。 这里我经过源码中的方法直接修改的name的值。this

handleFormDataChange ({ key, value }) {
    if (key === 'type') {
      const { type } = this.$refs.d2Crud.formData
      let editorType = type === 'markdown' ? 'd2-mde' : 'd2-quill'
      this.$refs.d2Crud.handleFormTemplateMode('content').component.name = editorType
    }
  }
复制代码

可是真的这么简单吗? spa

显然,这种方法行不通,组件虽然有变化,可是原来的组件并无清除掉。这里咱们须要知道,若是想要从新渲染组件,通常能够经过 v-if或者 $forceUpdate来触发从新渲染。

经过源码能够看到 el-col上有 v-if可让咱们来实现从新渲染。

this.$refs.d2Crud.handleFormTemplateMode('content').component.show = false
this.$nextTick(() => {
    this.$refs.d2Crud.handleFormTemplateMode('content').component.show = true
    this.$refs.d2Crud.handleFormTemplateMode('content').component.name = editorType
    this.$refs.d2Crud.$forceUpdate() // 由于只修改show的值,并无从新渲染,因此须要执行$forceUpdate,强制渲染
})
复制代码

这里经过修改show的值,来触发渲染,虽然有效果,可是只是清除掉原组件,而没有渲染新的组件,因此最后只能经过$forceUpdate强制渲染。

小结

到这里,整篇文章就写完了。

相关文章
相关标签/搜索