mission:home和city之间共享,即在city中切换城市,home会变化。
用到Vuex,这是官方推荐的数据框架。
先在vscode中创建上图虚线部分的内容,暂且称其为store,我们创建一个state区域,存放公用数据
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '北京'
}
})
还要在main.js中,创建根实例new vue中,把store传进去,这样每个子组件都能使用这个数据
由于之前是ajax来传递数据,现在不需要了,可以把index.json中也去掉city,所以在home中可以把与city有关的代码都去掉, 回到header中,props里的city也去掉,并把插值表达式改为{{this.$store.state.city}},同样把city里的list组件的当前城市内容也改为{{this.$store.state.city}}。
想要实现点击city页面的热门城市,在home中变成一样的城市,那么就要更改最开始的state里的city的值。
按照官方文档流程图,组件调用actions,actions调用 mutations, mutations再去修改state:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '北京'
},
actions: {
changeCity(ctx, city) {
ctx.commit('changeCity', city)
}
},
mutations: {
changeCity(state, city) {
state.city = city
}
}
})
其实这里组件可以直接调用mutations就可以,把actions可以去掉,
在组件中不用dispatch,直接commit调用mutations。list.vue:
methods : {
handleCityClick (city) {
this.$store.commit('changeCity',city)
// alert(city)
}
},
同样,对于list和search列表中的城市,可以把@click相关的代码复制过去,从而实现点击阿拉尔等全国城市也会在home里切换。
接着想要改变城市之后实现页面的跳转,用到vue.router,在每个组件(list和search)中:
methods : {
handleCityClick (city) {
this.$store.commit('changeCity',city)
// alert(city),
this.$router.push('/')
}
},
这样就可以点击城市后,直接回到home!
此时还有问题,当首页刷新的话,定位的城市又回变成vuex的state代码我们给定的原始城市。
我们用localstorage来解决,实现本地cookie(存储)
export default new Vuex.Store({
state: {
city: localStorage.ciyu || '北京'
// 逻辑运算符 A||B 若A能取到,则A,若A是false则peking!
},
// actions: {
// changeCity(ctx, city) {
// ctx.commit('changeCity', city)
// }
// },
mutations: {
changeCity(state, city) {
state.city = city
localStorage.city = city
}
}
})
但如果用户使用隐私模式或取消cookie,就会异常,所以加上这样的代码:
let defaultCity = '北京'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {}
export default {
city: defaultCity
}
可以把state和mutations都在单独的js文件中写。
浏览器提示:
chrome性能优化的一个警告,不用管,继续写代码就好了,手机上不会有这个问题的。
下面对代码再优化,import { mapState } from 'vuex',通过展开运算符,把vuex的city映射到计算属性中,映射名字是currentCity,再把div中的也改为currentCity
computed: {
...mapState({
currentCity:'city'
})
},
<div class="button">
{{this.currentCity}}
<!-- {{this.$store.state.city}} -->
</div>
达到简化效果,其余的插值表达式中的$store写法都可以改成这样同理。
补充:
①官方文档中的getters可根据state中的数据进行一些计算,类似于computed。
本次代码中,利用getters对home.vue右上角的城市进行修改,让其显示两次,在index.js里添加getters,在home的header中写成{{this.doubleCity}}
getters: {
doubleCity(state) {
return state.city + '' + state.city
}
}
②module可以对复杂的mutations和actions进行拆分,可以提高可维护性。
最后一步!代码入库!