事情發生在上週(2019-06-06)團隊技術分享的時候。
原由在於一個問題:vue 中多個組件如何使用同一個變量,咱們叫這個變量爲 baseConfig
吧。
說實話我沒想到那麼多人不理解其中的知識。今天我整理一下發出來。html
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。Vuex 能夠幫助咱們管理共享狀態,並附帶了更多的概念和框架。這須要對短時間和長期效益進行權衡。前端
狀態自管理應用包含如下幾個部分:vue
如下是一個表示「單向數據流」理念的簡單示意:vuex
其實看完了上面的介紹,咱們就明白,這是一個很是符合咱們需求的工具。那麼咱們就來看看怎麼去應用。編程
mapState
輔助函數 當一個組件須要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。爲了解決這個問題,咱們可使用 mapState 輔助函數幫助咱們生成計算屬性。store
中獲取的。這樣在經過 mutations
等方式改變以後,咱們的值也會動態更新。const store = new Vuex.Store({ state: { baseConfig: { server_name: 'lilnong.top' } } }) // 建立一個 User 組件 const Serv = { template: `<div>{{ server_name }}</div>`, computed: { server_name() { // this.$store return store.state.baseConfig.server_name } } } const app = new Vue({ el: '#app', store, // 這樣能夠把 store 的實例注入全部的子組件 components: { Serv }, template: ` <div class="app"> <serv></serv> </div> ` })
baseConfig
須要定義在最外面,而後給全部的子組件都傳遞進去,當有改變的時候,子組件也會跟着改變。數組
{ data: { baseConfig: { server_name: 'lilnong.top' } } } <child :server_name="baseConfig.server_name" :baseConfig="baseConfig">
每一個子組件都須要接收。微信
{ props:['server_name', 'baseConfig'],//這種是無默認值,無類型檢查的,正常使用不推薦這種寫法 }
該方案也叫方案二,並非我寫錯了,是由於他們的場景是同樣。
在 Vue Router 的路由中,咱們把組件配置在 routes
中,致使咱們沒法在模板之中傳遞參數。
這裏咱們須要使用他提供的 props
屬性來傳參,文檔地址。jsRun測試地址。lilnong.top測試地址app
const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] const router = new VueRouter({ routes // (縮寫) 至關於 routes: routes }) const app = new Vue({ router }).$mount('#app')
<div id="app"> <h1>Hello App!</h1> <p> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <router-view></router-view> </div>
就是以下使用,定義一個全局對象,而後修改這個全局對象就行了異步
const sourceOfTruth = {} const vmA = new Vue({ data: sourceOfTruth }) const vmB = new Vue({ data: sourceOfTruth })
原理上來說,仍是全局對象,可是經過簡單的規定,來明確數據流向
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 } })
好了,三種方案這裏就已經介紹完了。那開始看看咱們的爭論:全局放個對象的方式不行(對方觀點),數據更新時組件不會自動更新
vue 數據綁定的原理你們都懂吧?經過 defineProperty
來劫持,Dep
收集依賴等等。
對於對象類型的數據,咱們變量裏面保存的實際上是一個指向堆的地址,咱們來看下面的這個例子。
var obj = {};//定義了一個對象,`obj` 存放的是一個地址 obj.a = 1;//經過 `obj` 的地址,找到對象,而後給對象裏面放了 `a=1` ; var obj1 = obj;//把 `obj` 的地址,給 `obj1` 複製了一下 obj1.a = 2;//經過 `obj1` 的地址,找到對象,而後給對象裏面放了 `a=2` ; //這個時候,對象裏面存放的就是{a:2}//console.log(obj, obj1) //這裏引出了另外一個問題 深拷貝與淺拷貝
這裏也就是個人核心原理。
是否是看到上面的原理好簡單?可是每每不是這麼簡單,下面我們分析一下狀況
null
、 undefined
對象覆蓋,就是以下的這個賦值場景。
其實我理解你是想給 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
的數據觀察隊列(新手常常犯的錯誤)
於 JavaScript 的限制,Vue 不能檢測對象屬性的添加或刪除:
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 如今是響應式的 vm.b = 2 // `vm.b` 不是響應式的
對象解決方案 Vue.set(object, propertyName, value)
對象解決方案(實例內) this.$set(object, propertyName, value)
數組更新檢測
將一些方法進行了封裝 push()、pop()、shift()、unshift()、splice()、sort()、reverse()
。
經過上面的方法來改變數組能夠監聽到改變。
因爲 JavaScript 的限制,Vue 不能檢測如下數組的變更:
vm.items[indexOfItem] = newValue
vm.items.length = newLength
共享數據三種方法
對象引用須要注意的地方
obj2={}
Array
與 Object
。String
與 Null
等不包括在內增長數據要注意是否被觀察到
Vue.set
測試地址,採用 setTimeout 來模擬異步操做。當時苦的一批,完了還沒保存。性感碼農,在線編程。
成功的說服了在場的兄弟們,而後週四就拖堂了。