前言
最近在做一个很多复合表格需要展示和编辑的项目,想分享一下如何build屎山
本项目用的是vue3
+vite
+ts
需求
如图所示,有很多块区域,每块区域可以单独编辑保存,互不干扰。
点击编辑时,该区域内可以编辑的地方都变成输入框。
上图测试手机是否被监控只是简单演示,实际上有非常多格子,会有合并单元格情况,甚至一块区域有多个表格。
设计
- Block:区域组件,封装数据的请求和保存,封装标题和编辑按钮。
- Ta输入框显示不出来ble:表格组件,封装表格布测试你适合学心理学吗局的组件。
- Row:行组件,表示表格每一行的组件。
- Col:列组件,表示表格每一列的组件,就是单元格。
- Edit:编辑组件,编辑时变成输入框,不编辑时显示文本。
可以通过不停嵌套搭配row和col通信形成合并单元格。
开淦
Block组件内部请求拿到的数据,通过作用域插槽暴露出来给Edit绑定使用。
现在elementary是什么意思还差了一点,由于编辑状态封装在B嵌套查询sql语句lock里面,所以也要暴露isEdit
来控制Edit是否展示输入框。
我们可以发现这样做看起来挺蠢的,上千个格子,每个Edit组件都要显式的绑定一下isEdit
。
当时我正在苦思,突然想到element
的Form组件可以设置size属性,来控制里面的表单组件大小,然后读了一下源码发现是用Pro嵌套vide/Inject
实现的,于是我也这样做。vb输入框
// Block.vue
provide('isEdit', isEdit)
// Edit.vue
<template>
<el-input v-if="isEdit" :modelValue="modelValue" v-bind="$attrs" />
<span v-else >{{ modelValue }}</span>
</template>
<script setup>
const isEdit = Inject('isEdit')
</script>
到目前为止,项目还算正常。
迭代
现在业务提出需求,编辑过的区域需要高亮显示变红,而且是永久记录,事情开始有趣了
当时我们一群人输入框激烈的讨论了好久实现的思嵌套循环路。
{
id1: { a: { original: '123', fresh: '456' }, b: { original: '789', fresh: '456' } },
id2: { c: { original: '123', fresh: '456' } },
}
如上图所示,接口这样返回,这里表示id1
这条Element数据的字段a
和字测试抑郁程度的问卷段b
修改过,id2
这通信工程专业条数据的字段c
和字段b
修改过,只要在这里出现的,就意味着修改过。
为什么会有多个id呢,因为有些区elementary域可能是对象,自然就一个id,有些区域可能是数组,就是多个id,如下图所示:
如果是嵌套数组的话,就直接拍扁。
至于{ orelementaryiginal: '123', fre输入框不显示sh: '456' }
是为了日后预留,万一以后提出要看到以前修改的旧值的需求呢。
然后Block组件内置请求,通过不同的参数来获取该区域相应的编辑记录。
现在拿到数据了,那该怎么比对呢?
这是我一开始设想过的各种输入框不显示方式,传记录、id和属性名,在Edit里面判断或者直接判断。但无论如何看起来都很蠢,首先v-model里面已经通信技术专业绑定的变量写了amount
,然后判断是否编辑过还要再写一次amount
这样写js输入框虽然解决了重复问题,但是仍然要修改非常多代码,因为有非常非常非常多的格子,Element每个格子都要这样修改累死人了。输入框显示不出来
毕竟懒才是第一生产力,我决定尽量保持原输入框显示不出来来的业务代码不变,那Edit组件vb输入框到底怎么获取记录,id,还要属性名呢?
id利用v-for遍历Row
组件时设置kqq输入框ey属性来获取,如果不是遍历,那就手动设置key属性。
属性名通过截取v-model绑定的值来获取。
快来瞧瞧具体实现吧。
获取记录
// Block.vue
provide('records', records)
// Edit.vue
const records = Inject('records')
和isE通信地址是写什么地址dit
一样,通过Provide/Inject
传递
这里还算正常,下嵌套循环面全是骚操作了
获取属性名
// Edit.vue
<template>
<el-input v-if="isEdit" :modelValue="modelValue" v-bind="$attrs" />
<span v-else >{{ modelValue }}</span>
</template>
// 使用
<Edit v-model="item.amount" />
先来回顾一下Edit
组件是这样编写与使用,我并没有手动输入框绑定input
事件嵌套分类汇总怎么做再emit
出去,而是利用v-model
的语法糖自通信地址是写什么地址动生成更新事件,放在attrs中,然后内部v−bind=”attrs中,然后内部 v-bind=”attrs” 就可以绑定事件了,不知道的同学可以看看这个 v3.cn.vuejs.org/guide/migra…
// vue2
console.log(this.$attrs)
// vue3
setup(props, { attrs }) {
console.log(attrs)
}
我们可以打输入框印出来瞧瞧百度输入框
const fn = String(attrs['onUpdate:modelValue'])
const temp = fn.slice(0, fn.lastIndexOf('=')).trim()
const key = temp.slice(temp.lastIndexOf('.') + 1)
这样可以拿到<Edit v-model="item.amo测试智商unt" />
绑定的属性名amo嵌套if函数unt
了
-
modelValue
是vue3的v-modelementary是什么意思el
默认绑定的qq输入框变量名 - 别被控elements制台迷惑,
attrs['onUpdate:modelValue']
拿到的函数,我这里使用String()
把它vb输入框转为字符串 - fn打印出来就类似这样了
$event => item.amount = $event
,我们可以通过字符串剪切来获取amount
当然这输入框在哪里有大坑,我们等下再说
获取id
上面我们说到既然v-for
时要设置k输入框ey
值,而key
值是用id值来设置的嵌套原理有哪些实例,我们可以利用此来传递id
于是正常思路就通过props
设置key来获取,可您猜怎么着,居然拿不到!
然后我再把attrs
打印出来,也没有!
奇了怪了,这个key到底去哪了,于是vb输入框我通信把this打印出来
最终在$
或_
中里面的通信行程卡vnode
中找到
原来是被vue用作虚拟dom中使用了
// Row.vue
setup(){
const { vnode } = getCurrentInstance()
provide(businessId, vnode.key)
}
// Edit.vue
const businessId = Inject('businessId**')**
vue3我嵌套分类汇总怎么做们可以百度输入框这样获取key,并通信技术专业和之前一样,通过Provide/Inject
通信,不过这样做是有坑的,下面会说到
然后Edit
组件就可以判断是否编辑过了,完整的代码如下:
const records = inject<Ref>('records', ref({}))
const businessId = inject<string>('businessId', '')
const hasEdit = computed(() => {
if (!businessId) return false
const fn = String(attrs['onUpdate:modelValue'])
const temp = fn.slice(0, fn.lastIndexOf('='))
const key = temp.slice(temp.lastIndexOf('.') + 1)
return !!records.value[businessId]?.[key]
})
?.
是es6可选链操测试纸怀孕图片作符,不懂的童鞋可以查一下
虽然我们拿到id了,但还可以做的更好
首先封装成hook
然后在Row
和Table
组件中使用,因为有些并不是数测试抑郁症的20道题组,就一个对象,而且有多个Row
,直接在Table
设通信一次id就方便许多。
坑
拿不到id
这个时候坑就来了,有很多地方居然拿不到id, 这就牵扯到通信地址一个问题了,大家想一想,如父组件Provide
一个变量叫a,然后子组件也Provide
一个变量叫a,那请问孙输入框组件Inject接收到的变量a到底是谁的值?
然后我试了试,答案拿到的是子组件,这是符合直觉的,就像样式position: absolute
一直向上找到最近的position: relative
,还有访问对象的属性一直跟着原型链向上找到为止。
出问题的原因是,虽然直通信技术接在Table
设置key,Row
不测试手机是否被监控用设key了,可Row
还是在Pelement滑板rovide
,所以要改成这样:
加个判断,只有当设置了key
值才Provide
有嵌套if函数些格子是没法正常反显
<Edit v-model="a ? item.b : item.c" />
这样写的话,我们上面的获取属性名的方法就失效了,所以就改嵌套原理有哪些实例成这样即可:
<Edit v-if="a" v-model="item.b" />
<Edit v-else v-model="item.c" />
其实还有更好的解决方法,但我懒了
测试环境所有的格子都是没法正常显示
经element翻译过排查发现,是在获取属性名的时候出问题了:
// dev
e => item.a = e
// test
e=>item.a=e
千万别利用空格截取字符串,因为只有开发环境才有空格,打包后的代码因为有压缩,所以是没有空格的
为了兼容不同的环境,所以可以使用trim()
去除空格
结束语
其实这篇文章我主要分享的是嵌套分类汇总怎么做利用key传递属性和截取v-model绑定的属性名这两个歪门邪道,就本身这块业务来说有非常多的点我没有说,通信大数据行程卡比如万一绑定的属性是a.b.celement滑板.d
,那样该怎么做呢?编辑的时候格子太多,一下子变成输入框可能会卡顿,所以使用requestAnimationFrame
分批更改是否编输入框辑的状态。再比如,如果某个区域有多个table
的话,那是不是该封装一个专门用来provide
key的组件来包裹更方便嵌套原理呢,不用每个table
都设置key等等非常多问题。
最后祝大家虎年虎虎生威,愿大家只用拉屎山第一坨翔,不用接着别人的拉