這是一個 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>