这是一个 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>