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強制渲染。

小結

到這裏,整篇文章就寫完了。

相關文章
相關標籤/搜索