vue 关联表单项组件,常用于组合条件

这是一个 vue 简单组件, 用来实现一个表单关联的功能。例如一些条件生成:
- 当 - 发言人 - 为 - 坐席
- 当 - 发言人 - 为 - 客户
- 当 - 发言内容 - 包含 - 你好
- 当 - 发言内容 - 不包含 - 你好
像上面的上级选项为某个值之后,后面是根据这个值又首先新的选项。
<template>
<div class="about">
<span>{{ rootTable.pre }}</span>
<template v-for="(tableValueItem, tableValueIndex) in filterOptions">
<el-cascader
:key="`el-cascader${tableValueIndex}`"
v-if="[`el-cascader`].includes(getItem(tableValueIndex).type)"
v-model="tableValue[tableValueIndex]"
:options="getOptions(tableValueIndex)"
v-bind="getItem(tableValueIndex).props"
clearable
></el-cascader>
<el-select
v-else
:key="`el-select${tableValueIndex}`"
clearable
v-model="tableValue[tableValueIndex]"
@change="(val) => change(val, tableValueIndex)"
:placeholder="getItem(tableValueIndex).placeholder"
:multiple="getItem(tableValueIndex).multiple"
:allow-create="getItem(tableValueIndex).allowCreate"
:filterable="getItem(tableValueIndex).allowCreate"
:default-first-option="getItem(tableValueIndex).allowCreate"
>
<el-option
:key="item.value"
v-for="item in getOptions(tableValueIndex)"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
<span :key="`span${tableValueIndex}`">{{ getSub(tableValueIndex) }}</span>
</template>
</div>
</template>
<script>
/**
- 只有选择父项目时才会出现子项
- 父项值改变时, 清空子项的值
*/
export default {
model: {
prop: "defaultValue",
event: "update",
},
props: {
// 默认值, 可以用 v-model 绑定
defaultValue: {
type: Array,
default() {
return ["发言内容发言内容", "包含包含", "关键词关键词", ["你好"]];
},
},
// 标签数据, 可以优化为数据公用表, 然后在 rootTable 中通过 optionsSource 选项引用
tagData: {
default() {
return [
{
value: "zhinan",
sub: `时`,
label: "指南",
children: [
{
value: "shejiyuanze",
label: "设计原则",
children: [
{
value: "yizhi",
label: "一致",
},
{
value: "fankui",
label: "反馈",
},
{
value: "xiaolv",
label: "效率",
},
{
value: "kekong",
label: "可控",
},
],
},
{
value: "daohang",
label: "导航",
children: [
{
value: "cexiangdaohang",
label: "侧向导航",
},
{
value: "dingbudaohang",
label: "顶部导航",
},
],
},
],
},
{
value: "zujian",
label: "组件",
children: [
{
value: "basic",
label: "Basic",
children: [
{
value: "layout",
label: "Layout 布局",
},
{
value: "color",
label: "Color 色彩",
},
{
value: "typography",
label: "Typography 字体",
},
{
value: "icon",
label: "Icon 图标",
},
{
value: "button",
label: "Button 按钮",
},
],
},
{
value: "form",
label: "Form",
children: [
{
value: "radio",
label: "Radio 单选框",
},
{
value: "checkbox",
label: "Checkbox 多选框",
},
{
value: "input",
label: "Input 输入框",
},
{
value: "input-number",
label: "InputNumber 计数器",
},
{
value: "select",
label: "Select 选择器",
},
{
value: "cascader",
label: "Cascader 级联选择器",
},
{
value: "switch",
label: "Switch 开关",
},
{
value: "slider",
label: "Slider 滑块",
},
{
value: "time-picker",
label: "TimePicker 时间选择器",
},
{
value: "date-picker",
label: "DatePicker 日期选择器",
},
{
value: "datetime-picker",
label: "DateTimePicker 日期时间选择器",
},
{
value: "upload",
label: "Upload 上传",
},
{
value: "rate",
label: "Rate 评分",
},
{
value: "form",
label: "Form 表单",
},
],
},
{
value: "data",
label: "Data",
children: [
{
value: "table",
label: "Table 表格",
},
{
value: "tag",
label: "Tag 标签",
},
{
value: "progress",
label: "Progress 进度条",
},
{
value: "tree",
label: "Tree 树形控件",
},
{
value: "pagination",
label: "Pagination 分页",
},
{
value: "badge",
label: "Badge 标记",
},
],
},
{
value: "notice",
label: "Notice",
children: [
{
value: "alert",
label: "Alert 警告",
},
{
value: "loading",
label: "Loading 加载",
},
{
value: "message",
label: "Message 消息提示",
},
{
value: "message-box",
label: "MessageBox 弹框",
},
{
value: "notification",
label: "Notification 通知",
},
],
},
{
value: "navigation",
label: "Navigation",
children: [
{
value: "menu",
label: "NavMenu 导航菜单",
},
{
value: "tabs",
label: "Tabs 标签页",
},
{
value: "breadcrumb",
label: "Breadcrumb 面包屑",
},
{
value: "dropdown",
label: "Dropdown 下拉菜单",
},
{
value: "steps",
label: "Steps 步骤条",
},
],
},
{
value: "others",
label: "Others",
children: [
{
value: "dialog",
label: "Dialog 对话框",
},
{
value: "tooltip",
label: "Tooltip 文字提示",
},
{
value: "popover",
label: "Popover 弹出框",
},
{
value: "card",
label: "Card 卡片",
},
{
value: "carousel",
label: "Carousel 走马灯",
},
{
value: "collapse",
label: "Collapse 折叠面板",
},
],
},
],
},
{
value: "ziyuan",
sub: `时`,
label: "资源",
children: [
{
value: "axure",
label: "Axure Components",
},
{
value: "sketch",
label: "Sketch Templates",
},
{
value: "jiaohu",
label: "组件交互文档",
},
],
},
];
},
},
/**
- 渲染表单的数据, 当上一级表单项有值后才会子项
pre - 在某个表单项前面
sub - 在某个表单项后面, 当表单项有值后才会显示
options - 子项的可选项
type - 可以根据此 type 来渲染组件, 默认为普通 select, 可以优化为动态渲染组件以及添加组件 props 选项
- el-cascader 级联选择
label - 选项的 label
value - 选项的 value
multiple - 是否多选
allowCreate - 是否显示清除图片
*/
rootTable: {
type: Object,
default() {
console.log(`tagDatatagData`, this.tagData);
return {
pre: `当`,
options: [
{
label: `发言内容`,
value: `发言内容发言内容`,
sub: `中`,
options: [
{
label: `不包含`,
value: `不包含不包含`,
sub: ``,
options: [
{
label: `语义标签`,
value: `语义标签语义标签`,
sub: `中的`,
type: `el-cascader`,
optionsSource: `tagData`,
},
{
label: `关键词`,
value: `关键词关键词`,
placeholder: `请输入`,
sub: `中的`,
multiple: true,
allowCreate: true,
forcedDisplay: true,
},
],
},
{
label: `包含`,
value: `包含包含`,
sub: ``,
options: [
{
label: `语义标签`,
value: `语义标签语义标签`,
sub: `中的`,
type: `el-cascader`,
optionsSource: `tagData`,
},
{
label: `关键词`,
value: `关键词关键词`,
placeholder: `请输入`,
sub: `中的`,
multiple: true,
allowCreate: true,
forcedDisplay: true,
},
],
},
],
},
{
label: `发言人`,
value: `发言人发言人`,
sub: `为`,
options: [
{
label: `用户`,
value: `用户用户`,
sub: ``,
options: [],
},
{
label: `坐席`,
value: `坐席坐席`,
sub: ``,
options: [],
},
{
label: `所有`,
value: `所有所有`,
sub: ``,
options: [],
},
],
},
],
};
},
},
},
data() {
return {
table: this.rootTable.options,
tableValue: this.defaultValue,
};
},
watch: {
defaultValue: {
handler(val) {
this.$emit(`update:defaultValue`, val);
},
deep: true,
},
},
created() {
// this.getOptions(`选项1选项1`, `选项11选项11`)
},
computed: {
filterOptions() {
let curItem = this.getCurItem({ index: undefined });
console.log(`curItemcurItem`, curItem);
let list = this.tableValue.length ? this.tableValue : [undefined];
// 如果还有子项并且父选项有值时, 那么就加载子项选择器
if (
curItem.forcedDisplay ||
(this.getOptions().length &&
[``, undefined].includes(list.slice(-1)[0]) === false)
) {
list.push(undefined);
}
return list;
},
sub() {
const curItem =
this.table.find((item) => item.value === this.tableValue[0]) || {};
return curItem.sub;
},
},
methods: {
getCurItem({ keys, index }) {
if (keys === undefined) {
keys =
index === undefined
? this.tableValue
: this.tableValue.slice(0, index);
}
let curItem = this.rootTable;
keys.forEach((key) => {
curItem =
(curItem.options || []).find((item) => {
return (
item.value === key ||
(typeof key === `object` ? key.includes(item.value) : false) // 处理多选时如果包含其中一个选项则返回
);
}) || {};
});
return curItem;
},
change(val, index) {
console.log(`val, key`, val, index);
this.tableValue.splice(index + 1, this.tableValue.length); // 当父项值改变的时候, 删除所有子项的值
},
getOptions(index) {
// 根据值获取选项
let curItem = this.getCurItem({ index });
curItem.options = this[curItem.optionsSource] || curItem.options;
console.log(`curItem.options`, curItem.options);
return curItem.options || [];
},
getItem(index) {
let curItem = this.getCurItem({ index });
return curItem;
},
getSub(index) {
// 根据值获取选项
if (
// 只有所选择的项存在值时, 才显示后缀
this.tableValue[index] === undefined ||
this.tableValue[index] === ``
) {
return ``;
}
const keys = this.tableValue.slice(0, index + 1);
let curItem = this.getCurItem({ keys });
console.log(`getSubgetSubgetSubgetSub`, keys, curItem);
return curItem.sub;
},
},
components: {},
};
</script>

浙公网安备 33010602011771号