淺析Vue.observable()實現類似vuex的狀態管理功能創建響應式全局數據


一、說明

  我們習慣於用Vuex去解決狀態的共享問題,但是在小項目中使用就會有增大代碼體積和將代碼復雜化的煩惱,所以在Vue(2.6.0)的版本中新增了一個跨組件通信方案:Vue.observable(object)。

  其作用是讓一個對象可響應,Vue 內部會用它來處理 data 函數返回的對象。返回的對象可以直接用於 渲染函數 和 計算屬性 內,並且會在發生改變時觸發相應的更新。也可以作為最小化的跨組件狀態存儲器,用於簡單的場景。

const state = Vue.observable({ count: 0 }) const Demo = { render(h) { return h('button', { on: { click: () => { state.count++ }} }, `count is: ${state.count}`) } }

二、如何使用

  用過vuex的都知道,在我們添加了vuex依賴后,我們為首先會在src目錄下新建一個store文件夾,用來管理我們的狀態,沒有用過的同學可以先去學習一下。

  仿照那種格式,我們也在src目錄下新建store文件夾,並新建子文件 index.jsstate.jsmutations.js。這里,我分別介紹一下這些文件的作用,並附上代碼:

1、state.js:就是一個狀態,存儲全局數據

import Vue from 'vue' export default Vue.observable({ count: 0 })

2、mutations.js:用來更新state;將state.js的數據導入,用於操作

import state from './state' export default { addCount () { state.count++ } }

3、index.js:用來將state與mutations合並成一個對象,並導出;將數據與計數器方法合並為一個store並導出

import state from './state' import mutations from './mutations' export default { state, mutations }

4、在頁面中使用數據(將store 首先導入)

import store from '@/store' // 注意這點並不是vuex // 這樣就可以直接使用
store.state store.mutations

  當然也可以不分文件,直接寫在同一個js里。這樣其實更方便

// 文件路徑 - /store/store.js
import Vue from 'vue' export const store = Vue.observable({ count: 0 }) export const mutations = { setCount (count) { store.count = count } }

  使用

<template>
    <div>
        <label for="bookNum">數 量</label>
            <button @click="setCount(count+1)">+</button>
            <span>{{count}}</span>
            <button @click="setCount(count-1)">-</button>
    </div>
</template>

<script> import { store, mutations } from '../store/store' // Vue2.6新增API Observable
 export default { name: 'Add', computed: { count () { return store.count } }, methods: { setCount: mutations.setCount
  也可以直接 ...mutations,就可以使用mutations里聲明的方法了
} }
</script>

  就這么簡單,輕量好用。

三、源碼解讀

  從源碼可以看出Vue.observable實際就是封裝了observe

  首先判斷是否包含__ob__這個屬性,然后實例化一個Observer對象:

 

  由於傳入的不是數組,進入walk(),在walk中遍歷key,並使用defineReactive$$1創建響應式對象

Walk through all properties and convert them into getter/setters. This method should only be called when value type is Object.
遍歷所有屬性並將它們轉換為getter/setter。僅當值類型為Object時才應調用此方法。

  通過property.get進行取值,通過property.set進行賦值

  接下來調用Object.defineProperty()給對象定義響應式屬性(Object.defineProperty是vue.js實現「響應式系統」的關鍵之一)

  • enumerable,屬性是否可枚舉,默認 false。
  • configurable,屬性是否可以被修改或者刪除,默認 false。
  • get,獲取屬性的方法。(進行依賴收集)(數據劫持)
  • set,設置屬性的方法。(進行響應式更新)

  dep.notify():通過dep.notify()對觀察者watchers進行通知,然后state就成全局響應式對象了。

  需要注意的是:在 Vue 2.x 中,被傳入的對象會直接被 Vue.observable 改變;在 Vue 3.x 中,則會返回一個可響應的代理,而對源對象直接進行修改仍然是不可響應的。因此,為了向前兼容,官方推薦始終操作使用 Vue.observable 返回的對象,而不是傳入源對象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM