vue + vant根据后台传递数据动态渲染组件
根据后台数据动态渲染页面封装组件,方便使用field和actionsheet封装selectPicker等组件利用Render函数来渲染利用动态组件的属性is来渲染需求:根据后台返回的数据,来生成一个form表单。几乎所有元素都是后台决定。后台会告诉前端这个页面里有几个input,label,select,selectDateTime等,以及他们的顺序。封装组件,方便使用field和acti...
需求:根据后台返回的数据,来生成一个form表单。几乎所有元素都是后台决定。后台会告诉前端这个页面里有几个input,label,select,selectDateTime等,以及他们的顺序。
封装组件,方便使用
field和actionsheet封装selectPicker等组件
我所封装的selectPicker用了很多插槽来满足样式需求,看起来有些繁复。而且这不是重点,就不列举代码了。仅展示一下所要达到的效果(封装以后的组件使用):
<select-picker
isRequired=true
fieldKey="influence"
fieldLabel="影响程度"
fieldValue=""
columns="['高', '中', '低']"
leftIcon="#icon_yxcd"
@confirmSelect="confirmSelect"/>
对于上述属性的说明
isRequired: 是否必填
fieldKey: name属性
fieldLabel: 显示的标题
fieldValue: 所选的值
columns: 选项
confirmSelect: 选好后调用的函数
leftIcon: 左边图标
以上只是selectPicker的组件封装。
类似的还封装了 类似textarea, dateTimePicker等组件。
利用Render函数来渲染
参考文章: 【Vue】动态添加组件的两种实现.
几乎就是参考这篇文章的第二种方式来实现的。
有关render,具体参考官网:: 渲染函数 & JSX.
就直接上代码了:
Test.vue
<template>
<div class="test>
<van-form>
<template #default>
<div ref="mainList"></div>
</template>
</van-form>
</div>
</template>
<script>
import FakeData from './utils/fakeDatas'
import RenderTags from './utils/renderTags'
export default {
data() {
return {
list: []
}
}
mounted() {
this.list = this.getFakeListData();
this.initTags(this.list);
},
methods: {
getFakeListData() {
//eg: { type: 'selectpicker', icon: 'icon_yingxiangchengdu', key: 'influence', keyValue: '影响程度', actions: ['高', '中', '低'], value: '', require: true },
return FakeData.getList();
},
initTags(list) {
if(list.length > 0) {
for(let item of list) {
let tag;
switch(item.type) {
case 'selectpicker':
tag = RenderTags.renderSelectPickerTag(item);
break;
case 'datetime':
tag = RenderTags.renderDateTimePickerTag(item);
break;
case 'textarea':
tag = RenderTags.renderTextareaTag(item);
break;
}
if(tag) {
tag.$mount();
this.$refs.mainList.appendChild(tag.$el);
}
}
}
},
}
}
</script>
renderTags.js 部分代码
renderSelectPickerTag(infoObj) {
let selectPickerTag = Vue.extend({
components: {
SelectPicker
},
data() {
return {
value: infoObj.value || ''
}
},
render(createElement) {
return createElement('div',
{
style: { 'margin-top': '4px' }
},
[
createElement('SelectPicker',{
attrs: {
isRequired: infoObj.require,
fieldKey: infoObj.key,
fieldLabel: infoObj.keyValue,
fieldValue: this.value,
columns: infoObj.actions,
leftIcon: '#' + infoObj.icon,
},
on: {
'confirmSelect': this.onConfirmSelect
}
})
]
);
},
methods: {
onConfirmSelect(value) {
this.value = value;
}
}
});
return new selectPickerTag();
},
还有datetimepicker组件和textarea组件的方法就不全部列举了。
这种方法,利用ref找到目标div,然后进行替换。
测试之后可以实现。
但是有一个问题,由于我同时使用了vant库的form组件,
render出来的list没有办法和form绑定上。
原因是,form标签在渲染的时候,还没有render出来的list,因此无法进行绑定。
所以,我决定摒弃这种方法,改用下面的方式来完成。
利用is属性来完成,代码更加简便也更加容易理解。
利用动态组件的属性is来渲染
<template>
<div class="test>
<van-form>
<template #default>
<div class="main-list">
<div v-for="(item, index) in list" :key="index" class="itemClass">
<component :is="item.type"
:isRequired="item.require"
:dateType="dateType"
:fieldKey="item.key"
:leftIcon="`#${item.icon}`"
:fieldValue="item.value"
:fieldLabel="item.keyValue"
:columns="item.actions"
@fieldConfirm="onConfirm($event ,index)" />
</div>
</div>
</template>
</van-form>
</div>
</template>
list便是后台返回来的数据了。
更多推荐
所有评论(0)