这所有要从最近接手了一段祖传的代码开始说起。。。
起因和解决形式
作为一名前端老司机(自封),也不晓得是不是招我进来的老哥看上了我的我的项目经验还是老板的无心为之(年底都是老我的项目优化),总而言之我接手了一段老的 n 手(n>3)代码,尽管提交工夫是一年前,然而这 ES5 语法好像是 15-17 年的产物,让我回想到我刚工作的时候接触的网页,有种亲切的感觉(不是)。
在一顿梳理之后,我把问题的指标锁定在了一对父子组件上,子组件内有两个函数:
- 依据 watch 监听的函数,在父组件上用 data 管制组件展现的同时,咱们要在这里做一个 localStorage.setItem 和赋值子组件 data 的操作,在每次关上时传入以后定位城市。
- 一个须要 localStorage.getItem 获取数据而后做申请与后端交互的函数,原有逻辑会在父组件上通过 ref 去调用,为了逻辑拆散和防止反复调用,不把(2)退出到(1)的逻辑里
如果是 react 的 setState,我会抉择把(2)函数传入 setState 的回调,然而这可是 vue2 啊。在他们两个同时调用的场景下,因为通过了 watch 的拦挡,(2)必定会先于(1)触发。于是,咱们就在(2)调用 localStorage.getItem 和赋值子组件 data 的时候在 Storage 外层包裹上 $nextTick,localStorage.getItem 就能正确拿到数据了,完满~
父组件调用:
this.isshowseach = true;
this.$refs.seachadrFuc.mapData(localStorage.getItem("currentCity"));
子组件 watch 和 methods:
watch: {
showOnoff: {handler(val) {console.log("showOnoff 触发");
// 默认把以后定位的城市填入
this.selectCity = this.city;
localStorage.setItem("selectCity", this.selectCity);
}
},
},
},
methods: {mapData(val) {console.log("mapData 触发");
this.$nextTick(() => {this.getupList();
});
},
getupList() {console.log(this.selectCity) // 胜利赋值为 this.city
}
}
剖析:
watch 这里应用的 Object.observe(proxy 同理)监听,属于微工作,所以会比同步工作 window.localStorage.getItem 后执行。
$nextTick 的原理是 Promise.then、MutationObserver 和 setImmediate 又或者是 setTimeout(fn,0), 都属于宏工作,因而 window.localStorage.getItem 和赋值子组件 data 包裹上宏工作 $nextTick 后,又会比 watch 后执行。