vuex
vuex是vue中的状态管理插件,可以实现全局统一的状态管理。在一个项目中只有一棵状态树,所有的数据都存储在上面
单向数据流
图片十分重要,要理解,可去官网查看详细解释
数据是单向流动的,view视图通过dispatch派发一个action(行为),改变state(数据),数据改变之后视图重新渲染
所有的和服务器端交互相关的,都放在actions里,比如和接口有关的
mutation——commit
actions——dispatch——接口
如何使用vuex
npm i vuex # 安装插件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
demo 部分内容
1.此demo使用的是前面创建的vue目录,所以有很多的东西不是本篇文章主要讲解的,还有一些配置没有此处说明但是并不是没有写,
2.因为获取接口数据用到了axios,所以还需要输入命令行安装axios:npm i axios
3.在src源文件中创建一个store目录,并在其中创建一个index.js文件,是用来文件拆分的
4.文件运行 npm run serve 打开localhost:8080
或者npm run build 然后在打包好的dist文件中双击打开index.html
本篇文章主要的文件是:
/src/store/index.js
/src/main.js
/src/App.vue
/src/pages/Home.vue
/src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 1,
list: [],
pages: 1,
totals: 1,
page: 1,
cartCount: 0
},
mutations: {
plus(state, step = 1) {
state.count += step
},
reduce(state) {
state.count--
},
loadDataEnd(state, payload) {
// 形参payload接收传参过来的数据也就是从接口那获得的数据,必须在下面写成详细的payload.movies,因为还要获取pages,要是直接就接收到详细的movies数据列表,那并排的pages和totals就获取不到了
this.state.list = [...state.list, ...payload.movies]
state.pages = payload.pages
state.totals = payload.totals
state.page++
},
buy(state) {
this.state.cartCount++
}
},
actions: {
loadData({ commit }, { page }) {
axios
.get('http://localhost:3000/api/v1/m', {
params: {
page
}
})
.then(res => {
console.log(res.data)
commit('loadDataEnd', res.data)
})
}
}
})
export default store
/src/main.js
import Vue from 'vue'
// import Vuex from 'vuex'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
// Vue.use(Vuex)
/* const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
plus(state, step = 1) {
state.count += step
},
reduce(state) {
state.count--
}
}
}) */
new Vue({
router,
store,// store: store,以后所有的组件中可以使用$store获取vuex中的数据
render: h => h(App)
}).$mount('#app')
/src/App.vue
给购物车哪里增加了购买数量
<template>
<div id="app" class="container">
<div class="header">芒果商城-{{ $store.state.count }}</div>
<router-view class="content"></router-view>
<ul class="footer">
<li class="active">
<i class="fa fa-home"></i>
<span>首页</span>
</li>
<li>
<i class="fa fa-fire"></i>
<span>热卖</span>
</li>
<li style="position:relative;">
<span class="dot" v-show="$store.state.cartCount>0">{{$store.state.cartCount}}</span>
<i class="fa fa-shopping-cart"></i>
<span>购物车</span>
</li>
<li>
<i class="fa fa-user"></i>
<span>我的</span>
</li>
</ul>
</div>
</template>
<style>
* {
margin: 0;
padding: 0;
}
html,
body,
.container {
width: 100%;
height: 100%;
}
.container {
display: flex;
flex-direction: column;
}
.container .header {
height: 40px;
text-align: center;
background: rgb(14, 184, 184);
line-height: 40px;
color: white;
font-weight: 900;
}
.container .content {
flex: 1;
overflow: auto;
}
.container .footer {
height: 50px;
display: flex;
justify-content: space-around;
align-items: center;
background: rgb(14, 184, 184);
color: white;
}
ul li {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
ul li i {
font-size: 1.6rem;
}
ul li span {
font-size: 0.6rem;
}
ul li.active {
color: black;
font-weight: 900;
}
img {
max-width: 100%;
}
.dot {
background: palevioletred;
color: white;
width: 1rem;
height: 1rem;
border-radius: 50%;
position: absolute;
padding: 0.2rem;
top: -10px;
left: 16px;
text-align: center;
}
</style>
/src/pages/Home.vue
<template>
<div class="home">
<h1>{{ $store.state.count }}</h1>
<button @click="countAdd">计数值+1</button>
<button @click="countAddStep(5)">计数值+5</button>
<button @click="countReduce">计数值-1</button>
<ul>
<li v-for="item in $store.state.list" :key="item._id">
{{ item.title }}-----------
<button @click="buyHandle">购买</button>
</li>
</ul>
<keep-alive>
<button v-show="isShowLoadMore" @click="loaData">加载数据</button>
</keep-alive>
<!-- <img :src="img" alt="巴卫" /> -->
<!-- <img alt="Vue logo" src="../assets/logo.png" />
<img :src="img" alt="巴卫" />
<HelloWorld msg="Welcome to Your Vue.js App" />-->
</div>
</template>
<script>
// @ is an alias to /src
// import HelloWorld from '@/components/HelloWorld.vue'
// import xx from '../assets/images/4.jpeg'
export default {
name: 'Home',
components: {
// HelloWorld
},
data() {
return {
// img: require('../assets/images/4.jpeg')
// img: xx,
isShowLoadMore: true
}
},
methods: {
countAdd() {
// commit 操作会传递两个参数 type payload
// type表示mutation中的名字
// payload(载荷)表示参数
this.$store.commit('plus')
},
countAddStep(buchang) {
this.$store.commit('plus', buchang)
},
countReduce() {
this.$store.commit('reduce')
},
loaData() {
// 这里的判断不可以写等号即不能写成<=,因为两者可能相等,要是写了等号,这个if就无效了
if (this.$store.state.pages < this.$store.state.page) {
this.isShowLoadMore = false
return
}
this.$store.dispatch('loadData', { page: this.$store.state.page })
},
buyHandle() {
this.$store.commit('buy')
}
}
}
</script>
<style scoped>
img {
max-width: 100%;
}
ul {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
width: 100%;
}
ul li {
flex: 1;
flex-direction: row;
height: 50px;
display: flex;
padding: 0.5rem 0.3rem;
}
</style>
``
demo 注释
/src/store/index.js
// 做模块拆分
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
import axios from 'axios'
// 使用veux
Vue.use(Vuex)
// 创建一个全局的vuex实例
const store = new Vuex.Store({
// 表示全局的state数据
// 以后所有的组件中可以使用$store获取vuex中的数据
state: {
count: 1,
list: [], // 数据
pages: 1, // 总页数
totals: 0, // 总数量
page: 1, // 当前页页码
cartCount: 0
},
// 是用来同步的改变数据的(所有的数据改变都是在这里进行的)
// 只能通过commit才可以提交(触发)一个mutation
mutations: {
// 参数一固定state(表示原始状态) 参数二 可以接收commit传的参数
plus(state, step = 1) {
state.count += step
},
reduce(state) {
state.count--
},
loadDataEnd(state, payload) {
// 如果没有分页直接这样取就可以了
// state.list = payload
// 如果有分页做加载更多的效果 需要:
state.list = [...state.list, ...payload.products]
state.pages = payload.pages
state.totals = payload.totalCount
// 点一次 页码加一 做加载更多的效果
state.page++
},
buy(state) {
state.cartCount++
}
},
// 如何派发 actions? 在Home里面派发了
// dispatch 派发actions actions和服务器端交互
actions: {
// 接收两个参数
// 参数一 context表示上下文是个对象 包含了vuex中的所有数据比如commit
// 参数二 表示接收传递的数据
// 在接收参数的时候 直接解构赋值
loadData({ commit }, { page }) {
// console.log(context)
// console.log(payload)
// 获取里面的commit
// const { commit } = context
axios
.get('http://localhost:3009/api/v1/products', {
params: {
page // page: page // 把页码传到服务器
}
})
.then((res) => {
console.log(res.data)
// 调出数据 通过 commit 提交一个mutations 改变state的数据
commit('loadDataEnd', res.data)
})
}
}
})
export default store