前言:不当心发现线上一个bug,看了下代码,了解到由于用Vue.nextTick的场景不对,在此作个记录。html
具体场景是,修改文件夹名称时,弹出一个修更名称的弹出框vue
此时文件名“啦啦啦”会带到编辑文件夹的弹出框中。修改保存后,文件名变成“啦啦啦123”,而后再次修改文件夹名,结果:异步
此时为何文件名没有带过去?this
经过查看代码了解到 编辑文件夹 弹出框是一个子组件,父组件触发修改文件名的事件时,经过 folderToBeRenamed 传递新的数据spa
this.$nextTick(() => { this.folderToBeRenamed = newFolderName })
子组件再经过props 获取 folderToBeRenamed调试
并用 watch 监听code
watch: { folderToBeRenamed () { this.folderName = this.folderToBeRenamed.folder_name } }
folderName就是子组件要获取的数据,看起来好像有道理,但是为何只起到一次监听做用?经过调试发现,只有第一次点击修改文件名,watch里的事件会执行;后续无论folderToBeRenamed是否改变都不会执行watch里的事件了。htm
先看下官网的解释事件
有点难懂o(╯□╰)oip
看到知乎上的解释:
HTML: <div id="testCount" v-html="message"></div> //改变数据 vm.message = 'changed' //想要当即使用更新后的DOM。这样不行,由于设置message后DOM尚未更新 console.log(document.getElementById('testCount').innerHTML) // 并不会获得'changed' //这样能够,nextTick里面的代码会在DOM更新后执行 Vue.nextTick(function(){ console.log(document.getElementById('testCount').innerHTML) //能够获得'changed' })
因此 vue的nextTick的做用相似setTimeout,再添加一个新的空的异步事件,执行完异步事件后调用callback。
因此回到咱们前面的bug,能够明白,子组件只感觉到folderToBeRenamed的一次变化,就至关于for循环里的setTimeout
for(var i = 0; i < 3; i++) { setTimeout(function() { console.log('timeout' + i); }) }
最后输出的i都是3,也就是只能感觉到i从0变为3 此次变化。
这里的逻辑原本是比较简单的,父组件传值,子组件直接获取就能够了。为何须要父组件用Vue.nextTick(),子组件用watch监听,我也不太清楚。由于本身对Vue.nextTick()用法也不太熟,因此在此记录,谨防踩坑_(:з」∠)_