当老板走过来对我说:“你能不能用 Vue 3 setup 实现一个动态表单的功能?”时,我的心情可以用两个字来形容:兴奋!
没错,不是紧张,不是焦虑,而是兴奋!因为用 Vue 3 setup 实现动态表单对于我来说,就像吃饭喝水一样简单。
接下来,我会详细讲解我是如何一步步完成这个任务的。
第一步:创建 Vue 3 项目
首先,我们需要创建一个 Vue 3 项目。如果你还没有安装 Vue CLI,可以使用以下命令来安装:
npm install -g @vue/cli
安装完毕后,可以使用以下命令创建一个新的 Vue 项目:
vue create dynamic-form
在创建过程中,选择 Vue 3 模板。完成后,进入项目目录:
cd dynamic-form
第二步:安装必要的依赖
为了实现动态表单,我们需要安装一些依赖。主要是 Vue Router 和 Vuex,用于路由管理和状态管理。使用以下命令安装:
npm install vue-router@next vuex@next
第三步:配置 Vue Router
接下来,我们需要配置 Vue Router。在 src
目录下创建一个新的 router
目录,并在其中创建 index.js
文件:
// src/router/index.js import { createRouter, createWebHistory } from 'vue-router'; import Home from '../views/Home.vue'; import Form from '../views/Form.vue'; const routes = [ { path: '/', component: Home }, { path: '/form', component: Form } ]; const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes }); export default router;
然后在 main.js
中引入这个路由:
// src/main.js import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; createApp(App).use(router).mount('#app');
第四步:创建动态表单组件
接下来,我们创建一个动态表单组件。我们会使用 <script setup>
来实现这个组件。在 src/components
目录下创建一个新的 DynamicForm.vue
文件:
<!-- src/components/DynamicForm.vue --> <template> <form @submit.prevent="handleSubmit"> <div v-for="(field, index) in fields" :key="index"> <label :for="field.name">{{ field.label }}</label> <input :type="field.type" :name="field.name" v-model="formData[field.name]" /> </div> <button type="submit">提交</button> </form> </template> <script setup> import { ref } from 'vue'; const fields = ref([ { name: 'username', label: '用户名', type: 'text' }, { name: 'email', label: '邮箱', type: 'email' }, { name: 'password', label: '密码', type: 'password' } ]); const formData = ref({}); fields.value.forEach(field => { formData.value[field.name] = ''; }); const handleSubmit = () => { console.log(formData.value); }; </script> <style scoped> form { display: flex; flex-direction: column; } label { margin: 8px 0 4px; } input { margin-bottom: 16px; padding: 8px; border: 1px solid #ccc; border-radius: 4px; } button { padding: 10px 20px; background-color: #42b983; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #369970; } </style>
第五步:将组件集成到页面
现在我们已经创建了动态表单组件,接下来将其集成到我们的页面中。在 src/views
目录下创建 Home.vue
和 Form.vue
文件。
Home.vue
<!-- src/views/Home.vue --> <template> <div> <h1>欢迎来到动态表单示例</h1> <router-link to="/form">跳转到表单页面</router-link> </div> </template> <script setup> </script>
Form.vue
<!-- src/views/Form.vue --> <template> <div> <h1>动态表单</h1> <DynamicForm /> </div> </template> <script setup> import DynamicForm from '../components/DynamicForm.vue'; </script>
第六步:运行项目
完成以上步骤后,我们可以运行项目来查看效果:
npm run serve
打开浏览器,访问 http://localhost:8080
,你会看到一个欢迎页面,点击跳转链接可以进入动态表单页面。
第七步:添加动态字段功能
为了使表单更具动态性,我们需要实现动态添加字段的功能。更新 DynamicForm.vue
文件如下:
<!-- src/components/DynamicForm.vue --> <template> <form @submit.prevent="handleSubmit"> <div v-for="(field, index) in fields" :key="index"> <label :for="field.name">{{ field.label }}</label> <input :type="field.type" :name="field.name" v-model="formData[field.name]" /> </div> <button type="button" @click="addField">添加字段</button> <button type="submit">提交</button> </form> </template> <script setup> import { ref } from 'vue'; const fields = ref([ { name: 'username', label: '用户名', type: 'text' }, { name: 'email', label: '邮箱', type: 'email' }, { name: 'password', label: '密码', type: 'password' } ]); const formData = ref({}); fields.value.forEach(field => { formData.value[field.name] = ''; }); const handleSubmit = () => { console.log(formData.value); }; const addField = () => { const newField = { name: `field${fields.value.length + 1}`, label: `字段${fields.value.length + 1}`, type: 'text' }; fields.value.push(newField); formData.value[newField.name] = ''; }; </script> <style scoped> form { display: flex; flex-direction: column; } label { margin: 8px 0 4px; } input { margin-bottom: 16px; padding: 8px; border: 1px solid #ccc; border-radius: 4px; } button { padding: 10px 20px; background-color: #42b983; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #369970; } </style>
第八步:添加字段类型选择功能
为了让我们的动态表单更强大,我们可以添加字段类型选择功能。再次更新 DynamicForm.vue
文件如下:
<!-- src/components/DynamicForm.vue --> <template> <form @submit.prevent="handleSubmit"> <div v-for="(field, index) in fields" :key="index"> <label :for="field.name">{{ field.label }}</label> <input :type="field.type" :name="field.name" v-model="formData[field.name]" /> </div> <div> <input v-model="newField.label" placeholder="字段标签" /> <select v-model="newField.type"> <option value="text">文本</option> <option value="email">邮箱</option> <option value="password">密码</option> <option value="number">数字</option> </select> <button type="button" @click="addField">添加字段</button> </div> <button type="submit">提交</button> </form> </template> <script setup> import { ref } from 'vue'; const fields = ref([ { name: 'username', label: '用户名', type: 'text' }, { name: 'email', label: '邮箱', type: 'email' }, { name: 'password', label: '密码', type: 'password' } ]); const formData = ref({}); initializeFormData(); const handleSubmit = () => { console.log(formData.value); }; const newField = ref({ label: '', type: 'text' }); const addField = () => { const fieldName = generateFieldName(); const newFieldData = { name: fieldName, label: newField.value.label || `字段${fields.value.length + 1}`, type: newField.value.type }; fields.value.push(newFieldData); formData.value[fieldName] = ''; newField.value.label = ''; }; function initializeFormData() { fields.value.forEach(field => { formData.value[field.name] = ''; }); } function generateFieldName() { return `field${fields.value.length + 1}`; } </script> <style scoped> form { display: flex; flex-direction: column; } label { margin: 8px 0 4px; } input { margin-bottom: 16px; padding: 8px; border: 1px solid #ccc; border-radius: 4px; } select { margin-bottom: 16px; padding: 8px; border: 1px solid #ccc; border-radius: 4px; } button { padding: 10px 20px; background-color: #42b983; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #369970; } </style>
第九步:优化代码结构
为了提高代码的可读性和维护性,我们可以将一些逻辑抽离出来,形成独立的函数。下面是优化后的 DynamicForm.vue
:
<!-- src/components/DynamicForm.vue --> <template> <form @submit.prevent="handleSubmit"> <div v-for="(field, index) in fields" :key="index"> <label :for="field.name">{{ field.label }}</label> <input :type="field.type" :name="field.name" v-model="formData[field.name]" /> </div> <div> <input v-model="newField.label" placeholder="字段标签" /> <select v-model="newField.type"> <option value="text">文本</option> <option value="email">邮箱</option> <option value="password">密码</option> <option value="number">数字</option> </select> <button type="button" @click="addField">添加字段</button> </div> <button type="submit">提交</button> </form> </template> <script setup> import { ref } from 'vue'; const fields = ref([ { name: 'username', label: '用户名', type: 'text' }, { name: 'email', label: '邮箱', type: 'email' }, { name: 'password', label: '密码', type: 'password' } ]); const formData = ref({}); initializeFormData(); const handleSubmit = () => { console.log(formData.value); }; const newField = ref({ label: '', type: 'text' }); const addField = () => { const fieldName = generateFieldName(); const newFieldData = { name: fieldName, label: newField.value.label || `字段${fields.value.length + 1}`, type: newField.value.type }; fields.value.push(newFieldData); formData.value[fieldName] = ''; newField.value.label = ''; }; function initializeFormData() { fields.value.forEach(field => { formData.value[field.name] = ''; }); } function generateFieldName() { return `field${fields.value.length + 1}`; } </script> <style scoped> form { display: flex; flex-direction: column; } label { margin: 8px 0 4px; } input { margin-bottom: 16px; padding: 8px; border: 1px solid #ccc; border-radius: 4px; } select { margin-bottom: 16px; padding: 8px; border: 1px solid #ccc; border-radius: 4px; } button { padding: 10px 20px; background-color: #42b983; color: white; border: none; border-radius: 4px; cursor: pointer; } button:hover { background-color: #369970; } </style>
结语
通过以上步骤,我们成功地使用 Vue 3 setup 实现了一个动态表单。这
个过程看似复杂,但只要一步一步来,每一步都不是很难。