Vue2.5 旅游项目实例17 城市选择页-使用Vuex实现数据共享
创建分支:city-vuex
拉取到本地并切换分支:
git pullgit checkout city-vuex
我们要做的功能是在城市列表页,选择某一个城市后,首页右上角的城市也跟着变化。
安装Vuex:
npm install vuex --save
在src目录下,创建store文件夹,新建index.js文件:
import Vue from 'vue'import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '北京'
}
})
然后打开main.js文件,添加:
import Store from './store'new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
打开Home.vue文件,可以看到给 home-hander 组件传递了一个city,现在我们改为:
<home-header></home-header>
现在刷新首页,右上角的北京没有了,只有一个下箭头。
然后打开Header.vue文件:
<div class="header-right">{{this.$store.state.city}} <i class="iconfont arrow-icon"></i></div><script>
export default {
name: 'HomeHeader'
}
</script>
这时首页右上角的北京又显示出来了。this.$store.state.city 取的是store里存储的默认值:北京
再打开city下的List.vue文件,把当前城市改为读取stroe:
<div class="button">{{this.$store.state.city}}</div>
这时候我们可以把store/index.js中 state.city 的默认值改为:上海
然后可以看到首页和列表也中的当前城市,都变为了上海。
下面我们希望点击热门城市,可以跟着变化,给每个热门城市添加点击事件:
<div class="button-wrapper" v-for="item in hotCity" :key="item.id"@click="handleCityClick(item.name)">
<script>
export default {
methods: {
// 热门城市点击事件
handleCityClick (city) {
this.$store.dispatch('changeCity', city)
}
},
}
</script>
然后打开store/index.js文件:
根据上图,首先组件调用 actions,actions 调用 mutations, mutations 去改变数据。
import Vue from 'vue'import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '北京'
},
actions: {
changeCity (context, city) {
context.commit('changeCity', city)
}
},
mutations: {
changeCity (state, city) {
state.city = city
}
}
})
这时候点击热门城市,当前城市跟着变化,首页右上角的城市也变化。这就实现了首页和城市列表页的数据共享。
但是我们刚才这个过程里没有任何的异步操作,而且操作也很简单,不是一些批量的数据操作,所以组件没必要去调用acions,可以直接去调用 mutations,所以我们可以修改为:
import Vue from 'vue'import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '北京'
},
// actions: {
// changeCity (context, city) {
// context.commit('changeCity', city)
// }
// },
mutations: {
changeCity (state, city) {
state.city = city
}
}
})
然后Lits.vue修改为:
// 热门城市点击事件handleCityClick (city) {
// this.$store.dispatch('changeCity', city)
this.$store.commit('changeCity', city)
}
OK,功能一样可以实现。
下面把城市列表也添加上点击事件:
<div class="item border-bottom" v-for="v in item" :key="v.id" @click="handleCityClick(v.name)">{{v.name}}
</div>
当然搜索的时候点击城市也要添加点击事件,打开Search.vue:
<li class="search-item border-bottom" @click="handleCityClick(item.name)"v-for="item in list" :key="item.id">
<script>
export default {
methods: {
// 切换城市点击事件
handleCityClick (city) {
this.$store.commit('changeCity', city)
}
},
}
</script>
OK,功能实现了。
下面就是在点击切换城市后,直接跳回到首页:
handleCityClick (city) {this.$store.commit('changeCity', city)
this.$router.push('/')
}
现在点击城市后,可以切换当前城市并且返回到首页。
Vuex的高级使用和localStorage
继续上面的代码,当我们点击城市切换,并返回到首页时,这时候都没问题,但是我们刷新页面,这时候右上角的城市又变为了默认值北京。这时候我们就需要用到 localStorage 本地存储。
打开stroe/index.js文件:
import Vue from 'vue'import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: localStorage.city || '北京'
},
mutations: {
changeCity (state, city) {
state.city = city
localStorage.city = city
}
}
})
这时切换城市后,在怎么刷新,也不会变了。
建议:
当使用 localStorage 的时候,建议大家在外层包裹一个try catch,因为在某些浏览器,如果用户关闭了本地存储功能或者使用了隐身模式时,使用 localStorage 有可能会导致浏览器抛出异常,代码就运行不了了。所以修改为:
import Vue from 'vue'import Vuex from 'vuex'
Vue.use(Vuex)
let defaultCity = '北京'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {
}
export default new Vuex.Store({
state: {
city: defaultCity
},
mutations: {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {
}
}
}
})
刷新,功能还是一样的。
这时候我们发现store/index.js的文件开始复杂起来了,这时候我们可以进行拆分,新创建一个state.js文件,我们把一部分代码复制到state.js中:
let defaultCity = '北京'try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {
}
export default {
city: defaultCity
}
再创建一个mutations.js文件:
export default {changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {
}
}
}
store/index.js改为:
import Vue from 'vue'import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
Vue.use(Vuex)
export default new Vuex.Store({
state: state,
mutations: mutations
})
这样我们就拆分为了几个部分。
小bug:当我们在城市列表中,点击文字多的城市,比如“阿拉善盟”,这时首页的样式有点变形了。
打开home下的Header.vue文件,修改下样式:
.header-rightpadding:0 .1rem
min-width: 1.04rem
float:right
text-align: center
color: #fff
这时候选几个字的城市都可以了。
下面进行代码优化
home文件夹下的Header.vue代码优化:
<div class="header-right">{{this.city}} <i class="iconfont arrow-icon"></i></div><script>
import { mapState } from 'vuex'
export default {
name: 'HomeHeader',
computed: {
// 展开运行符
// 把city这个公用数据映射到名字叫做city的计算属性之中
...mapState(['city'])
}
}
</script>
city文件夹下的list.vue代码优化:
<div class="button">{{this.city}}</div><script>
import Bscroll from 'better-scroll'
import { mapState, mapMutations } from 'vuex'
export default {
computed: {
// 把vuex里面的city这个公用的数据映射到这个组件的计算属性里,映射过来的名字叫做currentCity
...mapState({
currentCity: 'city'
})
},
methods: {
// 热门城市点击事件
handleCityClick (city) {
// this.$store.commit('changeCity', city) 改为下面代码
this.changeCity(city)
this.$router.push('/')
},
// 有一个mutations叫changeCity,然后把这个mutations映射到组件里一个名字叫changeCity的方法里
...mapMutations(['changeCity'])
},
}
</script>
然后是Search.vue页面:
import { mapMutations } from 'vuex'export default {
methods: {
// 切换城市点击事件
handleCityClick (city) {
// this.$store.commit('changeCity', city) 改为下面代码
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
},
}
Vuex核心概念:
State:存放的是公用的数据
Action:一些异步的方法可以写在Action里
Mutation:放的是同步的一些对数据的改变
Getter:当我们需要根据state里的数据,计算出一些新的数据时,我们可以用Getter。有点类似于组件中的computed计算属性的作用。
Module:可以把 store的代码进行分割成模块
例如:Getter例子:首页右上角显示:城市 城市
store/index.js文件:
import Vue from 'vue'import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
Vue.use(Vuex)
export default new Vuex.Store({
state: state,
mutations: mutations,
getters: {
doubleCity (state) {
return state.city + ' ' + state.city
}
}
})
home下的Header.vue文件:
<div class="header-right">{{this.doubleCity}} <i class="iconfont arrow-icon"></i></div><script>
import { mapState, mapGetters } from 'vuex'
export default {
name: 'HomeHeader',
computed: {
...mapState(['city']),
...mapGetters(['doubleCity'])
}
}
</script>
这时页面效果图:
提交代码并进行合并:
git add .git commit -m "vuex实现数据共享和localStorage"
git push
git checkout master
git merge city-vuex
git push
以上是 Vue2.5 旅游项目实例17 城市选择页-使用Vuex实现数据共享 的全部内容, 来源链接: utcz.com/z/376460.html