vue 动态组件
为什么需要动态组件
存在这样的需求,需要制作一个搜索栏,这个搜索栏中的字段可能是input输入框,可能是select选择框,如果是通过template模板这样的需求肯定是可以完成的,但是我们在很多的地方上需要这样的组件,能否通过传递配置数组,就能够自动的生成搜索栏成为我的探索。
通过v-if条件判断制作动态组件
我们需要创建一个通用的组件,通过配置文件传过来的组件类型,在v-if的判断需要选择的组件,代码如下,这里编写的是一个通用的表单输入组件:
<template>
<span class="searchitem">
<FormItem v-if="searchdetail.type === 'text'" :label="searchdetail.label" prop="user">
<Input @on-change="valueChange" type="text" :placeholder="searchdetail.placeholder">
</Input>
</FormItem>
<FormItem v-if="searchdetail.type === 'select'" :label="searchdetail.label" :label-width="searchdetail.labelwidth" prop="user">
<Select @on-change="valueSelect" :placeholder="searchdetail.placeholder" :style="searchdetail.class">
<Option :key="index" v-for="(item, index) in searchdetail.options" :value="item.value">{{item.name}}</Option>
</Select>
</FormItem>
<FormItem v-if="searchdetail.type === 'date'" :label="searchdetail.label">
<DatePicker v-model="defaultDateRange" @on-change="dateChange" type="daterange" :placeholder="searchdetail.placeholder"></DatePicker>
</FormItem>
</span>
</template>
<script>
import moment from 'moment';
export default {
name: 'searchitem',
props: ['searchdetail'],
data () {
let dateEnd = moment();
let dateStart = moment().subtract(1, 'months');
console.log(dateStart.format('YYYY-MM-DD'));
return {
name: 'jingchenxu',
defaultDateRange: [dateStart.format('YYYY-MM-DD'), dateEnd.format('YYYY-MM-DD')]
};
},
mounted () {
let me = this;
// 将初始化好的数据传递过去
if (me.$props.searchdetail.type === 'date') {
let dateRange = [];
dateRange[0] = moment(me.defaultDateRange[0]).format('YYYY-MM-DD');
dateRange[1] = moment(me.defaultDateRange[1]).format('YYYY-MM-DD');
this.$emit('searchDateChange', dateRange);
}
},
methods: {
valueChange (e) {
this.$emit('paramsChange', this.$props.searchdetail.name, e.target.value);
},
valueSelect (val) {
this.$emit('paramsChange', this.$props.searchdetail.name, val);
},
dateChange (val) {
this.$emit('searchDateChange', val);
}
}
};
</script>
可以看到,这里主要做的工作就是,将多个表单输入组件,汇总到一个组件当中,通过v-if进行条件判断,左右的组件对外的表现通过封装来保持一致,这里基本实现了动态组件的需求,但是如果在未来需要的表单输入组件的类型增多了之后,需要手动修改此组件才能实现组件功能的扩展。
vue提供动态组件功能
说实在的vue提供的api实在是太多了,现在想来react提供的api就相对较少了,大量的功能需要引入第三发npm包来实现,所以可能学习路线比较的陡峭,好了,让我们说说vue的动态组件功能,该功能配合ES6的 import 及 对象自展开功能,可以完成一个灵活的动态组件。
首先我们还是来看下代码:
<template>
<Card :bordered="false" :dis-hover="true" class="searchbar-comtainer">
<Form :model="searchbar" inline :label-width="80">
<component @valueChange="valueChange" :itemConfig="item" :key="index" v-for="(item, index) in searchConfig.searchList" :is="item.component"></component>
<FormItem>
<Button v-if="searchConfig.canSearch" type="primary" @click="handleSearch" icon="ios-search">查询</Button>
<Button v-if="searchConfig.canExport" type="primary" @click="handleExport" icon="ios-redo">导出</Button>
<Button v-if="searchConfig.canDelete" type="primary" @click="handleDelete" icon="ios-close">删除</Button>
<Button v-if="searchConfig.canAdd" type="primary" @click="handleAdd" icon="android-add">新增</Button>
</FormItem>
</Form>
</Card>
</template>
<script>
import * as formcomponents from './formcomponents'
export default {
name: 'searchbar',
components: {...formcomponents},
props: {
searchConfig: {
type: Object,
required: true
}
},
data () {
return {
searchbar: {
user: '',
password: ''
},
searchParams: {}
}
},
methods: {
handleSearch () {
// eslint-disable-next-line
let me = this;
me.$emit('searchSubmit', me.searchbar);
},
handleExport () {
// 导出
},
handleDelete () {
// 删除
let me = this;
me.$emit('deleteSubmit');
},
handleAdd () {
// 新增
},
valueChange (key, value) {
this.searchParams[key] = value;
console.dir(this.searchParams);
}
}
}
</script>
<template>
<FormItem :label-width="labelwidth" :label="itemConfig.label">
<DatePicker @on-change="rangeChange" type="datetimerange" :placeholder="placeholder" style="width: 300px"></DatePicker>
</FormItem>
</template>
<script>
export default {
name: 'daterangeitem',
props: {
itemConfig: {
type: Object,
required: true
}
},
computed: {
placeholder () {
return `请输入${this._props.itemConfig.label}`
},
labelwidth () {
return this._props.itemConfig.labelwidth || 80
}
},
data () {
return {
value: ''
}
},
methods: {
rangeChange (e) {
console.dir(e);
this.$emit('valueChange', this._props.itemConfig.prop, value)
}
}
}
</script>
所有的组件按照第二段代码来实现,当需要新增一个类型的组件时,只需要在formcomponents文件下创建,并引入到index.js当中即可,在不改变已有代码的情况下,实现了动态组件的扩展。
最后更新于