Vue.observable 是什么

Observable?翻譯過來我們可以理解成可觀察的

Vue.js2.6?新增

Vue.observable,讓一個對象變成響應式數據。Vue?內部會用它來處理?data?函數返回的對象 。

返回的對象可以直接用于渲染函數和計算屬性內,并且會在發生變更時觸發相應的更新。也可以作為最小化的跨組件狀態存儲器

Vue.observable({ count : 1})
其作用等同于
new vue({ count : 1})

?在?Vue 2.x?中,被傳入的對象會直接被?Vue.observable?變更,它和被返回的對象是同一個對象

在?Vue 3.x?中,則會返回一個可響應的代理,而對源對象直接進行變更仍然是不可響應的

Observable 是什么

Vue.observable 是 Vue.js 提供的一個 API,它可以將一個普通的 JavaScript 對象轉換為響應式對象。通過使用 Vue.observable,可以在任何地方創建一個響應式對象,而不僅僅是在 Vue 實例中使用。它在 Vue.js 的響應式系統中扮演了很重要的角色,可以用于管理狀態、狀態共享等場景。

Observable 作用

使用 Vue.observable 可以將一個普通對象轉換為響應式對象,從而使其成為 Vue.js 的響應式系統的一部分。在轉換之后,可以對該對象進行讀取、修改等操作,并且在修改后,Vue.js 會自動進行重新渲染。

解決了什么問題

Vue.observable 的出現解決了在 Vue.js 中管理狀態的問題。在 Vue.js 中,通過將狀態保存在 Vue 實例的 data 屬性中,可以實現狀態管理,但是這種方式只能在 Vue 實例中使用,無法在其他地方使用。通過使用 Vue.observable,我們可以在任何地方創建一個響應式對象,從而更加靈活地管理狀態。

適用場景

非父子組件通信時,可以使用通常的bus或者使用vuex,但是實現的功能不是太復雜,而使用上面兩個又有點繁瑣。這時,observable就是一個很好的選擇。

舉個例子:

// utils.js 文件
import Vue from 'vue'
// 創建響應式對象
export const state = Vue.observable({count: 1
})export const mutations = Vue.observable({increase() {state.count++}
})
// 在 vue 文件中使用
<template><div id="app"><button @click="increaseCount">+</button>{{ num }}</div>
</template><script>
import { state, mutations } from '@/utils/index'
export default {name: 'App',computed: {num() {return state.count}},methods: {increaseCount: mutations.increase}
}
</script>

原理分析

源碼位置:src\core\observer\index.js

export function observe (value: any, asRootData: ?boolean): Observer | void {if (!isObject(value) || value instanceof VNode) {return}let ob: Observer | void// 判斷是否存在__ob__響應式屬性if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {ob = value.__ob__} else if (shouldObserve &&!isServerRendering() &&(Array.isArray(value) || isPlainObject(value)) &&Object.isExtensible(value) &&!value._isVue) {// 實例化Observer響應式對象ob = new Observer(value)}if (asRootData && ob) {ob.vmCount++}return ob
}

Observer

export class Observer {value: any;dep: Dep;vmCount: number; // number of vms that have this object as root $dataconstructor (value: any) {this.value = valuethis.dep = new Dep()this.vmCount = 0def(value, '__ob__', this)if (Array.isArray(value)) {if (hasProto) {protoAugment(value, arrayMethods)} else {copyAugment(value, arrayMethods, arrayKeys)}this.observeArray(value)} else {// 實例化對象是一個對象,進入walk方法this.walk(value)}
}

walk函數

walk (obj: Object) {const keys = Object.keys(obj)// 遍歷key,通過defineReactive創建響應式對象for (let i = 0; i < keys.length; i++) {defineReactive(obj, keys[i])}
}

defineReactive方法

