在下面的例子中,使用 vue3 的计算属性,我们应该将“computed”放在最外层还是单独对数据进行“computed”?哪个表现更好?
const arr = computed(()=>[
{options:cpuData.map((item)=>({...item,name:'tom'}))},
{options:disData.map((item)=>({...item,name:'jerry'}))},
{options:memoryData.map((item)=>({...item,name:'oh'}))},
{options:testData.map((item)=>({...item,name:'test'}))},
{options:[{name:'test'},{name:'test2'}]},
{options:[{name:'test'},{name:'test2'}]},
{options:[{name:'test'},{name:'test2'}]},
{options:[{name:'test'},{name:'test2'}]},
])
const arr = [
{options:computed(()=>cpuData.map((item)=>({...item,name:'tom'}))),
{options:computed(()=>disData.map((item)=>({...item,name:'tom'}))),
{options:computed(()=>memoryData.map((item)=>({...item,name:'tom'}))),
{options:computed(()=>testData.map((item)=>({...item,name:'tom'}))),
{options:[{name:'test'},{name:'test2'}]},
{options:[{name:'test'},{name:'test2'}]},
{options:[{name:'test'},{name:'test2'}]},
{options:[{name:'test'},{name:'test2'}]},
]
1
vivipure 2022-11-06 00:13:05 +08:00
直觉第二种,但是写还是写第一种,没啥必要。
|
2
wu67 2022-11-06 00:38:30 +08:00
// 我一般这么写
const temp = computed(() => [ { options: cpuData.map(item => ({ ...item, name: 'tom' })) }, { options: disData.map(item => ({ ...item, name: 'jerry' })) }, { options: memoryData.map(item => ({ ...item, name: 'oh' })) }, { options: testData.map(item => ({ ...item, name: 'test' })) }, ]) const constantData = [ { options: [{ name: 'test' }, { name: 'test2' }] }, { options: [{ name: 'test' }, { name: 'test2' }] }, { options: [{ name: 'test' }, { name: 'test2' }] }, { options: [{ name: 'test' }, { name: 'test2' }] }, ] const result = computed(() => { return temp.concat(constantData) }) |
3
wu67 2022-11-06 00:47:47 +08:00
一般情况下, 纯展示的页面, 前端不需要考虑性能问题.
但是当你的数据量到达某种程度之后, 就需要考虑空间换时间了, 例如: 1. 你的一维数组的行数到达了千量级, 动不动就是几千行的数据 2. 你的数据需要对 2 维数组进行处理, 例如 2~6 千行, 每行里面还有 3 4 百列的 3. 3 维或者更复杂的玩意... 到了这种地步之后才需要考虑是否需要优化. 可能实际情况会有所不同, 不能纯纯的靠空间换时间, 因为可能占用内存过高, 浏览器本身卡了, 不是数据便利的卡... |
4
zcf0508 2022-11-06 00:51:17 +08:00 via Android 1
一,第二种的 arr 不是响应式的
二,如果你不需要 arr 变更触发响应式的话,那第二种只会在读取 computed 的 index 才会触发响应式,其他的不会触发响应式,理论上性能更好 三,就这几行数据应该不会有什么性能的差别 |
5
Finnn 2022-11-06 01:33:39 +08:00
其实你第一种应该是无效的?
因为 computed 并不能自动深度响应对象内部值的变化 |
6
chenjiangui998 2022-11-07 09:40:01 +08:00
@Finnn computed 默认就是深度响应的
|
7
xintianyou 2022-11-07 10:55:17 +08:00
@Finnn 你记错了吧,vue2 的 watch 才是默认不会深度响应
|
8
Finnn 2022-11-12 22:32:52 +08:00
@xintianyou 只是题主的 computed 返回的数据结构是新构建的, 不存在监听已有引用类型, 如果 computed 一个对象内部的变化自然是不行的
|
10
chenjiangui998 2022-11-15 11:00:07 +08:00
@Finnn 你这个例子不正说明了 computed 是深度响应的吗, 如果不是, push 对象界面根本不会响应
|
11
chenjiangui998 2022-11-15 11:02:35 +08:00 1
@Finnn 而且直接 return author.books.map(() => '1'), log 也会多次执行
|
12
Finnn 2022-11-15 14:25:21 +08:00 1
@chenjiangui998 你可以打开控制台呢, 看看 computed 了没有
|
13
Finnn 2022-11-15 16:06:25 +08:00
@chenjiangui998 你这例子可差远了, 完全不是一个概念
|
16
mizuhashi 2022-11-17 21:53:27 +08:00 via iPhone
@Finnn 我覺得這個說法不對,computed 會觀察所有「用到的」的屬性,但本身不一定會總是重復運行,在保證返回結果正確的情況下。你的例子裏沒有重復執行,但是返回的結果是正確的,我的例子裏如果不重復執行就不能確定結果正確,所以就重復執行了
|
17
Finnn 2022-11-17 22:00:58 +08:00
@mizuhashi 因为你监控了 books.length, 一个变化的基本类型, 上面 return author.books.map(() => '1') 的同样是监控了 books 的每一个值的变化
|
18
Finnn 2022-11-17 22:04:55 +08:00
@mizuhashi 你这说法更不对,怎么会不能确定结果的正确性.
computed 之所以响应是因为其回调内部的所有监控值变化了才会执行, 直接响应一个对象自然是不会深度检查内部的各个值的变化的 |
19
mizuhashi 2022-11-17 22:58:51 +08:00
@Finnn 「深度檢查內部各個值」的具體標準是什麼?如果引用了.length ,那麼 books 的元素變化會導致 length 變化,所以 computed 也重復執行了,這在我看來應該算深度檢查了內部值的。如果只是引用了.books ,這個 computed 關心的就僅僅是 books 返回的數組的引用,由於這個引用沒變,所以 computed 不會重新執行。
如果要證明「 computed 不會監視深度的數組內容變化」,那麼應該構造這麼一個 computed ,其監視了並使用了數組的內容,但是當數組改變的時候,這個 computed 沒有觸發。如果只是.books ,並沒有使用數組的內容,而使用了數組內容的例子(如.books.length ),computed 是有重新觸發的,所以還需要一個有效的反例才能證明原命題。 |
20
Finnn 2022-11-18 00:28:55 +08:00
@mizuhashi
1 , 我没有说「 computed 不會監視深度的數組內容變化」,是 computed 不会自动深度搜集未监控的引用的内部属性变化, 2 , “那麼應該構造這麼一個 computed ,其監視了並使用了數組的內容,但是當數組改變的時候,這個 computed 沒有觸發。” 很简单,只需要我修改的数组项是引用类型就行了 : https://sfc.vuejs.org/#eNp9Uk1v2zAM/SuELnaBxA7anYzEQIsB+wB6G4YBUQ+KzcTubEkQJQ+F4f8+ynbaYV8XW+QjH/lIjuLe2mwIKAqxp8q11gOhD7aUuu2tcR5GcKgq3w64gcr0NnisYYKzMz0knJlILXVlNHlQwTfGweE1Ix2lBtCqxwKSz6bR8N5gsonOkzHfqYBjfAMkXwPCLWzhvh6UrrjCh9DWa+gK3zH8oKit/oK9Y+xLg/D4Qh7dyxU7PsU/f6YbqfMc1JsCh+dr2zacupYarB9iT49IpC7IKq6xaXoDhxJmLTHDdJh15pJKcY2QgvmlX/Rns7SsQ33xTcxxPFCn1+ks6NIRT/qT5n4H1XGNQzlX+DXsePeU2UBNOov8lnDOtLnd7Xb82OfLvnhTbHjsbac8sgWwt+VHRW+61mHv87hWhskqXY7jP4RPE1PHiFjjlVdsxHIQ217Z7JmM5pOZG5YrQFIUy5Cijy8j2lI03lsq8pzOVTy0Z8qMu+T8ylzQvu0xQ+q3J2d+EDomlmJd3syRs3NAt3Woa3To/sf5W+gfvJF24gmK6SeJHwQE |
21
Finnn 2022-11-18 00:40:41 +08:00
@mizuhashi 我认为你理解的深度并不是 vue 概念上的 watch 意义的深度,watch 的深度是自动响应引用类型内部所有值的变化的,computed 首先是惰性的,然后是只响应回调函数内所有声明监控的基本类型的变化, 就像 watch/computed:“author.books[3].length” 一样直达某个对象内部的一个基本类型的变化,这不是 vue 意义上的深度
|