vuex:组件间数据通信
在电商app中,会有各种各样的广告,为了能够保证各个组件都能够调用广告信息,最简单的处理方式就是通过vuex;
vuex的官方说法
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
以下从几个相关文件的写法入手,详细介绍一下vuex的使用:
App.vue——app入口文件
所涉及到的知识点:
- 应用的生命周期
函数名 | 说明 |
---|---|
onLaunch | 当uni-app 初始化完成时触发(全局只触发一次) |
onShow | 当 uni-app 启动,或从后台进入前台显示 |
onHide | 当 uni-app 从前台进入后台 |
onError | 当 uni-app 报错时触发 |
onUniNViewMessage | 对 nvue 页面发送的数据进行监听 |
- 将数据存储到vuex中的函数放到
onLaunch
中。 - 为了让界面更加整洁,将
onLaunch
中的函数放到另一个js文件中进行处理
<script>
import {appOnLaunch,appOnShow,appOnHide} from '@/static/js/applife.js'
export default {
onLaunch: function() {
appOnLaunch()
},
onShow: function() {
appOnShow()
},
onHide: function() {
appOnHide()
}
};
</script>
<style lang="scss">
/* H5端引用。玄学问题,我这边在这里引入的css,在APP上无效。前面加/也一样。原因未知...
可自行测试在APP上是否有效,如果有效,可在vue里删除css引入的代码。 */
/* #ifndef APP-PLUS */
@import "./static/colorui/main.css";
@import "./static/colorui/icon.css";
@import "./static/zaiui/style/app.scss";
/* #endif */
@import "./static/css/app.css";
@import "./static/font/good/icon.css";
/* 项目css */
</style>
applife.js——onLaunch执行函数
此文件中的知识点:
//加载广告 requestAdvertSearchForMap().then(res=>{ store.commit('SET_ADVERT', res); });
此段代码的意思是:调用requestAdvertSearchForMap
接口,然后将获取的res
数据存储到SET_ADVERT
中,如果其他页面需要使用广告的数据,则可以通过this.$store.state.Advert.advert
的方式进行获取,或者通过this.$store.getters.GET_ADVERT
也是可以获取的。
/* app生命周期处理 */
import {requestSysConfig} from "@/static/api/config.js"
import store from '@/store/index.js'
import {requestGoodsCateByID} from "@/static/api/goodsCate.js"
import {doLoginFromCache} from '@/static/api/login.js'
import {requestDicts} from "@/static/api/dicts.js"
import {requestAdvertSearchForMap} from "@/static/api/advert.js"
// #ifdef APP-PLUS
import APPUpdate from "@/static/common/appupdate/index.js"
import {initAlibaichuan} from "@/static/js/alibaichuan.js"
// #endif
/* 启动app时执行 */
export function appOnLaunch(){
console.log('启动app')
/* 加载系统配置 */
requestSysConfig().then(res =>{
store.commit('SET_SYS_CONFIG', res)
});
//加载广告
requestAdvertSearchForMap().then(res=>{
store.commit('SET_ADVERT', res);
});
// 加载字典
requestDicts().then(res=>{
store.commit('SET_DICTS',res)
});
/* 加载用户登录信息 */
doLoginFromCache(store.state.loginFrom.launch)
// 检测版本更新
// #ifdef APP-PLUS
APPUpdate()
/* 初始化阿里百川 */
initAlibaichuan()
// #endif
}
/* 进入/激活app时执行,每次进入到app都会执行 */
export function appOnShow(){
console.log('appOnShow')
}
/* 隐藏app时执行,每次离开app都会执行此方法 */
export function appOnHide(){
console.log(appOnHide)
}
main.js——主js文件
此文件中的知识点:
此文件中需要引入vue store等,然后挂载到app上
import Vue from 'vue'
import App from './App'
import Request from '@/static/common/luch-request/index.js'
import store from '@/store/index.js'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App,
store
})
app.$mount()
store文件夹中的Index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import actions from './actions.js'
import mutations from './mutations.js'
import state from './states.js'
// import Router,{RouterMount} from 'uni-simple-router';
// Vue.use(Router)
Vue.use(Vuex)
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)
// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// set './app.js' => 'app'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
state,
modules,
getters,
actions,
mutations
})
export default store
request 获取广告的api文件
import {request} from '@/static/common/luch-request/index.js'
// 查询所有广告管理,以唯一识别为key
export function requestAdvertSearchForMap() {
console.log("查询所有广告管理,以唯一识别为key")
let url = '/advert/search/for/map'
return request.post( url );
}
对应的store中的广告的js文件
const advert = {
state: {
advert: {}
},
mutations: {
SET_ADVERT: (state, advert) => {
state.advert = advert
}
},
getters:{
GET_ADVERT: state => {
return state.advert
}
}
}
export default advert
home.vue——app首页的广告获取
此文件中的知识点:
- 获取广告信息在
watch
和created
两个地方都是需要的,created
函数中获取广告是为了保证如果页面一开始创建的时候就要从vuex中拿取数据。watch
是为了当vuex中的广告信息发生改变的时候,自动刷新更改数据。两者缺一不可。 created
函数的代码,我一开始放到了onLoad
函数中,在这个函数中如果调用vuex中的数据,很大部分是无法获取到数据的,如果放到created
函数中。- 注意在
watch
监听函数中写属性的方式:
i. 属性名用’’(英文单引号)包裹;
ii. 虽然是监听属性,但是书写方式是函数的形式,而且有两个参数,newObj
oldObj
,一个是新数据,一个是老数据,当新老数据不一致的时候才会执行代码。
iii. 监听数据中的$store
是不需要写this
的,但是在其他函数中是需要的,比如created
函数中,还有就是在页面渲染时,也是不需要使用this
的。
watch: {
'$store.state.Advert.advert':function(newObj,oldObj){
this.advert = newObj;
console.log(this.advert,'store中的advert内容watch')
}
},
created() {
this.advert = this.$store.state.Advert.advert;
console.log(this.advert,'store中的advert内容onload')
}