export function defineReactive (obj: Object,key: string,val: any,customSetter?: ?Function,shallow?: boolean
) {const dep = new Dep()const property = Object.getOwnPropertyDescriptor(obj, key)if (property && property.configurable === false) {return}// cater for pre-defined getter/settersconst getter = property && property.getconst setter = property && property.setif ((!getter || setter) && arguments.length === 2) {val = obj[key]}let childOb = !shallow && observe(val)// 接下來調用Object.defineProperty()給對象定義響應式屬性Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter () {const value = getter ? getter.call(obj) : valif (Dep.target) {dep.depend()if (childOb) {childOb.dep.depend()if (Array.isArray(value)) {dependArray(value)}}}return value},set: function reactiveSetter (newVal) {const value = getter ? getter.call(obj) : val/* eslint-disable no-self-compare */if (newVal === value || (newVal !== newVal && value !== value)) {return}/* eslint-enable no-self-compare */if (process.env.NODE_ENV !== 'production' && customSetter) {customSetter()}// #7981: for accessor properties without setterif (getter && !setter) returnif (setter) {setter.call(obj, newVal)} else {val = newVal}childOb = !shallow && observe(newVal)// 對觀察者watchers進行通知,state就成了全局響應式對象dep.notify()}})
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/165086.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165086.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165086.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Git的指令

Git 各平臺安裝包下載地址為&#xff1a;http://git-scm.com/downloads Ubuntu Git 安裝命令為&#xff1a; $ apt-get install git用戶信息 配置個人的用戶名稱和電子郵件地址&#xff1a; $ git config --global user.name "runoob" $ git config --global user.…

Python----類對象和實例對象

目錄 一.類和類的實例 二.類屬性和實例屬性 三.私有屬性和公有屬性 四.靜態方法和類方法 五.__init__方法&#xff0c;__new__方法和__del__方法&#xff1a; 六.私有方法和公有方法 七.方法的重載 八.方法的繼承 九.方法的重寫 十.對象的特殊方法 十一.對象的引用&a…

軟件開發模式開源和閉源的優劣之爭

開源和閉源&#xff0c;兩種截然不同的開發模式&#xff0c;對于大模型的發展有著重要影響。開源讓技術共享&#xff0c;吸引了眾多人才加入&#xff0c;推動了大模的創新。而閉源則保護了商業利益和技術優勢&#xff0c;為大模型的商業應用提供了更好的保障。 開源與閉源軟件的…

基于命令行模式設計退款請求處理

前言 這篇文章的業務背景是基于我的另一篇文章: 對接蘋果支付退款退單接口-CSDN博客 然后就是說設計模式是很開放的東西,可能我覺得合適,你可能覺得不合適,這里只是做下討論,沒有一定要各位同意的意思.... 相關圖文件 這里我先把相關的圖文件放上來,可能看著會比較清晰點 代碼邏…

sql之left join、right join、inner join的區別

sql之left join、right join、inner join的區別 left join(左聯接) 返回包括左表中的所有記錄和右表中聯結字段相等的記錄 right join(右聯接) 返回包括右表中的所有記錄和左表中聯結字段相等的記錄 inner join(等值連接) 只返回兩個表中聯結字段相等的行 舉例如下&#xff1…

Web服務器(go net/http) 處理Get、Post請求

大家好 我是寸鐵&#x1f44a; 總結了一篇Go Web服務器(go net/http) 處理Get、Post請求的文章? 喜歡的小伙伴可以點點關注 &#x1f49d; 前言 go http請求如何編寫簡單的函數去拿到前端的請求(Get和Post) 服務器(后端)接收到請求后&#xff0c;又是怎么處理請求&#xff0c…

【限時免費】20天拿下華為OD筆試之【前綴和】2023B-尋找連續區間【歐弟算法】全網注釋最詳細分類最全的華為OD真題題解

文章目錄 題目描述與示例題目描述輸入描述輸出描述示例一輸入輸出說明 示例二輸入輸出 解題思路代碼PythonJavaC時空復雜度 華為OD算法/大廠面試高頻題算法練習沖刺訓練 題目描述與示例 題目描述 給定一個含有N個正整數的數組&#xff0c;求出有多少個連續區間&#xff08;包…

【網絡奇緣】- 計算機網絡|分層結構|ISO模型

&#x1f308;個人主頁: Aileen_0v0&#x1f525;系列專欄: 一見傾心,再見傾城 --- 計算機網絡~&#x1f4ab;個人格言:"沒有羅馬,那就自己創造羅馬~" 目錄 計算機網絡分層結構 OSI參考模型 OSI模型起源 失敗原因: OSI模型組成 協議的作用 &#x1f4dd;全文…

二十四、RestClient操作文檔

目錄 一、新增文檔 1、編寫測試代碼 二、查詢文檔 1、編寫測試代碼 三、刪除文檔 1、編寫測試代碼 四、修改文檔 1、編寫測試代碼 五、批量導入文檔 批量查詢 一、新增文檔 1、編寫測試代碼 SpringBootTest public class HotelDocumentTest {private RestHighLevelC…

【棧】不同字符的最小子序列

題目&#xff1a; /*** 思路&#xff1a;棧,使用數組記錄每個字母出現的次數&#xff0c;再用一個數組標記字符是否在棧中* 遍歷棧&#xff0c;存儲字符時比較棧頂字符&#xff0c;若小于棧頂字符并且后面有重復的字符則* 棧頂元素出棧&#xff0c;否則入棧。** au…

PS 注釋工具 基礎使用方法講解

好 上文PS 顏色取樣器&標尺工具 基本使用講解中 我們講了 顏色取樣器和標尺工具的基本用法 下面我們來看一下 注釋工具 這個 主要是后面 比較大的作品 可能不是我們一個人取設計 團隊作圖 就需要用到它 選擇 注釋工具 后 我們隨便點擊圖像任何一個位置 右側就會出現一個輸…

gitlab各版本安裝注意點:

研發團隊在安裝gitlab各版本過程中可能遇到各種問題&#xff0c;為了后續容易查看特將我們在實踐過程中遇到的各類問題要點總結如下&#xff1a; gitlab 10.8.3 (564c342&#xff09;安裝 centos Linux yum安裝網址查找網址&#xff1a;gitlab/gitlab-ce - Results for gitla…

執行shell腳本提示syntax error: unexpected end of file

具體報錯如下&#xff1a; ./test.sh: line 36: syntax error: unexpected end of file執行命令時需將test.sh替換為實際的腳本文件名稱。 情形一&#xff1a; shell腳本在Windows下編寫&#xff0c;上傳到Linux上執行&#xff0c;由于 fileformat 類型不同&#xff0c;所以報…

黑馬點評12-實現好友關注/取關功能,查看好友共同關注列表

好友關注 數據模型 數據庫中的tb_follow記錄博主與粉絲的關系 tb_follow表對應的實體類 Data EqualsAndHashCode(callSuper false) Accessors(chain true) TableName("tb_follow") public class Follow implements Serializable {private static final long ser…

代碼隨想錄算法訓練營第三十二天| 122 買賣股票的最佳時機 || 55 跳躍游戲 45 跳躍游戲 ||

目錄 122 買賣股票的最佳時機 || 55 跳躍游戲 45 跳躍游戲 || 122 買賣股票的最佳時機 || 設置變量now代表此時買入的股票&#xff0c;為賦值為Integer.MAX_VALUE&#xff0c;遍歷prices數組&#xff0c;有如下兩種情況&#xff1a; 如果比now小說明不能售出&#xff0c;可以…

關于unicloud云對象或云函數獲取時間不對的問題

話不多說&#xff0c;直接上代碼&#xff1a; function timeWeekFormat() { //定義一個日期對象; var dateTime getOffsetDate(8); //獲得系統年份; var year dateTime.getFullYear(); //獲得系統月份; var month dateTime.getMonth() 1; //獲…

棧和隊列的OJ題--12.括號匹配

12.括號匹配 20. 有效的括號 - 力扣&#xff08;LeetCode&#xff09; 解題思路&#xff1a;該題比較簡單&#xff0c;是對棧特性很好的應用&#xff0c;具體操作如下&#xff1a;循環遍歷String中的字符&#xff0c;逐個取到每個括號&#xff0c;如果該括號是&#xff1a;1. …

Git工作流和Commit規范

Git大家都非常熟悉了&#xff0c;就不做過多介紹&#xff0c;但是如何用好Git、如何進行合理的分支開發、Merge你是否有一個規范流程呢&#xff1f;&#x1f4a4; 不論是一個團隊一起開發一個項目&#xff0c;還是自己獨立開發一個項目&#xff0c;都少不了要和Git打交道&…

【NGINX--5】身份驗證

1、HTTP 基本身份驗證 需要通過 HTTP 基本身份驗證保護應用或內容。 生成以下格式的文件&#xff0c;其中的密碼使用某個受支持的格式進行了加密或哈希處理&#xff1a; # comment name1:password1 name2:password2:comment name3:password3第一個字段是用戶名&#xff0…

紫光展銳V8821榮獲“中國芯”重大創新突破產品獎

近日&#xff0c;“中國芯”優秀產品評選落下帷幕&#xff0c;紫光展銳首顆5G IoT-NTN衛星通信SoC芯片V8821憑借在衛星通信前沿領域的技術創新&#xff0c;從285家芯片企業、398款芯片產品中脫穎而出&#xff0c;榮獲第十八屆“中國芯”年度重大創新突破產品獎。 “中國芯”優…