最近在用d2-crud開發後臺,d2-crud是一套基於Vue.js 2.2.0+和Element UI 2.0.0+的表格組件。D2-Crud
將 Element
的功能進行了封裝,並增長了表格的增刪改查、數據校驗、表格內編輯等經常使用的功能。大部分功能可由配置 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
由於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
的變化,只須要修改組件,就大功告成了。 這裏只要將配置中的component
的name
修改就能夠了。 這裏我經過源碼中的方法直接修改的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
強制渲染。
到這裏,整篇文章就寫完了。