最近在用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
强制渲染。
到这里,整篇文章就写完了。