Vue的data為啥只能是函數(shù)原理詳解
前言
在學習vue的時候vue2只有在組件中嚴格要求data必須是一個函數(shù),而在普通vue實例中,data可以是一個對象,但是在vue3出現(xiàn)后data必須一個函數(shù),當時看著官方文檔說的是好像是對象的引用問題,但是內部原理卻不是很了解,今天通過一個簡單的例子來說明為啥data必須是一個函數(shù)
參考 (vue2data描述)
參考: (vue3data描述)
1.Vue3中的data
const { createApp } = Vue const app = { data: { a: 1 }, template: ` <h1>{{a}}</h1> ` } createApp(app).mount('#app')
可以看到上來vue就給了警告說明data必須是一個函數(shù) 下面直接拋錯
2.vue中的data
var app = new Vue({ el: '#app', data: { a: 'hello world' } })
這種寫法是可以的,前面提過普通實例data可以是對象,但是在組件中必須是函數(shù), 那么在vue2中難道普通實例就沒有缺陷嘛?答案:是有缺陷的, 比如這樣
<div id="app1">{{ message }}</div> <div id="app2">{{ message }}</div>
const data = { message: 'hello world' } const vue1 = new Vue({ el: '#app1', data }) const vue2 = new Vue({ el: '#app2', data })
這樣在頁面中會顯示2個內容為hello world的div標簽 那么當我們通過實例去改變messag呢?
vue1.message = 'hello Vue'
奇怪的事情發(fā)生了,我知識改變了vue1的實例中的數(shù)據(jù),但是其他實例的數(shù)據(jù)也發(fā)生了改變,相信很簡單就能看出來這應該是共用同一個對象的引用而導致的,這在開放中是非常不友好的,開發(fā)者很容易就產生連串的錯誤,vue2也知道這種缺陷只是沒有在普通實例中去體現(xiàn)而已,只在組件中實現(xiàn)了對于data的約束
為了讓大家更好的立即為啥data必須是一個函數(shù),黑貓在此簡單實現(xiàn)一個vue的實例然后來證明為啥data是一個函數(shù),以及如果data不是一個函數(shù),我們應該如何處理
3.證明data是函數(shù)以及原理實現(xiàn)
在實現(xiàn)簡單原理之前,我們需要搞清楚Vue在創(chuàng)建實例之前,對于data到底做了什么事情簡單來說就是:
vue 在創(chuàng)建實例的過程中調用data函數(shù)返回實例對象通過響應式包裝后存儲在實例的data上并且實例可以直接越過data上并且實例可以直接越過data上并且實例可以直接越過data訪問屬性
1.通過這句描述可以知道Vue是一個構造函數(shù),并且傳入的參數(shù)中有一個data的屬性,我們可以$data去訪問,也可以直接訪問這個屬性,并且我們需要對這個data做代理
那么簡單實現(xiàn)如下
function Vue(options) { this.$data = proxy(options.data()) } function proxy(options) { return new Proxy(options, { get(target, key, value, receiver) { return Reflect.get(target, key, value, receiver) }, set(target, key, newValue, receiver) { Reflect.set(target, key, newValue, receiver) } }) } const data = function () { return { a: 'hello world' } } const vue1 = new Vue({ data }) const vue2 = new Vue({ data }) vue1.$data.a = 'hello Vue' console.log(vue1.$data.a) // hello Vue console.log(vue2.$data.a) // hello world
通過簡單實現(xiàn)可與看出來,當我們的data是一個函數(shù)的時候,在Vue的構造函數(shù)中,只有有實例創(chuàng)建就有執(zhí)行data函數(shù),然后返回一個特別的對象,所以當我們修改其中一個實例的時候并不會對其他實例的數(shù)據(jù)產生變化
那么當data不是一個函數(shù)呢 ,我們簡單改下代碼,代碼如下
function Vue(options) { this.$data = proxy(options.data) } function proxy(options) { return new Proxy(options, { get(target, key, value, receiver) { return Reflect.get(target, key, value, receiver) }, set(target, key, newValue, receiver) { Reflect.set(target, key, newValue, receiver) } }) } const data = { a: 'hello world' } const vue1 = new Vue({ data }) const vue2 = new Vue({ data }) vue1.$data.a = 'hello Vue' console.log(vue1.$data.a) // hello Vue console.log(vue2.$data.a) // hello Vue
可以看出,由于共用一個對象,當代理的時候也是對同一個對象進行代理,那么當我們通過一個實例去改變數(shù)據(jù)的時候,就會影響其他實例的狀態(tài)
4.如果data必須是一個對象呢?
假如有人提出如果data是一個對象,那么我們應該如何處理呢,其實也非常簡單,在代理的時候我們可以將傳入的data對象通過深拷貝即可,這樣我們就不會使用相同引用的對象啦。
[深拷貝封裝參考]不一樣的深拷貝
以上就是Vue的data為啥只能是函數(shù)原理詳解的詳細內容,更多關于Vue data 函數(shù)原理的資料請關注腳本之家其它相關文章!
相關文章
Vue+axios 實現(xiàn)http攔截及路由攔截實例
這篇文章主要介紹了Vue+axios 實現(xiàn)http攔截及路由攔截 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04Vue+ECharts+高德地圖API實現(xiàn)天氣預報數(shù)據(jù)可視化的教程
所謂數(shù)據(jù)可視化,我們可以理解為從宏觀角度來看一眼就能看出來整個數(shù)據(jù)的占比,走向,對于數(shù)據(jù)可視化,很多互聯(lián)網(wǎng)公司是很看重這一塊的,包括大廠,本就將給大家介紹如何通過Vue+ECharts+高德地圖API實現(xiàn)天氣預報數(shù)據(jù)可視化2023-06-06如何在Vue單頁面中進行業(yè)務數(shù)據(jù)的上報
為什么要在標題里加上一個業(yè)務數(shù)據(jù)的上報呢,因為在咱們前端項目中,可上報的數(shù)據(jù)維度太多,比如還有性能數(shù)據(jù)、頁面錯誤數(shù)據(jù)、console捕獲等。這里我們只講解業(yè)務數(shù)據(jù)的埋點。2021-05-05