问题起因
最近做项目遇到了一个问题,如下图:
在menu中动态生成了如上几条item,当我点击每条item,会拿到当前item的id,也就是歌单的id,去向后台请求对应id的歌单里面的数据,然后展示出来,展示组件的路由命名为userplaylist-detail。
每次点击都会执行如下代码:
this.$router.push({ name: "userplaylist-detail", query: { id } });
也就是往路由中添加路由userplaylist-detail,vue的组件监测到路由发现变化,便会加载路由对应的组件展示出来,这里的问题是:第一次点击item的时候,可以显示歌单数据,当点击另一个item时,还是显示第一次点击的item的数据,虽然数据改变了,但是页面没有重新渲染。
出现以上问题的原因是vue的一个特性:组件就地复用。因为上述几个item对应的路由都是一样的,组件监测到路由并没有发现改变,所以不会重新渲染页面。
解决办法
既然组件因为路由没有改变而不重新渲染,而我们又需要保持路由一致,那我们就收到刷新组件,这里使用v-if指令来刷新组件,通过依赖注入来解决刷新问题。
在根组件(App.vue)中,写入如下代码:
我们通过属性isRouteActive来控制组件的渲染,然后在menu.vue组件中写入如下代码:
分析上述代码,其实关键就是子组件menu.vue调用了父组件App.vue提供的方法reloadRouterView,而reloadRouterView方法则负责改变isRouteActive的值来达到渲染组件的效果。
上述代码中框住的部分有两个很关键的词,provide和inject,它们就是构成依赖注入的关键。其实依赖注入的作用就是实现父子组件之间的通信,让子组件可以调用父组件的方法来改变父组件的数据。
依赖注入
我理解的依赖注入就是:两个有依赖关系的双方,比如说父子组件,子组件依赖父组件,父组件通过provide提供子组件需要的属性或者方法,而子组件通过inject把父组件提供的属性或者方法注入到自身中,这样就能像使用自身属性或者方法一样使用父组件的属性或者方法。
具体可以查看官方文档:https://cn.vuejs.org/v2/guide/components-edge-cases.html#%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5
所以说,我们在开发中遇到的许许多多的问题都能在官方文档中找到答案,所以还是要多看看文档。