有点类似于安卓的信息中心,有一个store对象用来存储所有共享数据
1、安装vuex依赖包
npm install vuex --save
2、导入vuex包
import Vuex from ‘vuex’
3、创建sore对象
const store =new Vuex.Store({
//state中存放的就是全局共享数据
state:{
count:0
}
})
new Vue(){
el:'#app',
render:h=>h(app),
router,
//将创建的共享数据对象,挂载到vue实例中
//所有的组件,就可以直接从store中获取全局的数据了
store
}
this.$store.state.全局数据名称
import { mapState } from 'vuex'
通过刚才导入的mapState函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性
computed:{
...mapState(['count])
}
案例:
stroe.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
},
actions: {
}
})
app.vue
<template>
<div id="app">
<my-addition></my-addition>
<hr>
<my-subtraction></my-subtraction>
</div>
</template>
<script>
import Addition from './components/Addition'
import Subtraction from './components/Subtraction'
export default {
data(){
return {
}
},
components: {
'my-addition':Addition,
'my-subtraction':Subtraction
}
}
</script>
<style>
</style>
Addition.vue
<template>
<div>
<h3>当前最新的count值为:{{this.$store.state.count}}</h3>
<button>+1</button>
</div>
</template>
<script>
export default {
data(){
return {
}
}
}
</script>
<style scoped>
</style>
Subtraction
<template>
<div>
<h3>当前最新的count值为:{{count}}</h3>
<button>-1</button>
</div>
</template>
<script>
//从vuex中按需导入mapState函数
import { mapState } from 'vuex'
export default {
data (){
return {
}
},
computed:{
...mapState(['count'])
}
}
</script>
<style scoped>
</style>
export default new Vuex.Store({
state: {
count:0
},
mutations: {
add(state){
//变更状态
state.count++
},
},
actions: {
}
})
触发Mutation
methods:{
btnHander1(){
//触发mutation的第一种方式
this.$store.commit('add')
}
}
完整案例
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
add(state){
//变更状态
state.count++
},
},
actions: {
}
})
app.vue
<template>
<div id="app">
<my-addition></my-addition>
<hr>
<my-subtraction></my-subtraction>
</div>
</template>
<script>
import Addition from './components/Addition'
import Subtraction from './components/Subtraction'
export default {
data(){
return {
}
},
components: {
'my-addition':Addition,
'my-subtraction':Subtraction
}
}
</script>
<style>
</style>
Addition.vue
<template>
<div>
<h3>当前最新的count值为:{{this.$store.state.count}}</h3>
<button @click="btnHander1">+1</button>
</div>
</template>
<script>
export default {
data(){
return {
}
},
methods:{
btnHander1(){
//触发mutation的第一种方式
this.$store.commit('add')
}
}
}
</script>
<style scoped>
</style>
stroe.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
addN(state,step){
//变更状态
state.count +=step
},
},
actions: {
}
})
Addition.vue
<template>
<div>
<h3>当前最新的count值为:{{this.$store.state.count}}</h3>
<button @click="btnHander1">+N</button>
</div>
</template>
<script>
export default {
data(){
return {
}
},
methods:{
btnHander1(){
//触发mutation的第一种方式
this.$store.commit('addN',3)
}
}
}
</script>
<style scoped>
</style>
import { maoMutations } from ‘vuex’
通过刚才导入的mapMutation函数,将需要的mutations函数,映射为当前组件的methods方法:
methods:{
...mapMutation(['add','addN'])
}
案例
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
addN(state,step){
//变更状态
state.count +=step
},
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
actions: {
}
})
app.vue
<template>
<div id="app">
<my-addition></my-addition>
<hr>
<my-subtraction></my-subtraction>
</div>
</template>
<script>
import Addition from './components/Addition'
import Subtraction from './components/Subtraction'
export default {
data(){
return {
}
},
components: {
'my-addition':Addition,
'my-subtraction':Subtraction
}
}
</script>
<style>
</style>
Subtraction.vue
<template>
<div>
<h3>当前最新的count值为:{{count}}</h3>
<button @click="btnhander1">-1</button>
<button @click="btnhander2">-N</button>
</div>
</template>
<script>
//从vuex中按需导入mapState函数
import { mapState,mapMutations } from 'vuex'
export default {
data (){
return {
}
},
computed:{
...mapState(['count'])
},
methods:{
...mapMutations(['sub','subN']),
btnhander1(){
this.sub()
},
btnhander2(){
this.subN(3)
}
}
}
</script>
<style scoped>
</style>
如果通过异步操作变更数据,必须通过Action,而不能使用Mutation,但是在action中还是要通过触发Mutation的方式间接变更数据
案例:
stroe.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
add(state){
//变更状态
state.count ++
},
addN(state,step){
//变更状态
state.count +=step
},
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
actions: {
addAsync(context){
setTimeout(()=>{
context.commit('add')
},2000)
}
}
})
Addition.vue
<template>
<div>
<h3>当前最新的count值为:{{this.$store.state.count}}</h3>
<button @click="btnHander1">+N</button>
</div>
</template>
<script>
export default {
data(){
return {
}
},
methods:{
btnHander1(){
//触发mutation的第一种方式
this.$store.dispatch('addAsync')
}
}
}
</script>
<style scoped>
</style>
app.vue
<template>
<div id="app">
<my-addition></my-addition>
<hr>
<my-subtraction></my-subtraction>
</div>
</template>
<script>
import Addition from './components/Addition'
import Subtraction from './components/Subtraction'
export default {
data(){
return {
}
},
components: {
'my-addition':Addition,
'my-subtraction':Subtraction
}
}
</script>
<style>
</style>
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
add(state){
//变更状态
state.count ++
},
addN(state,step){
//变更状态
state.count +=step
},
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
actions: {
addAsync(context,step){
setTimeout(()=>{
context.commit('addN',step)
},2000)
}
}
})
Addition.vue
<template>
<div>
<h3>当前最新的count值为:{{this.$store.state.count}}</h3>
<button @click="btnHander1">+1</button>
<button @click="btnHander2">+N</button>
</div>
</template>
<script>
export default {
data(){
return {
}
},
methods:{
btnHander1(){
//触发mutation的第一种方式
this.$store.dispatch('addAsync')
},
btnHander2(){
//触发mutation的
this.$store.dispatch('addAsync',5)
}
}
}
</script>
<style scoped>
</style>
1、从vuex中按需导入mapAction函数
import {mapAction} from ‘vuex’
2、通过刚才导入的mapActions函数,将需要的action函数,映射为当前组件的methods函数
methods:{
...mapActions(['addAsync','addNAsync'])
}
案例
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
add(state){
//变更状态
state.count ++
},
addN(state,step){
//变更状态
state.count +=step
},
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
actions: {
addAsync(context,step){
setTimeout(()=>{
context.commit('addN',step)
},2000)
},
subAsync(context){
setTimeout(()=>{
context.commit('sub')
},2000)
},
subNAsync(context,step){
setTimeout(()=>{
context.commit('subN',step)
},2000)
},
}
})
Subtraction.vue
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
add(state){
//变更状态
state.count ++
},
addN(state,step){
//变更状态
state.count +=step
},
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
actions: {
addAsync(context,step){
setTimeout(()=>{
context.commit('addN',step)
},2000)
},
subAsync(context){
setTimeout(()=>{
context.commit('sub')
},2000)
},
subNAsync(context,step){
setTimeout(()=>{
context.commit('subN',step)
},2000)
},
}
})
Getter用于对store中的数据进行加工处理形成的新的数据(包装),类似于java的getter和setter
范例:
const store =new Vuex.Store({
state:{
count:0
},
getter:{
showNum:state=>{
return '当前最新的数据是【'+state.count+'】'
}
}
})
this.$store.getters.名称
范例:
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
add(state){
//变更状态
state.count ++
},
addN(state,step){
//变更状态
state.count +=step
},
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
actions: {
addAsync(context,step){
setTimeout(()=>{
context.commit('addN',step)
},2000)
},
subAsync(context){
setTimeout(()=>{
context.commit('sub')
},2000)
},
subNAsync(context,step){
setTimeout(()=>{
context.commit('subN',step)
},2000)
},
},
getters:{
showNum(state){
return '当前最最最最新的数量是【'+state.count+'】'
}
}
})
Substration.vue
<template>
<div>
<h3>{{$store.getters.showNum}}</h3>
<button @click="btnhander1">-1</button>
<button @click="btnhander2">-N</button>
<button @click="btnhander3">-N async</button>
<button @click="btnhander4">-1 async</button>
</div>
</template>
<script>
//从vuex中按需导入mapState函数
import { mapState,mapMutations,mapActions } from 'vuex'
export default {
data (){
return {
}
},
computed:{
...mapState(['count'])
},
methods:{
...mapMutations(['sub','subN']),
...mapActions(['subAsync','subNAsync']),
btnhander1(){
this.sub()
},
btnhander2(){
this.subN(3)
},
btnhander3(){
this.subNAsync(3)
},
btnhander4(){
this.subAsync()
}
}
}
</script>
<style scoped>
</style>
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
add(state){
//变更状态
state.count ++
},
addN(state,step){
//变更状态
state.count +=step
},
sub(state){
state.count--
},
subN(state,step){
state.count-=step
}
},
actions: {
addAsync(context,step){
setTimeout(()=>{
context.commit('addN',step)
},2000)
},
subAsync(context){
setTimeout(()=>{
context.commit('sub')
},2000)
},
subNAsync(context,step){
setTimeout(()=>{
context.commit('subN',step)
},2000)
},
},
getters:{
showNum(state){
return '当前最最最最新的数量是【'+state.count+'】'
}
}
})
Substraction.vue
<template>
<div>
<h3>{{showNum}}</h3>
<button @click="btnhander1">-1</button>
<button @click="btnhander2">-N</button>
<button @click="btnhander3">-N async</button>
<button @click="btnhander4">-1 async</button>
</div>
</template>
<script>
//从vuex中按需导入mapState函数
import { mapState,mapMutations,mapActions,mapGetters } from 'vuex'
export default {
data (){
return {
}
},
computed:{
...mapState(['count']),
...mapGetters(['showNum']),
},
methods:{
...mapMutations(['sub','subN']),
...mapActions(['subAsync','subNAsync']),
btnhander1(){
this.sub()
},
btnhander2(){
this.subN(3)
},
btnhander3(){
this.subNAsync(3)
},
btnhander4(){
this.subAsync()
}
}
}
</script>
<style scoped>
</style>
list.json
[
{
"id": 0,
"info": "Racing car sprays burning fuel into crowd.",
"done": true
},
{ "id": 1,
"info": "Japanese princess to wed commoner.",
"done": false },
{
"id": 2,
"info": "Australian walks 100km after outback crash.",
"done": true
},
{ "id": 3,
"info": "Man charged over missing wedding girl.",
"done": false },
{ "id": 4,
"info": "Los Angeles battles huge wildfires.",
"done": false }
]
main.js
需要安装ant-design-vue组件做外观
import Vue from 'vue'
import App from './App.vue'
// 1. 导入 ant-design-vue 组件库
import Antd from 'ant-design-vue'
// 2. 导入组件库的样式表
import 'ant-design-vue/dist/antd.css'
// 3、导入store
import store from './store'
Vue.config.productionTip = false
// 3. 安装组件库
Vue.use(Antd)
new Vue({
store,
render: h => h(App)
}).$mount('#app')
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
//所有的任务列表
list:[],
//文本框内容
inputValue:'aaa',
nextId:5,
viewKey:'all'
},
mutations: {
//获取列表数据
initList (state, list) {
state.list = list
},
//设置输入文本
setInputValue (state, value) {
state.inputValue = value
},
//添加文本
addItem (state) {
const obj = {
id: state.nextId,
info: state.inputValue.trim(),
done: false
}
state.list.push(obj)
state.nextId++
state.inputValue = ''
},
//删除列表item
removeItem(state,id){
//根据id查找对应项索引
let index=state.list.findIndex(x=> x.id==id)
//根据索引删除数组元素
if (index!=-1){
state.list.splice(index,1)
}
},
//修改列表项参数
changeStatus(state,param){
const index=state.list.findIndex(x=>x.id==param.id)
if (index !=-1){
state.list[index].done=param.status
}
},
//清除完成的任务
clearDone(state){
state.list=state.list.filter(x=>x.done===false)
},
//改变任务显示
changeViewKey(state,key){
state.viewKey=key
}
},
actions: {
getList(context) {
axios.get('/list.json').then(({ data }) => {
// console.log(data)
context.commit('initList', data)
})
}
},
getters:{
//统计未完成任务的条数
unDoneLength(state){
return state.list.filter(x=>x.done===false).length
},
//包装list,获取各种状态下的list
infoList(state){
if (state.viewKey==='all'){
return state.list
}
if (state.viewKey =='undone'){
return state.list.filter(x=>!x.done)
}
if (state.viewKey =='done'){
return state.list.filter(x=>x.done)
}
return state.list
}
}
})
app.vue
<template>
<div id="app">
<a-input placeholder="请输入任务" class="my_ipt" :value="inputValue"
@change="handleInputChange" />
<a-button type="primary" @click="addItemToList">添加事项</a-button>
<a-list bordered :dataSource="infoList" class="dt_list">
<a-list-item slot="renderItem" slot-scope="item">
<!-- 复选框 -->
<a-checkbox :checked="item.done" @change="(e)=>{cbStatusChange(e,item.id)}">{{item.info}}</a-checkbox>
<!-- 删除链接 -->
<a slot="actions" @click="removeItemById(item.id)">删除</a>
</a-list-item>
<!-- footer区域 -->
<div slot="footer" class="footer">
<!-- 未完成的任务个数 -->
<span>{{unDoneLength}}条剩余</span>
<!-- 操作按钮 -->
<a-button-group>
<a-button :type="viewKey === 'all' ? 'primary' : 'default'" @click="changeList('all')">全部</a-button>
<a-button :type="viewKey === 'undone' ? 'primary' : 'default'" @click="changeList('undone')">未完成</a-button>
<a-button :type="viewKey === 'done' ? 'primary' :'default'" @click="changeList('done')">已完成</a-button>
</a-button-group>
<!-- 把已经完成的任务清空 -->
<a @click="clean">清除已完成</a>
</div>
</a-list>
</div>
</template>
<script>
import { mapState,mapGetters } from 'vuex'
export default {
name: 'app',
data() {
return {
}
},
created () {
this.$store.dispatch('getList')
},
computed:{
...mapState(['inputValue','viewKey']),
...mapGetters(['unDoneLength','infoList'])
},
methods:{
//监听文本框内容变化
handleInputChange(e){
// console.log(e.target.value)
this.$store.commit('setInputValue',e.target.value)
},
//向列表中新增item项
addItemToList(){
if (this.inputValue.trim().length<=0){
return this.$message.error('请输入内容')
}
this.$store.commit('addItem')
},
//通过id删除item项
removeItemById(id){
// console.log(id)
this.$store.commit('removeItem',id)
},
//监听复选框选中状态事件,列表item选中与否
cbStatusChange(e,id){
//接受最先的选中状态
// console.log(e.target.checked,id)
const param={
id:id,
status:e.target.checked
}
this.$store.commit('changeStatus',param)
},
//清除已经完成的任务
clean(){
this.$store.commit('clearDone')
},
//查看完成与否
changeList(key){
// console.log(key)
this.$store.commit('changeViewKey',key)
}
}
}
</script>
<style scoped>
#app {
padding: 10px;
}
.my_ipt {
width: 500px;
margin-right: 10px;
}
.dt_list {
width: 500px;
margin-top: 10px;
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>