安装
npm run vuex --save
是什么? 怎么使用
vuex 是一个专门为vue.js应用程序开发的状态管理模式。
这个状态我们可以理解为在data中的属性,需要共享给其他组件使用的部分。
也就是说,是我们需要共享的data,使用vuex进行统一集中式的管理。
vuex中,有默认的五种基本的对象:
state:存储状态(变量)
getters:对数据获取之前的再次编译,可以理解为state的计算属性。我们在组件中使用
s
o
t
r
e
.
g
e
t
t
e
r
s
.
f
u
n
(
)
m
u
t
a
t
i
o
n
s
:
修
改
状
态
,
并
且
是
同
步
的
。
在
组
件
中
使
用
sotre.getters.fun() mutations:修改状态,并且是同步的。在组件中使用
sotre.getters.fun()mutations:修改状态,并且是同步的。在组件中使用store.commit(’’,params)。这个和我们组件中的自定义事件类似。
actions:异步操作。在组件中使用是$store.dispath(’’)
modules:store的子模块,为了开发大型项目,方便状态管理而使用的。这里我们就不解释了,用起来和上面的一样。
图解
这个图很重要
管理应用的所有组件的状态。
这个状态自管理应用包含以下几个部分:
state,驱动应用的数据源;
view,以声明方式将 state 映射到视图;
actions,响应在 view 上的用户输入导致的状态变化。
使用
导出创建的库
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
import actions from './actions'
Vue.use(Vuex)
// 导出 的是通过vuex 创建的仓库
export default new Vuex.Store({
// 存放全局公用的数据 在 state.js 中 和mutations.js中
state,
mutations,
actions
})
这里还有 state、 mutations、actions三个文件 分别对应的是vuex 的3个对象
第一种方法: 直接使用
<template>
<div class="list" ref="wrapper">
<div >
<div class="area">
<div class="title border-topbottom">当前城市</div>
<div class="button-list">
<div class="button-wrapper">
<div class="button">{{this.$store.state.city}}</div>
</div>
</div>
</div>
<div class="area">
<div class="title border-topbottom">热门城市</div>
<div class="button-list">
<div
class="button-wrapper"
v-for=' item of hotCities '
:key='item.id'
@click="handleCityClick(item.name)"
>
<div class="button">{{item.name}}</div>
</div>
</div>
</div>
<div class="area"
v-for="(item,key) of cities "
:ref="key"
:key="key"
>
<div class="title border-topbottom" >{{key}}</div>
<div class="item-list">
<div class="item border-bottom"
v-for="innerItem of item"
:key="innerItem.id"
@click="handleCityClick(innerItem.name)"
>
<div>{{innerItem.name}}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Bscroll from 'better-scroll'
// 代码优化 将vuex 中的 state 、 mutations、actions 映射到此对象上
import { mapState, mapMutations,mapActions } from 'vuex'
export default {
name:"CityList",
props:{
hotCities:Array,
cities:Object,
letter:String
},
methods:{
handleCityClick(city) {
console.log("共享数据");
// 使用vuex 中的对象的第一种方法 还有另一种高级在search.vue 中
this.$store.dispatch('changeCity',city);
// localstroage 中保存一份 刷新之后 还 有城市
localStorage.city = city;
this.$router.push('./home');
}
},
watch:{
letter(){// 方法名要和数据一样
console.log("到watch ");
if(this.letter){
// scroll 组件中的操作
const element = this.$refs[this.letter][0];
this.scroll.scrollToElement(element);
}
}
},
mounted(){
// { mouseWheel: true, click: true, tap: true }后面的加上点击才会生效
this.scroll = new Bscroll(this.$refs.wrapper,{ mouseWheel: true, click: true, tap: true });
},
computed:{
//扩展运算符...mapState,意思是把vuex的state数据映射到计算属性里面,映射后的名字为city 使用state中对象
...mapState({
currentCity:'city'
})
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.border-topbottom
&:before
border-color:#ccc
&:after
border-color:#ccc
.border-bottom
&:before
border-color:#ccc
.list
overflow:hidden
position:absolute
top:1.7rem
left:0
right:0
bottom:0
.title
line-height:.54rem
background:#eee
padding-left:.2rem
color:#666
font-size:.26rem
.button-list
overflow:hidden
padding:.1rem .6rem .1rem .1rem
.button-wrapper
float:left
width:33.33%
.button
margin: .1rem
padding: 0.1rem
text-align: center
border:.02rem solid #cccccc
border radius 0.06rem
.item-list
.item
line-height:.76rem
padding-left:.2rem
</style>
第二种方法 将vuex对象映射到当前对象中 具体代码
<template>
<div>
<div class="search">
<input v-model="keyword" class="search-input" type="text" placeholder="请输入城市或拼音" />
</div>
<div
class="search-content"
ref="search"
v-show="keyword"
>
<ul>
<li
class="search-item border-bottom"
v-for="item of list"
:key="item.id"
@click="handleCityClick(item.name)"
>
{{item.name}}
</li>
<li class="search-item border-bottom" v-show="hasNodata">
没有找到匹配的数据
</li>
</ul>
</div>
</div>
</template>
<script>
import Bscroll from 'better-scroll'
// 代码优化 将vuex 中的 state 、 mutations、actions 映射到此对象上
import { mapState, mapActions,mapMutations } from 'vuex'
export default {
name:'CitySearch',
props:{
cities:Object
},
data(){
return {
keyword:'',
list:[],
timer:null
}
},
computed:{//计算属性
// 查看是否有数据
hasNodata(){
return !this.list.length
}
},
watch:{
keyword(){
//截流 降低内存
if(this.timer){
clearTimeout(this.timer);
}
// 查看是否有值决定显示的内容
if(!this.keyword){
this.list = [];
return
}
this.timer = setTimeout(()=>{
const result = []
for (let i in this.cities){
this.cities[i].forEach((value) =>{
if(value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1){
result.push(value);
}
})
}
console.log(result);
this.list = result
},100);
},
},
mounted (){
this.scroll = new Bscroll(this.$refs.search,{ mouseWheel: true, click: true, tap: true });
},
methods:{
handleCityClick(city) {
console.log("共享数据");
//this.$store.dispatch('changeCity',city);
this.changeCity(city);
// localstroage 中保存一份 刷新之后 还 有城市
localStorage.city = city;
this.$router.push('./home');
},
// vuex 高级使用 ...mapMutation把本组件的mutations映射到changeCity方法里(changeCity在mutations里)
...mapActions(['changeCity'])
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.search
height: .72rem
padding: 0 .1rem
background: $bgColor
.search-input
box-sizing: border-box
width: 100%
height: .62rem
padding: 0 .1rem
line-height: .62rem
text-align: center
border-radius: .06rem
color: #666
.search-content
z-index: 1
overflow: hidden
position: absolute
top: 1.58rem
left: 0
right: 0
bottom: 0
background: #eee
.search-item
line-height: .62rem
padding-left: .2rem
background: #fff
color: #666
</style>