当前位置: 首页 > Web前端 > HTML

元素的form形式应该这样配置,以

时间:2023-03-27 22:39:08 HTML

为设计目标。我们希望能够让表单的内容、校验规则,甚至表单的样式和格式更加规则化和可配置化,以便后面通过构造json来实现。表单甚至可以用于实现拖放式构建表单。Theparameterssimpleandlevelofjsonaspossible,减少json的参数,字段更加语义化。自由度json其实是一套规则,自由度不多,但是Vue给我们提供了更多的自由度,比如h函数,比如动态组件,我们可以通过这些方式来实现更高的自由度。我的实现流程表单项的格式设计是第一步。让我们设计一个基本格式。在这个JSON中,字段名称是非常简单的英文单词。我特地把validationrule规则放到了每个子item中吧,这样也比较直观。constoneItem={key:'title',title:'小说标题',component:'el-input',props:{placeholder:'请输入你的名字'},rule:[{required:true,trigger:'blur',message:'required'}],}复制代码在这种格式中,有两个重要的东西,key和component。key其实就是你表单中数据的字段名,component就是你指定的编辑组件。这里我们可以直接使用字符串,其实我们可以使用Vue的动态组件来实现更灵活的应用。例如,我们可以改变一个组件库的输入组件import{Input}from'@varlet/ui'import'@varlet/ui/es/input/style/index.js'constoneItem={component:Input}copycode这个时候我们需要动态组件来渲染它,所以我们可以这样写来渲染它。当组件是字符串时,比如el-input,我们渲染元素的输入组件。至于v-model,我省略了复制代码v-bind的妙用每个组件库的组件参数都不一样,我们有些属性可能用不到,比如el-input有这个属性prefix-icon,是前缀图标,其他组件库可能没有。那我们需要把所有组件库的所有属性都写在json里吗?我在前面的json中设计了一个props字段,里面存放的是组件库的属性,或者说我们需要传递给组件的值。这时候vue为我们提供了一个非常方便的功能,可以直接使用v-bind传入一个对象,它会自动帮我们绑定属性。比如写constprops={a:1,b:2}复制代码vue会自动处理如下,这就是v-bind的神奇之处。当然使用renderFunction也可以达到这个效果,大家可以自己试试复制神奇的代码computed:implementv-model我们来看看数据问题。Vue提供了方便的v-model,方便我们实时响应修改后的值,我们可以自己实现一个自定义的v-model。它的基本原理是这样的,我们先把父组件传给子组件,然后子组件通过事件告诉父组件修改这个值。大概实现是这样的exportdefault{props:['modelValue',//v-model'a'//v-model:a],emits:['update:modelValue','update:a'],方法:{add(){this.$emit('update:modelValue',this.modelValue++)this.$emit('update:a',this.a++)}}}复制代码但是这段代码有一个问题,我们不能在vue中实际修改props,也就是说this.modelValue++会报错,那么这个问题怎么解决呢,答案是computed,computed其实是可以修改的,我们可以指定它的set方法,这样就避免了修改props的问题,从而实现了v-model{computed:{num:{get(){returnthis.modelValue},set(val){this.$emit('update:modelValue',val)}}}}复制useAttrs的妙用我的组件里有这么一个功能,upload。这就涉及到回调函数的问题了,也就是说我上传之后,连方法名都包含进去了,这样比较灵活。比如我们在json中添加一个新的字段,{uploader:{emits:'handleUploadCover',}}复制代码然后我在渲染的时候会绑定这个事件到它上面,那么我们如何获取这个事件的函数并调用呢?复制代码在vue3中,我使用了useAttrs。需要注意的是这里vue3好像和vue2有些区别。在vue3中,attrs获取未注册的值。比如你在emits中声明,这里是获取不到的,但这正是我想要的。我们可以随意指定事件名称。constattrs=useAttrs()/*Returnvalue{onHandleUploadCover:function(){xxx}}*/复制代码可以看到这里可以获取事件,只是名字略有不同。在这里你可以处理它。表单验证中最重要的是表单验证。首先,在我之前的设计中,表单验证的规则是分布在各个子项中的,所以我们需要对其进行整合。这个我就不细说了,很简单。我直接使用的验证方式是el-form的验证,只是封装而已。需要注意的是,如果是使用脚本设置,需要使用defineExpose导出这个方法constvalidate=()=>newPromise((resolve)=>{this.$refs.form.validate((isValid)=>resolve(isValid));})defineExpose({validate})复制代码上传文件上传文件这里我其实是拦截了element的上传,只使用了它选择的文件的功能,其实自己也可以实现。因为我上传中间需要加很多参数和验证,所以我用了before-upload的方式,主动拒绝了。beforeUpload(file,item)":show-file-list="false"v-bind="item.uploader.props">点击上传constbeforeUpload=(rawFile,{key,uploader})=>{/*执行逻辑,其实就是调用uploader.emits中的方法*/returnPromise.reject()}复制代码代码总结我把demo放在这里,有空我整理一下,发个npm包时间以后。stackblitz.com/edit/vue-m8...这次封装这个组件学到了很多东西,一些细微的vue3知识点,比如v-bind。但是我也知道这种封装也存在一些问题或者争论。我应该使用json吗?之前看了一篇封装el-table的文章,反对使用json的原因有两个:json结构太大,json结构不利于接手代码的人使用。先说第二点。我觉得这个问题可以通过良好的结构定义来缓解,但是你的功能封装就没有学习成本吗?我觉得json封装其实就是每次都是复制粘贴。反之,学习成本更低,但开发成本会更高。你需要处理各种错误的值和错误的结构,所以结构越简单越好,甚至可以扁平化。json并不大,但我们的表单很大。如果表格中有数百个项目,无论您如何编写它都只会很大。因此,建议分表及时上报。是否需要v-model在我这次的包中,我是通过v-model实时返回数据的,但是我写到最后的时候,我觉得表格的数据不需要是实时的,因为我们什么需要的不是实时数据,而是验证后的正确数据。所以我认为我们可以公开一个getData方法并返回经过验证的正确数据。性能问题在实际使用中,我发现这种封装方式似乎有点卡顿。目前不知道问题出在哪里,有待研究。