詳解uniapp的全局變量實(shí)現(xiàn)方式
前言
本文整理了一些uniapp全局變量的實(shí)現(xiàn)方式,細(xì)節(jié)知識(shí)來(lái)自于uView官網(wǎng)中對(duì)uniapp中的全局變量實(shí)現(xiàn),感興趣的同學(xué)可以前往uView官網(wǎng)搜索vuex進(jìn)行查看
全局變量的實(shí)現(xiàn)方式
一般來(lái)說(shuō)在uniapp中有以下幾種方式
- 本地存儲(chǔ)
- 配置文件
- 掛載到 Vue.prototype
- globalData
- vuex
下面對(duì)這5種方式的實(shí)現(xiàn)進(jìn)行介紹
本地存儲(chǔ)
永久存儲(chǔ),以app為例即使該應(yīng)用被關(guān)閉,該數(shù)據(jù)依然會(huì)被存儲(chǔ)
這是一種永久的存儲(chǔ)方式,類(lèi)似于web的Local Storage(有關(guān)于Cookie、Token、SessionStorage、LocalStorage,會(huì)整理在另一篇文章中),當(dāng)我們需要永久存儲(chǔ)用戶(hù)的某一信息時(shí)會(huì)使用這種方法,但是需要注意使用這種方式需要避免對(duì)存儲(chǔ)數(shù)據(jù)的頻繁獲取和修改操作,因?yàn)闀?huì)對(duì)性能產(chǎn)生一定的影響,應(yīng)用聲明周期內(nèi)的變量,不應(yīng)該使用此種方式
這種存儲(chǔ)方式有 同步和異步兩種
同步存儲(chǔ)
//同步存儲(chǔ)
uni.setStorageSync("key","value")
//同步獲取
let value = uni.getStorageSync("key")
console.log("我會(huì)等到上邊執(zhí)行完畢后才會(huì)執(zhí)行)
異步存儲(chǔ)
uni.setStorage({
key:"key",
data:"value",
success:function(){
//存儲(chǔ)成功的回調(diào)
console.log("我是異步存儲(chǔ)的回調(diào),我會(huì)在val聲明后被執(zhí)行")
}
})
let val = 1//這行會(huì)先執(zhí)行
uni.getStorage({
key:"key",
success:function(res){
//存儲(chǔ)成功的回調(diào)
console.log("我是異步獲取的回調(diào),我會(huì)在val2聲明后被執(zhí)行")
}
})
let val2 = 2//這行會(huì)先執(zhí)行
配置文件
這是一種利用模塊化文件導(dǎo)出實(shí)現(xiàn)的方式,先將變量寫(xiě)在js文件中,然后通過(guò)export default的形式導(dǎo)出使用
一般來(lái)說(shuō)使用這種方式實(shí)現(xiàn)的全局變量,是需要在應(yīng)用被用戶(hù)安裝之前到用戶(hù)卸載時(shí)都必須使用的變量,如向后端請(qǐng)求的域名,其他的情況不太適用這種方式,同時(shí)這種方式也有弊端,就是每次使用都需要引入文件
config.js
//如在config.js中 我們導(dǎo)出了一個(gè)基礎(chǔ)域名
export default{
baseUrl:"http://www.test.com"
}
index.js
//通過(guò)import引入這個(gè)文件
import config from "../common/config.js"
export default {
onLoad(){
console.log(config.baseUrl)//baseUrl:"http://www.test.com"
}
}
掛載到Vue.prototype
這是一種利用原型的實(shí)現(xiàn)方式(有關(guān)于js的原型鏈和繼承,會(huì)在整理在另一篇文章中),但是這種方式在微信小程序上會(huì)有特殊表現(xiàn)
注意:在微信小程序中 模板無(wú)法直接讀取展示引入的全局變量
main.js
//這里的config.js參照上文已經(jīng)寫(xiě)好的文件 import config from "./common/config.js" //將baseUrl掛載到Vue上,此后在頁(yè)面和組件中就可以通過(guò)this.baseUrl的方式去訪(fǎng)問(wèn) Vue.prototype.baseUrl = config.baseUrl
頁(yè)面中
<template>
<!-- 微信小程序中值為undefined,其他端有效 -->
<view>
值為:{{this.baseUrl}}
</view>
</template>
<script>
export default {
onLoad() {
console.log(this.baseUrl)//"http://www.test.com"
}
}
</script>
globalData
這種方式是微信小程序特有的,小程序無(wú)法使用vuex因此出現(xiàn)了globalData,uniapp是小程序另一種實(shí)現(xiàn)因此也出現(xiàn)了globalData
使用globalData有以下幾點(diǎn)需要注意的地方:
- globalData不是響應(yīng)式的,一個(gè)文件中對(duì)globalData的修改,不會(huì)動(dòng)態(tài)的在另一個(gè)文件中響應(yīng)
- 如果想實(shí)現(xiàn)globalData的"響應(yīng)",你需要在onShow的生命周期中手動(dòng)獲取值
對(duì)第二點(diǎn)進(jìn)行解釋?zhuān)瑸槭裁葱枰趏nShow里去獲取值onLoad不行么?
因?yàn)槿绻鸄、B頁(yè)面都引入了globalData,B在頁(yè)面內(nèi)部修改了globalData的值返回A頁(yè)面,此時(shí)A頁(yè)面沒(méi)有被銷(xiāo)毀不會(huì)調(diào)用onLoad生命鉤子,只會(huì)執(zhí)行onShow此時(shí)在onLoad里去獲取globalData,那么是不會(huì)執(zhí)行的,也就無(wú)法做到響應(yīng)式
App.vue
export default{
//需要在App.vue中去定義globalData
globalData:{
userName:"白居易"
},
//這里需要注意,如果想要在App.vue中使用globalData,不能直接使用getApp().globalData.Name,因?yàn)榇藭r(shí)getApp()未有生成
// 1. 非V3模式,可以通過(guò)this.$scope.globalData獲取
// 2. V3模式,可以通過(guò)getApp({allowDefault: true}).globalData獲取
onLaunch(){
console.log(this.$scope.globalData.userName)
}
}
當(dāng)在App.vue中定義好globalData后我們就可以在頁(yè)面中使用了
A.vue
<template>
<view>
<view>
<!-- 注意,不能在模板中直接使用 getApp().globalData.userName -->
<<賣(mài)炭翁>>的作者是:{{author}}
</view>
<view>
<u-button @click="modifyUserName">修改userName值</u-button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
author: ''
}
},
onShow() {
// 每次A.vue出現(xiàn)在屏幕上時(shí),都會(huì)觸發(fā)onShow,從而更新author值
this.author = getApp().globalData.userName;
},
methods: {
modifyUserName() {
//此時(shí)修改了globalData的值
getApp().globalData.userName = "詩(shī)圣";
// 修改userName后,本頁(yè)的author依然不會(huì)自動(dòng)刷新,因?yàn)間lobalData不是響應(yīng)式的
// 我們?nèi)匀恍枰謩?dòng)刷新本頁(yè)的author值,由此可見(jiàn)globalData的弊端
this.author = getApp().globalData.userName;
}
}
}
</script>
Vuex的實(shí)現(xiàn)方式
強(qiáng)烈建議使用vuex的方式,在uniapp使用vuex有兩種方式,一種是基于傳統(tǒng)vue的方式,一種是uView封裝后的方式,下面介紹uView官網(wǎng)對(duì)vuexd的封裝
傳統(tǒng)實(shí)現(xiàn)方式
傳統(tǒng)vuex的使用方式,這里只做簡(jiǎn)單介紹,如果對(duì)vuex不了解的同學(xué),可以去vue官網(wǎng)查看官方文檔
在uni.app的根目錄下創(chuàng)建一個(gè)store文件,并在其中創(chuàng)建一個(gè)index.js文件 內(nèi)容如下
//index.js
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const store = new Vuex.Store({
state:{
vuex_token:"123456"
},
//同步修改 state 中值的方法
mutations:{
//payload使用戶(hù)在使用mutations是傳入的參數(shù),可以使單一值也可以是對(duì)象
modifyToken(state,payload){
state.vuex_token = payload.token
}
}
})
export default store
在main.js中引入
import store from '@/store';
// 將store放入Vue對(duì)象創(chuàng)建中
const app = new Vue({
store,
...App
})
在頁(yè)面中使用
<template>
<view>
<view>
Token值為{{vuex_token}}
</view>
<u-button @click="btnClick">修改vuex_token</u-button>
</view>
</template>
<script>
//這是Vue官方為了更方便使用store提供的api,詳情可以去Vue官方查看文檔
import {mapState, mapMutations} from 'vuex';
export default {
computed: {
...mapState(['vuex_token'])
},
methods: {
...mapMutations(['modifyToken']),
btnClick() {
// 這里第二個(gè)參數(shù)可以普通變量或者對(duì)象,自定義的,根據(jù)mutations需求處理(不使用mapMutations的方式)
this.$store.commit('modifyToken', {token: 'xxxyyyzzz'}
//使用mapMutations的方式
this.modifyToken({token: 'xxxyyyzzz'})
}
}
}
</script>
uView的vuex實(shí)現(xiàn)方式(重點(diǎn))
首說(shuō)為什么uView對(duì)vuex進(jìn)行了封裝,原因有以下兩點(diǎn)
- uView覺(jué)得需要在vuex中定義state和mutations,在每個(gè)需要用到vuex的地方都需要引入mapState進(jìn)行解構(gòu),然后再次使用(操作繁瑣)
- 因?yàn)関uex是將變量保存在內(nèi)存中的,刷新瀏覽器就會(huì)導(dǎo)致vuex變量消失,一般還需要配合其他的存儲(chǔ)方式進(jìn)行使用如LocalStorage
針對(duì)這些問(wèn)題uView官方提供了自己封裝使用vuex的一套方法,這個(gè)方法結(jié)合LocalStorage、vuex,使得用戶(hù)不必再去繁瑣的調(diào)用vuex和考慮刷新丟失的問(wèn)題,下面我將代碼展示,并將其思路和過(guò)過(guò)程解釋
- 先在根目錄下創(chuàng)建一個(gè)index.js文件,寫(xiě)入以下內(nèi)容,開(kāi)頭我會(huì)先提供大致思路具體含義之后會(huì)在注釋中解釋
思路:index.js的大致思路如下
a. 為了解決vuex刷新丟失無(wú)法永久存儲(chǔ)數(shù)據(jù)的問(wèn)題,創(chuàng)建了一個(gè)lifeData對(duì)象,這個(gè)對(duì)象會(huì)通過(guò)函數(shù),將其存儲(chǔ)在LocalStorage中,以達(dá)到永久保存的效果,此時(shí)我只需要將vuex中需要永久保存的數(shù)據(jù),以key、value的形式存儲(chǔ)在這個(gè)對(duì)象中就可以了
b. 為了解決每次使用vuex都需要使用mutations中的函數(shù)去操作對(duì)應(yīng)的stroe中的變量,封裝了$uStore這一個(gè)方法去操作所有的store中的變量,當(dāng)然只進(jìn)行了簡(jiǎn)單的復(fù)制操作,對(duì)于更拓展的功能,用戶(hù)可以自己在mutations中去封裝函數(shù)進(jìn)行拓展
c. 封裝一個(gè)saveStateKeys數(shù)組,這個(gè)數(shù)組的數(shù)據(jù)會(huì)在app啟動(dòng)時(shí)就會(huì)被取出,因此我們可以把一些需要app啟動(dòng)時(shí)就獲取的數(shù)據(jù)放在其中,如應(yīng)用中上次用戶(hù)已經(jīng)登陸的信息,實(shí)際上saveStateKeys和lifeData是配合使用的,只有存在saveStateKeys中的變量,才會(huì)在存儲(chǔ)時(shí)被存儲(chǔ)在lifeData中以達(dá)到永久的存儲(chǔ),其他的就和普通vuex存儲(chǔ)方式一樣,對(duì)于這點(diǎn)我們可以在下述代碼中看到
//引入Vuex、vue 使用Vuex,這一步和一般使用vuex沒(méi)有區(qū)別
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//創(chuàng)建一個(gè)變量,這個(gè)變量用于存儲(chǔ)需要永久存儲(chǔ)的數(shù)據(jù)
let lifeData = {};
try{
// 嘗試獲取本地是否存在lifeData變量,第一次啟動(dòng)APP時(shí)是不存在的
lifeData = uni.getStorageSync('lifeData');
}catch(e){
}
// 需要永久存儲(chǔ),且下次APP啟動(dòng)需要取出的,在state中的變量名
let saveStateKeys = ['vuex_user', 'vuex_token'];
// 保存變量到本地存儲(chǔ)中(達(dá)到刷新/重啟(app不存在刷新,app只會(huì)重啟)不丟失)
const saveLifeData = function(key, value){
// 判斷變量名是否在需要存儲(chǔ)的數(shù)組中
//這一條就是在判斷如果變量名存儲(chǔ)在saveStateKeys中,那么就將其存儲(chǔ)在lifeData中達(dá)到永久存儲(chǔ),否則就和一般vuex的存儲(chǔ)方式一樣
if(saveStateKeys.indexOf(key) != -1) {
// 獲取本地存儲(chǔ)的lifeData對(duì)象,將變量添加到對(duì)象中
let tmp = uni.getStorageSync('lifeData');
// 第一次打開(kāi)APP,不存在lifeData變量,故放一個(gè){}空對(duì)象
tmp = tmp ? tmp : {};
tmp[key] = value;
// 執(zhí)行這一步后,所有需要存儲(chǔ)的變量,都掛載在本地的lifeData對(duì)象中
uni.setStorageSync('lifeData', tmp);
}
}
const store = new Vuex.Store({
// 下面這些值僅為示例,使用過(guò)程中請(qǐng)刪除
state: {
// 如果上面從本地獲取的lifeData對(duì)象下有對(duì)應(yīng)的屬性,就賦值給state中對(duì)應(yīng)的變量
// 加上vuex_前綴,是防止變量名沖突,也讓人一目了然
// 被永久存儲(chǔ)的數(shù)據(jù)會(huì)從lifeData中去獲取,因?yàn)閘ifeData已經(jīng)存儲(chǔ)在了本地中
vuex_user: lifeData.vuex_user ? lifeData.vuex_user : {name: '明月'},
vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '',
// 如果vuex_version無(wú)需保存到本地永久存儲(chǔ),無(wú)需lifeData.vuex_version方式
vuex_version: '1.0.1',
},
mutations: {
$uStore(state, payload) {
//payload就是后來(lái)調(diào)用的this.$u.vuex時(shí)傳入的對(duì)象
//如this.$u.vuex("user.info.score","jack") payload = {name:"user.info.score",value:"jack"}
// 判斷是否多層級(jí)調(diào)用,state中為對(duì)象存在的情況,諸如user.info.score = 1
let nameArr = payload.name.split('.');//[user,info,score]
let saveKey = '';
let len = nameArr.length;
if(nameArr.length >= 2) {
let obj = state[nameArr[0]];
for(let i = 1; i < len - 1; i ++) {
obj = obj[nameArr[i]];// 此時(shí)obj就是user.info,當(dāng)然此時(shí)他還是一個(gè)空數(shù)據(jù)
}
//nameArr[len-1]就是score,obj[nameArr[len - 1]]相當(dāng)于 user.info.score
obj[nameArr[len - 1]] = payload.value;
saveKey = nameArr[0];
} else {
// 單層級(jí)變量,在state就是一個(gè)普通變量的情況
state[payload.name] = payload.value;
saveKey = payload.name;
}
// 保存變量到本地,見(jiàn)頂部函數(shù)定義
saveLifeData(saveKey, state[saveKey])
}
}
})
export default store
在同目錄下創(chuàng)建 mixin.js文件
思路:
a. 為了能夠在每個(gè)頁(yè)面都能通過(guò)this.的方式使用變量,我們需要將mapState通過(guò)Vue mixin的方式進(jìn)行全局混入
b. 為了能夠在每個(gè)頁(yè)面都能輕松的調(diào)用vuex中的mutations里的方法,我們需要一個(gè)方法能夠幫我們?nèi)フ{(diào)用uStore,而不是每次都通過(guò)commit的方式,因此uView還混入了另一個(gè)方法$u.vuex
ps: minxi(混入)是Vue提供的一種實(shí)現(xiàn)全局功能的一個(gè)api,混入有多種方式這里使用了全局混入,如果對(duì)于混入不是很了解可以去Vue官網(wǎng)查看相關(guān)文檔
//mixin.js
import { mapState } from 'vuex'
import store from "@/store"
// 嘗試將用戶(hù)在根目錄中的store/index.js的vuex的state變量,全部加載到全局變量中
let $uStoreKey = [];
try{
$uStoreKey = store.state ? Object.keys(store.state) : [];
}catch(e){
}
module.exports = {
created() {
// 將vuex方法掛到this.$u上
// 使用方法為:如果要修改vuex的state中的user.name變量為"史詩(shī)" => this.$u.vuex('user.name', '史詩(shī)')
// 如果要修改vuex的state的version變量為1.0.1 => this.$u.vuex('version', '1.0.1')
this.$u.vuex = (name, value) => {
this.$store.commit('$uStore', {
name,value //這里有沒(méi)有回憶起來(lái)$uStore傳入的payload haha
})
}
},
computed: {
// 將vuex的state中的所有變量,解構(gòu)到全局混入的mixin中
...mapState($uStoreKey)
}
}
開(kāi)始全局混入,在main.js中引入 mixin.js文件進(jìn)行混入
//main.js
let vuexStore = require("@/store/$u.mixin.js");
Vue.mixin(vuexStore);
將store放到Vue實(shí)例中
//main.js
import store from '@/store';
// 將store放入Vue對(duì)象創(chuàng)建中
const app = new Vue({
store,
...App
})
以上就是uView官方對(duì)vuex的封裝,在app開(kāi)發(fā)中使用這種封裝后的vuex很便捷,同時(shí)自身也可以根據(jù)需要在@/stote/index.js中去拓展自己的方法
結(jié)語(yǔ)
以上就是uniapp全局變量的不同實(shí)現(xiàn)方式,具體使用哪一種需要在實(shí)際開(kāi)發(fā)中根據(jù)實(shí)際選擇,個(gè)人感覺(jué)uView對(duì)vuex的封裝,對(duì)于初入前端我而言有著很高參考價(jià)值,因此特別整理出來(lái)留存分享。
到此這篇關(guān)于詳解uniapp的全局變量實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)uniapp 全局變量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js中動(dòng)態(tài)創(chuàng)建json,動(dòng)態(tài)為json添加屬性、屬性值的實(shí)例
下面小編就為大家?guī)?lái)一篇js中動(dòng)態(tài)創(chuàng)建json,動(dòng)態(tài)為json添加屬性、屬性值的實(shí)例。小編覺(jué)的挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12
JavaScript剩余操作符Rest Operator詳解
在本篇文章里小編給各位分享的是關(guān)于JavaScript剩余操作符Rest Operator知識(shí)點(diǎn)用法總結(jié),有需要的朋友們跟著學(xué)習(xí)下。2019-07-07
用javascript判斷IE版本號(hào)簡(jiǎn)單實(shí)用且向后兼容
項(xiàng)目中需要判斷IE版本號(hào),又因?yàn)?jQuery 2.0 去除了對(duì)瀏覽器版本號(hào)的判斷于是就看到一老外寫(xiě)的一段代碼,下面與大家分享下2013-09-09
javascript實(shí)現(xiàn)鼠標(biāo)拖動(dòng)改變層大小的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)鼠標(biāo)拖動(dòng)改變層大小的方法,涉及javascript操作鼠標(biāo)事件及樣式的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04
js確認(rèn)框confirm()用法實(shí)例詳解
這篇文章主要針對(duì)js確認(rèn)框confirm()用法進(jìn)行實(shí)例講解,介紹了javascript確認(rèn)框的三種使用方法,感興趣的小伙伴們可以參考一下2016-01-01
js下將字符串當(dāng)函數(shù)執(zhí)行的方法
js下將字符串當(dāng)函數(shù)執(zhí)行的方法,需要的朋友可以參考下。2011-07-07

