You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Vue.js实现产品类型选择器切换对应表单输入区域?

问题描述

我需要实现一个选择器功能,选项包含DVD、图书(Books)、家具(Furniture)。当选择对应选项时,页面需切换为对应的输入表单(比如选DVD显示尺寸输入表单)。

以下是我的实现代码:

HTML代码

<div class="typeswitcher">
    <div>
        <h4 class="typeHeading">Type Switcher</h4>
    </div>
    <select name="typeSwitcher" id="typeSwitcher" v-model="itemType">
        <option value="DVD" id="DVD">DVD</option>
        <option value="dimensions" id="Furniture">Furniture</option>
        <option value="weight" id="Book">Books</option>
    </select>
</div>
<form method="POST">
    <div class="switcher-form">
        <!-- slice used to remove unnecessary iterations from the v-for -->
        <div v-if="itemType === 'DVD'" class="row mb-1" v-html="item.size" v-for="item in switcherForm.slice(0,1)" :key="item">
        </div>
        <div v-if="itemType === 'dimensions'" class="row mb-1" v-html="item.dimensions" v-for="item in switcherForm.slice(1,2)" :key="item">                            
        </div>
        <div v-if="itemType === 'weight'" class="row mb-1" v-html="item.weight" v-for="item in switcherForm.slice(2,3)" :key="item">
        </div>
    </div>

JS代码

import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'

createApp({
    data() {
        return {
            title: 'Add product',
            itemType: null,
            switcherForm: [
                {
                    size:`
                    <label class="col-sm-4 col-form-label">Size (MB)</label>
                    <div class="col-sm-6">
                        <input id="size" type="text" name="size" placeholder="size" value="<?php echo $size; ?>"></input>
                        <h6>Please provide DVD size in MB.</h6>
                    </div>
                    `
                },
                {
                    dimensions:`
                    <label class="col-sm-4 col-form-label">Dimensions</label>
                    <div class="col-sm-6">
                        <input type="text" name="dimensions" placeholder="dimensions" value="<?php echo $dimensions; ?>"></input>
                        <h6>Please provide dimensions in HxWxL. format</h6>
                    </div>
                    `
                },
                {
                    weight:`
                    <label class="col-sm-4 col-form-label">Weight (KG)</label>
                    <div class="col-sm-6">
                        <input type="text" name="weight" placeholder="weight" value="<?php echo $weight; ?>"></input>
                        <h6>Please provide Book weight in KG.</h6>
                    </div>
                    `
                },
            ] 
        }
    },
}).mount('#add-product')

我的实现逻辑是:将itemType与选择器通过v-model绑定,使用v-for结合slice方法渲染对应表单区域,switcherForm是存储HTML输入框的对象数组。请问该实现方式是否合理,或有无优化方案?


回答

原实现的不合理之处

  • v-html存HTML字符串:违背Vue组件化思想,代码可读性差,存在XSS安全风险,同时无法利用Vue的数据双向绑定优势(比如输入框value用PHP输出,无法和Vue数据联动)。
  • v-for+slice冗余写法:明明只需要渲染单个表单区域,却用循环+切片的方式绕弯,逻辑没必要。
  • 选项值命名混乱:选择器选项值中,DVD对应DVD、家具对应dimensions、图书对应weight,命名逻辑不统一,后期维护易出错。

优化方案

采用统一数据结构+Vue原生条件渲染的方式,充分利用Vue响应式特性,代码更整洁易维护:

优化后的代码示例

HTML部分
<div id="add-product">
    <div class="typeswitcher">
        <div>
            <h4 class="typeHeading">Type Switcher</h4>
        </div>
        <select name="typeSwitcher" id="typeSwitcher" v-model="selectedType">
            <option :value="type.id" v-for="type in productTypes" :key="type.id">{{ type.label }}</option>
        </select>
    </div>
    <form method="POST">
        <div class="switcher-form">
            <!-- DVD表单 -->
            <div v-if="selectedType === 'dvd'" class="row mb-1">
                <label class="col-sm-4 col-form-label">Size (MB)</label>
                <div class="col-sm-6">
                    <input type="text" v-model="formData.size" placeholder="size">
                    <h6>请提供DVD的大小(MB)。</h6>
                </div>
            </div>
            <!-- 家具表单 -->
            <div v-if="selectedType === 'furniture'" class="row mb-1">
                <label class="col-sm-4 col-form-label">尺寸</label>
                <div class="col-sm-6">
                    <input type="text" v-model="formData.dimensions" placeholder="尺寸(格式:HxWxL)">
                    <h6>请提供尺寸,格式为HxWxL。</h6>
                </div>
            </div>
            <!-- 图书表单 -->
            <div v-if="selectedType === 'book'" class="row mb-1">
                <label class="col-sm-4 col-form-label">重量(KG)</label>
                <div class="col-sm-6">
                    <input type="text" v-model="formData.weight" placeholder="重量">
                    <h6>请提供图书的重量(KG)。</h6>
                </div>
            </div>
        </div>
    </form>
</div>
JS部分
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'

createApp({
    data() {
        return {
            title: 'Add product',
            selectedType: null,
            // 统一的产品类型元数据
            productTypes: [
                { id: 'dvd', label: 'DVD' },
                { id: 'furniture', label: '家具' },
                { id: 'book', label: '图书' }
            ],
            // 表单数据,和输入框双向绑定
            formData: {
                size: '',
                dimensions: '',
                weight: ''
            }
        }
    },
}).mount('#add-product')

进阶优化(可选)

如果后续表单逻辑更复杂,可将每个类型的表单抽成独立Vue组件,用<component :is="currentFormComponent"></component>动态渲染,进一步提升代码复用性和可维护性。


内容的提问来源于stack exchange,提问作者aTHEM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 10:10:28