摘要:它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。狀態(tài)自管理應(yīng)用包含以下幾個部分,驅(qū)動應(yīng)用的數(shù)據(jù)源,以聲明方式將映射到視圖,響應(yīng)在上的用戶輸入導(dǎo)致的狀態(tài)變化。
事情發(fā)生在上周(2019-06-06)團(tuán)隊技術(shù)分享的時候。
起因在于一個問題:vue 中多個組件如何使用同一個變量,我們叫這個變量為 baseConfig 吧。
說實(shí)話我沒想到那么多人不理解其中的知識。今天我整理一下發(fā)出來。
Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。Vuex 可以幫助我們管理共享狀態(tài),并附帶了更多的概念和框架。這需要對短期和長期效益進(jìn)行權(quán)衡。
狀態(tài)自管理應(yīng)用包含以下幾個部分:
state,驅(qū)動應(yīng)用的數(shù)據(jù)源;
view,以聲明方式將 state 映射到視圖;
actions,響應(yīng)在 view 上的用戶輸入導(dǎo)致的狀態(tài)變化。
以下是一個表示“單向數(shù)據(jù)流”理念的簡單示意:
Vuex 的應(yīng)用其實(shí)看完了上面的介紹,我們就明白,這是一個非常符合我們需求的工具。那么我們就來看看怎么去應(yīng)用。
mapState 輔助函數(shù) 當(dāng)一個組件需要獲取多個狀態(tài)時候,將這些狀態(tài)都聲明為計算屬性會有些重復(fù)和冗余。為了解決這個問題,我們可以使用 mapState 輔助函數(shù)幫助我們生成計算屬性。
從下面的例子可以看到,我們子組件中的值是通過計算屬性來從 store 中獲取的。這樣在通過 mutations 等方式改變之后,我們的值也會動態(tài)更新。
當(dāng)然,你的頁面簡單的時候,也不需要再去使用 Vuex,考慮一下后面的方案吧。
const store = new Vuex.Store({ state: { baseConfig: { server_name: "lilnong.top" } } }) // 創(chuàng)建一個 User 組件 const Serv = { template: `方案二:父子組件傳參 父傳參的方式{{ server_name }}`, computed: { server_name() { // this.$store return store.state.baseConfig.server_name } } } const app = new Vue({ el: "#app", store, // 這樣可以把 store 的實(shí)例注入所有的子組件 components: { Serv }, template: `` })
baseConfig 需要定義在最外面,然后給所有的子組件都傳遞進(jìn)去,當(dāng)有改變的時候,子組件也會跟著改變。
{ data: { baseConfig: { server_name: "lilnong.top" } } }子組件接受參數(shù)的方式
每個子組件都需要接收。
{ props:["server_name", "baseConfig"],//這種是無默認(rèn)值,無類型檢查的,正常使用不推薦這種寫法 }父子組件方案的優(yōu)缺點(diǎn)
所有的父組件都需要傳遞參數(shù),所有的子組件都要接收參數(shù)。
傳入的問題可以通過,傳入一個對象的所有參數(shù)來解決
方案二:路由組件傳參該方案也叫方案二,并不是我寫錯了,是因為他們的場景是一樣。
在 Vue Router 的路由中,我們把組件配置在 routes 中,導(dǎo)致我們無法在模板之中傳遞參數(shù)。
這里我們需要使用他提供的 props 屬性來傳參,文檔地址。jsRun測試地址。lilnong.top測試地址
const Foo = { template: "foo" } const Bar = { template: "bar" } const routes = [ { path: "/foo", component: Foo }, { path: "/bar", component: Bar } ] const router = new VueRouter({ routes // (縮寫) 相當(dāng)于 routes: routes }) const app = new Vue({ router }).$mount("#app")
方案三:全局對象(store 模式)Hello App!
Go to Foo Go to Bar
簡單狀態(tài)管理起步使用 --官方文檔
全局對象就是如下使用,定義一個全局對象,然后修改這個全局對象就好了
const sourceOfTruth = {} const vmA = new Vue({ data: sourceOfTruth }) const vmB = new Vue({ data: sourceOfTruth })store 模式
原理上來講,還是全局對象,但是通過簡單的規(guī)定,來明確數(shù)據(jù)流向
var store = { debug: true, state: { message: "Hello!" }, setMessageAction (newValue) { if (this.debug) console.log("setMessageAction triggered with", newValue) this.state.message = newValue }, clearMessageAction () { if (this.debug) console.log("clearMessageAction triggered") this.state.message = "" } } var vmA = new Vue({ data: { privateState: {}, sharedState: store.state } }) var vmB = new Vue({ data: { privateState: {}, sharedState: store.state } })爭論核心:全局對象方案究竟行不行?原理?
好了,三種方案這里就已經(jīng)介紹完了。那開始看看我們的爭論:全局放個對象的方式不行(對方觀點(diǎn)),數(shù)據(jù)更新時組件不會自動更新
先說原理,內(nèi)存地址vue 數(shù)據(jù)綁定的原理大家都懂吧?通過 defineProperty 來劫持,Dep 收集依賴等等。
對于對象類型的數(shù)據(jù),我們變量里面保存的其實(shí)是一個指向堆的地址,我們來看下面的這個例子。
var obj = {};//定義了一個對象,`obj` 存放的是一個地址 obj.a = 1;//通過 `obj` 的地址,找到對象,然后給對象里面放了 `a=1` ; var obj1 = obj;//把 `obj` 的地址,給 `obj1` 復(fù)制了一下 obj1.a = 2;//通過 `obj1` 的地址,找到對象,然后給對象里面放了 `a=2` ; //這個時候,對象里面存放的就是{a:2}//console.log(obj, obj1) //這里引出了另一個問題 深拷貝與淺拷貝
這里也就是我的核心原理。
定義一個對象(保存在 window 上)
通過對象變量保存的是地址的原理
我們在其他組件都用 window 上的對象以此來達(dá)到目的。
再說場景,細(xì)化問題是不是看到上面的原理好簡單?但是往往不是這么簡單,下面咱們分析一下情況
window 上沒綁對象,而是其他類型這么辦?比如說 null 、 undefined
我也沒轍,大哥,看好上面的原理,主要原理就是地址引用。
對象覆蓋,就是如下的這個賦值場景。
其實(shí)我理解你是想給 obj 重新都賦值一下。
obj={}; obj2 = obj; obj.a = 1; obj2 = {a:2,b:3};//這里把 obj2 的地址換成了新的一個對象 //console.log(obj, obj2)
但是不能這樣寫,正確操作如下:
Object.assign(obj2, {a:2,b:3})
一個一個值的寫 obj2.a=2;obj2.b=3;
后添加的屬性,沒有計入 vue 的數(shù)據(jù)觀察隊列(新手經(jīng)常犯的錯誤)
對象變更檢測注意事項
于 JavaScript 的限制,Vue 不能檢測對象屬性的添加或刪除:
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 現(xiàn)在是響應(yīng)式的 vm.b = 2 // `vm.b` 不是響應(yīng)式的
對象解決方案 Vue.set(object, propertyName, value)
對象解決方案(實(shí)例內(nèi)) this.$set(object, propertyName, value)
數(shù)組更新檢測
將一些方法進(jìn)行了封裝 push()、pop()、shift()、unshift()、splice()、sort()、reverse()。
通過上面的方法來改變數(shù)組可以監(jiān)聽到改變。
由于 JavaScript 的限制,Vue 不能檢測以下數(shù)組的變動:
當(dāng)你利用索引直接設(shè)置一個數(shù)組項時,例如:vm.items[indexOfItem] = newValue
當(dāng)你修改數(shù)組的長度時,例如:vm.items.length = newLength
總結(jié)共享數(shù)據(jù)三種方法
vuex
大而全,使用復(fù)雜
組件值傳遞
原生自帶,使用復(fù)雜,適合組件相關(guān)數(shù)據(jù)
store
簡單,不適合復(fù)雜項目。工程的話,還是推薦 vuex
對象引用需要注意的地方
不能給變量二次賦值obj2={}
只有對象類型才是存地址, Array 與 Object。
String 與 Null等不包括在內(nèi)
增加數(shù)據(jù)要注意是否被觀察到
對象:注意 Vue.set
數(shù)組:使用規(guī)定方法
測試地址,采用 setTimeout 來模擬異步操作。當(dāng)時苦的一批,完了還沒保存。性感碼農(nóng),在線編程。
成功的說服了在場的兄弟們,然后周四就拖堂了。
VUEX 中文站
狀態(tài)管理 --vue官網(wǎng)
微信公眾號:前端linong文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/104573.html
摘要:五六月份推薦集合查看最新的請點(diǎn)擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請點(diǎn)擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:解決了組件之間同一狀態(tài)的共享問題。當(dāng)我們的應(yīng)用遇到多個組件之間的共享問題時會需要狀態(tài)管理核心狀態(tài)管理有個核心,分別是以及。當(dāng)錯誤出現(xiàn)時,我們現(xiàn)在也會有一個記錄之前發(fā)生了什么。此外,每個實(shí)例組件仍然可以擁有和管理自己的私有狀態(tài) 一,css部分 1,簡單介紹下css權(quán)重優(yōu)先級: 默認(rèn)樣式 .father{ width:300px; ...
閱讀 2585·2021-11-24 09:39
閱讀 3139·2021-10-15 09:39
閱讀 3273·2021-07-26 23:38
閱讀 2419·2019-08-30 11:14
閱讀 3489·2019-08-29 16:39
閱讀 1780·2019-08-29 15:23
閱讀 889·2019-08-29 13:01
閱讀 2781·2019-08-29 12:29