小白使用 vue2.6.10 的 v-for 遇到的一个问题从而引发了一个对于这一行业的思考,希望有人可以开导我

2019-08-08 21:07:20 +08:00
 zazalu
我遇到的问题是这样的,我描述下:

问题 1:

父组件使用"props"传递一个数组"items"给子组件,

子组件使用 v-for 处理这个"items"来循环打印"item"中的 content 字段内容,

过了一段时间后,我会去触发一次父组件的 items 更新,类似如下代码:

```
this.items = this.items.concat([{id:11, content: "第十一条通知"}])
```

因为 vue 官方文档说过,如果是非变异方法改变数组内容,直接使用"replace a array"的方式,也就是我上面的方式.

所以我认为我的代码是没问题的.

但是事实却痛击了我, 不知道为啥 v-for 循环并没有刷新数据.

于是我先使用{{items}}检查了 props 的数据是否已经更新.

结果是{{items}}确实已经更新了第十一条通知的内容进去.

并且我使用 slice 方法去更新数组内容,是可以的, 就唯独 concat 方法不行

问题 2:

问题 2 是我在问题 1 后出现的一个新问题.

我将{{items}}放到了 v-for 所在组件的后面(问题 1 中我是放在最前面验证的), 这时候神奇的事情发生了.

v-for 居然更新了内容.

所以 vue 内部到底发生了什么... 我该怎么去解... 文档我也上下翻了好几次, google,baidu 了类似问题,但是很遗憾没有和我遇到一样问题的伙伴出现

问题 3:

我依旧不服, 想着在单元测试中也试试会不会存在这个问题,

所以我使用 vue-cli 创建了一个超级简单的 vue 单组件项目作为我的单元测试项目, 然后我将一些核心代码移了过去,重新测试了下

(我强调下, 单元测试的代码肯定是和我真正项目中用的是一样的! )

结果是没有任何问题, v-for 工作完全正常!

我.................................................................................



总结:

到最后, 我没法搞定这个问题(我采用的是问题 2 中描述的折中但是非常不优雅的写法), 感觉内心非常的难受, 关电脑, 回宿舍, 简单的吃了下晚饭, 吃着吃着差点掉眼泪 , 感觉写代码也至少一年多了, 这类问题以前在使用 jsp 的时候其实也遇到过类似的. 结果,一年过去了, 我连这种问题都没法搞定, 还谈什么设计模式,算法呢, 一年来感觉压根没有多大提升, 除了找资料和看英文文档能力感觉比以前强了以外, 能做的无非只有 crud.

这么一个问题, 搞得我焦头烂额,浪费了一下午+晚上几个小时的青春. 我想真诚的问下各位前辈们, 是不是我这种人不适合做程序员
8567 次点击
所在节点    Vue.js
121 条回复
shintendo
2019-08-09 10:40:13 +08:00
@yixiang
实际使用中,这种监听不到的边际情况其实影响很小。首先对象,只有新增的属性才会监听不到,但好的实践本就应该在一开始把数据结构定义好,实在需要中途新增属性也有$set 这种方式。其次数组,像 push, splice 这种方法 vue 都做了劫持,只有通过数组下标修改才会监听不到,但我实在想不到什么情况会用下标修改。
等 vue3 用 proxy 重写以后,这些边际情况也没有了。
zazalu
2019-08-09 11:04:07 +08:00
@shintendo 啊! 大佬! 我上传了一个最小复现 demo! 这次是真的来求助了! 弟弟真的搞不懂啊
zazalu
2019-08-09 11:04:26 +08:00
@shintendo 在主题的 APPEND 里
CDL
2019-08-09 11:09:35 +08:00
push 不就行了,这个 concat 后再赋值是什么意思
zazalu
2019-08-09 11:11:45 +08:00
@CDL concat 不会影响原数组,而是返回一个新数组 所以要赋值回去.
实际代码中数据量大,所以 push 要循环, 直接用 concat 方法方便..
我也用了 push,也是不行的!
zazalu
2019-08-09 11:16:45 +08:00
@karnaugh 我上传了最小复现 demo,在 APPEND 里, 这次是货真价实的求助了.
liximomo
2019-08-09 11:17:08 +08:00
@zazalu Mac 下 chrome 无法复现,请说明你的环境
zazalu
2019-08-09 11:21:06 +08:00
@liximomo 哭了! mac 下正常吗. 我也有有台 mac,我试试. 我的环境在 APPEND 里说了
zazalu
2019-08-09 11:23:58 +08:00
@liximomo 我录个小视频然后转 gif 发上来,给您看下
CDL
2019-08-09 11:25:16 +08:00
@zazalu push 不行只能说明你数据有问题,你这个 concat 应该也是一样的情况,concat 返回的数据包含了原始数据的拦截器属性,直接赋值后导致设置拦截器属性失败,这里算是 bug 还是边界情况我没看源码就不清楚了
zazalu
2019-08-09 11:30:14 +08:00
yinjy
2019-08-09 11:30:59 +08:00
之前遇到了类似问题,好像是用 this.$set()来更新数据就可以了
Sendya
2019-08-09 11:35:04 +08:00
@zazalu Windows 下 chrome , firefox, edge (均 Latest )无法复现
zazalu
2019-08-09 11:36:29 +08:00
@liximomo 啊。搞错了 这个好像是加密图片。 我自己本地转成 gif 然后搞到 guthub 上去吧。 无视我上面的那条回复就行。
zazalu
2019-08-09 11:40:43 +08:00
@Sendya 我 windows 上复现了,chrome 版本肯
也不低。 你页面上两个地方(模板语法和 v-for 语句)全部都会更新吗?
Sendya
2019-08-09 11:41:32 +08:00
另外楼主要不要试试这样写法,好看点 哈哈哈

```
onClick() {
this.fatherItems = [...this.fatherItems, {
id: 3,
content: "第三条通知"
}]
}
```
Sendya
2019-08-09 11:46:49 +08:00
是用了 `Drawer` 之后才不能更新的吗?
getElementBy1d
2019-08-09 11:46:51 +08:00
建议好好读一下官方文档 有很多问题官方文档已经写了
lxmfly123
2019-08-09 11:46:57 +08:00
Mac Chrome 可复现。
这个极有可能是 iView 的锅。那个 NewMessage 组件里,只有一个 iView 的 Drawer 组件,我把这个 NewMessage 换成不含 Drawer 的组件,就一切正常了。
具体怎么回事,估计要看 iView 的源码了。
zazalu
2019-08-09 11:47:26 +08:00
@Sendya js 真的很灵活啊.我没想到可以这么写

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/590284

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX