FormData props

本文详细解读Vue中的三类关键符号:'v-bind'、'v-on'及'.',并阐述它们在实际开发中的应用。包括表单数据处理与异步上传文件等场景,以及符号在模板渲染中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Survive by day and develop by night.
talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive.
happy for hardess to solve denpendies.

目录

在这里插入图片描述

概述

FormData props

需求:

设计思路

实现思路分析

1.FormData

FormData 接口提供了一种表示表单数据的键值对 key/value 的构造方式,并且可以轻松的将数据通过前端Ajax 方法发送出去,本接口和此方法都相当简单直接。如果送出时的编码类型被设为 “multipart/form-data”,它会使用和表单一样的格式。
FormData的主要用途有两个:
1、将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。
2、异步上传文件

2.vue中“:”、“.”、“@”意义

“:” 是指令 “v-bind”的缩写,“@”是指令“v-on”的缩写;“.”是修饰符。详细如下
v-bind 指令可以用于响应式地更新 HTML 特性:
v- 前缀作为一种视觉提示,用来识别模板中 Vue 特定的特性。当你在使用 Vue.js 为现有标签添加动态行为 (dynamic behavior) 时,v- 前缀很有帮助,然而,对于一些频繁用到的指令来说,就会感到使用繁琐。同时,在构建由 Vue.js 管理所有模板的单页面应用程序 (SPA - single page application) 时,v- 前缀也变得没那么重要了。因此,Vue.js 为 v-bind 和 v-on 这两个最常用的指令,提供了特定简写:
修饰符 (Modifiers) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault():

3.props

一个组件可以直接在模板里面渲染data里面的数据(双大括号)。
子组件不能直接在模板里面渲染父元素的数据。
如果子组件想要引用父元素的数据,那么就在prop里面声明一个变量(比如a),这个变量就可以引用父元素的数据。然后在模板里渲染这个变量(前面的a),这时候渲染出来的就是父元素里面的数据。

参考资料和推荐阅读

1.https://blog.youkuaiyun.com/yangfengjueqi/article/details/86536347
2.https://blog.youkuaiyun.com/m0_49989338/article/details/111308568
3.https://www.cnblogs.com/zouwangblog/p/11149588.html

欢迎阅读,各位老铁,如果对你有帮助,点个赞加个关注呗!~

业务画面:<template> <div> <CustomForm :form-data="formData" :rules="rules" @submit="handleSubmit"> <template #default> <CustomFormItem label="产品名称" prop="name" :required="true"> <CustomInput v-model="formData.name" placeholder="请输入产品名称"/> </CustomFormItem> <CustomFormItem label="产品描述" prop="description" :required="true"> <CustomInput v-model="formData.description" placeholder="请输入产品描述" type="textarea"/> </CustomFormItem> </template> </CustomForm> <div>产品名称值: {{ formData.name }}</div> <div>产品描述值: {{ formData.description }}</div> </div> </template> <script setup> import { reactive } from 'vue'; import CustomForm from '@/components/customForm'; import CustomFormItem from '@/components/customFormItem'; import CustomInput from '@/components/customInput'; const formData = reactive({ name: '', description: '' }); const rules = reactive({ name: [ { required: true, message: '产品名称不能为空' }, { max: 10, message: '长度超过10个汉字' } ], description: [ { required: true, message: '产品描述不能为空' }, { max: 200, message: '描述不能超过200个汉字' } ] }); function handleSubmit(valid, data) { if (valid) { alert('表单验证通过! 提交数据: ' + JSON.stringify(data)); } else { console.log('表单验证失败'); } } </script> 组件customForm:<template> <form @submit.prevent="submitForm" class="custom-form"> <slot name="default"></slot> <button type="submit" class="submit-btn"> 提交 </button> </form> </template> <script setup> import { ref, defineProps, defineEmits, provide } from 'vue'; // 添加依赖注入 provide('formData', props.formData); provide('formRules', props.rules); const props = defineProps({ formData: { type: Object, required: true }, rules: { type: Object, default: () => ({}) } }); const emit = defineEmits(['submit']); const formItems = ref([]); // 向子组件提供注册方法 provide('registerFormItem', (item) => { formItems.value.push(item); }); async function submitForm() { let isValid = true; // 验证所有表单项 for (const item of formItems.value) { const valid = await item.validate(); if (!valid) isValid = false; } emit('submit', isValid, props.formData); } </script> <style scoped> .custom-form { margin-bottom: 20px; display: flex; flex-direction: column; gap: 18px; } .submit-btn { margin-top: 15px; padding: 10px 20px; background-color: #409eff; color: white; border: none; border-radius: 4px; cursor: pointer; align-self: flex-start; } .submit-btn:hover { background-color: #66b1ff; } </style> 组件customFormItem:<template> <div class="custom-form-item"> <label v-if="label" class="form-label"> {{ label }} <span v-if="required" class="required-mark">*</span> </label> <div class="form-content"> <slot></slot> <div v-if="errorMessage" class="error-message">{{ errorMessage }}</div> </div> </div> </template> <script setup> import { ref, defineProps, inject, onMounted, watch } from 'vue'; const props = defineProps({ label: String, prop: String, required: Boolean }); const formData = inject('formData'); const formRules = inject('formRules'); const registerFormItem = inject('registerFormItem'); const errorMessage = ref(''); const currentValue = ref(''); // 注册到父表单 onMounted(() => { if (registerFormItem && props.prop) { registerFormItem({ prop: props.prop, validate }); } }); // 值变化监听 watch(() => formData[props.prop], (newVal) => { currentValue.value = newVal; validate(); }); function validate() { if (!props.prop || !formRules || !formRules[props.prop]) { errorMessage.value = ''; return true; } const rules = formRules[props.prop]; const value = currentValue.value; for (const rule of rules) { if (rule.required && !value?.trim()) { errorMessage.value = rule.message; return false; } if (rule.max && value?.length > rule.max) { errorMessage.value = rule.message; return false; } } errorMessage.value = ''; return true; } </script> <style scoped> .custom-form-item { display: flex; flex-direction: column; gap: 8px; } .form-label { font-weight: 600; font-size: 14px; } .required-mark { color: #f56c6c; margin-left: 4px; } .form-content { display: flex; flex-direction: column; gap: 4px; } .error-message { color: #f56c6c; font-size: 12px; height: 20px; } </style>组件customInput:<template> <div class="custom-input"> <input v-if="type !== 'textarea'" :value="modelValue" @input="handleInput" @blur="$emit('blur')" :placeholder="placeholder" :type="type" class="input-field"/> <textarea v-else :value="modelValue" @input="handleInput" @blur="$emit('blur')" :placeholder="placeholder" class="textarea-field"></textarea> </div> </template> <script setup> defineProps({ modelValue: [String, Number], placeholder: { type: String, default: "" }, type: { type: String, default: "text" } }); const emit = defineEmits(['update:modelValue', 'blur']); function handleInput(event) { emit('update:modelValue', event.target.value); } </script> <style scoped> .custom-input { width: 100%; } .input-field, .textarea-field { width: 100%; padding: 10px 12px; border: 1px solid #dcdfe6; border-radius: 4px; font-size: 14px; transition: border-color 0.3s; } .textarea-field { min-height: 80px; resize: vertical; } .input-field:focus, .textarea-field:focus { border-color: #409eff; outline: none; box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2); } </style> 哪写错啦,不显示
最新发布
07-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迅捷的软件产品制作专家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值