Vue 元件 data 為什麼必須是個函式,而 Vue 的根例項卻沒有此限制?

時間 2021-05-29 23:04:11

1樓:

區別就是元件的例項是否共享data

如果返回函式,元件的例項的data(值)都是單獨的,互不影響。

如果返回物件,那麼元件的所有例項的data都是同乙份,乙個元件例項的data改了,其他元件的例項的data也會變,因為就是同乙份。

2樓:ssh-晨曦時夢見兮

事實上如果元件裡 data 直接寫了乙個物件的話,那麼如果你在模板中多次宣告這個元件,元件中的 data 會指向同乙個引用。

此時如果在某個元件中對 data 進行修改,會導致其他元件裡的 data 也被汙染。而如果使用函式的話,每個元件裡的 data 會有單獨的引用,這個問題就可以避免了。

這個問題我同樣舉個例子來方便理解,假設我們有這樣的乙個元件,其中的 data 直接使用了物件而不是函式:

varCounter=}

注意,這裡的 Counter.data 僅僅是乙個物件而已,它是乙個引用,也就是它是在當前的執行環境下全域性唯一的,它真正的值在堆記憶體中占用了一部分空間。

也就是說,不管利用這份 data 資料建立了多少個元件例項,這個元件例項內部的 data 都指向這乙個唯一的物件。

然後我們在模板中呼叫兩次 Counter 元件:

"a"/>

"b"/>

div>

我們從原理出發,先看看它被編譯成什麼樣的 render 函式:

function

render()}

每乙個 Counter 會被 _c 所呼叫,也就是 createElement,想象一下 createElement 內部會發生什麼,它會直接拿著 Counter 上的 data 這個引用去建立乙個元件。也就是所有的 Counter 元件例項上的 data 都指向同乙個引用。

此時假如 id 為 a 的 Counter 元件內部呼叫了 count++,會去對 data 這個引用上的 count 屬性賦值,那麼此時由於 id 為 b 的 Counter 元件內部也是引用的同乙份 data,它也會感覺到變化而更新元件,這就造成了多個元件之間的資料混亂了。

那麼如果換成函式的情況呢?每建立一次元件例項就執行一次 data() 函式:

function

data()}

// 元件a建立乙份data

consta=

data

()// 元件b建立乙份data

constb=

data()a

===b

// false

是不是一目了然,每個元件擁有了自己的乙份全新的 data,再也不會互相汙染資料了。

3樓:自由的囚徒

data 為什麼必須是個函式?

因為元件是可復用的 Vue 例項,(它們與new Vue接收相同的選項),每用一次元件,都new出來乙個新的元件,。

="components-demo"

>

>button-counter

>

>button-counter

>div>

當元件被建立後,會拿到data引數 。在原始碼中 vue會判斷傳入的data是否是乙個函式,如果是乙個函式就會執行這個函式,此時會返回乙個物件,然後賦值給data。

function

initData(vm

)那我們都知道,物件儲存在棧中的是引用位址。假如說你直接向元件中傳入乙個物件,當我們進行資料修改的時候,就會修改存放在位址(指標)上的值,也就導致了所有元件都發生了改變。

JS 的引用賦值與傳值賦值

而如果data是乙個函式,在傳入元件例項之後會執行此函式,並返回乙個新的物件。也就相當於在棧中重新分配了引用位址。元件之間就不會共享data了。

為什麼vue 的根例項卻沒有此限制?

因為根例項只有乙個 ,不需要被復用 ,因此根例項使用函式或者物件都行。

4樓:Tianfan

API — Vue.js

仔細閱讀文件第五段文字的描述。

當然,實現上完全可以不這麼做。但 vue 選擇了保留兩種方式。

之所以根例項可以不是函式,是因為,只有乙個例項化。不會出現多個例項共享引用同乙個資料物件的現象。

而其他元件,可能會被多次使用,是可能多次例項化。

同時 data 如果是函式時候,可以在返回之前,方便做一些其他的操作。

一句話概括就是, vue 就是這麼設計的。

5樓:尹千江

簡單來說,是因為根元件只會有乙個,而子元件可能會被 new 很多次,如果 data 不用函式返回的話那麼所有的子元件例項的 data 都會指向同乙個物件(元件 options 中你所寫的 data)

6樓:

我是臨時翻了下原始碼,如有錯誤請斧正。

Vue原始碼對data的處理在這個位置

export

function

initState(vm

:Component

)else

,true

/* asRootData */)}

if(opts

.computed

)initComputed(vm

,opts

.computed)if

(opts

.watch

&&opts

.watch

!==nativeWatch)}

我們再看下initData方法

// observe data 依賴收集。

observe

(data

,true

/* asRootData */)}

再節奏看看上面的getData方法做了什麼

export

function

getData

(data

:Function,vm

:Component):

anycatch(e

)}finally

}data.call(vm, vm) 因此我覺得data必須是函式是由於要解決繫結this的引用問題。

比如下面這個demo場景, data是乙個普通物件。

data是乙個普通物件

提示報錯

data是乙個函式

7樓:雪山隔壁

angular就沒有這樣囉嗦的限制,元件例項就是乙個普通的類例項,他的屬性不會被框架做任何的更改,像vue那樣的響應式,屬性劫持是有很大侵入性的,

為什麼 Vue3 的元件庫都在使用 jsx tsx?

我們來倒推原因。作為第三方庫 考慮的是相容可能的場景 需要很多動態化處理jsx就是js的擴充套件,比template靈活 未必都是jsx,但是是有傾向 官方推薦template是有道理的,畢竟針對template有靜態優化。所以這個考量的點在於,需不需要那麼多的動態化處理。 okay哦開 因為越基礎...

什麼是宣告式元件?

陶文 首先要明白介面不是只在時間 t 渲染一次。而是時間 t1 渲染出乙個結果,時間 t2 渲染出乙個結果,時間 t3 渲染出乙個結果 那麼就有兩種做法 你要通過 add remove 的方法來描述,f t1 需要新增多少元件,然後 f t2 要在 t1 的結果上刪掉什麼,新增什麼。這個刪掉的過程需...

PE檔案中 data節區為什麼VirtualSize會大於SizeOfRawData?

這個VirtualSize的大小是編譯器寫的,也就是說c c 執行庫需要在節載入到記憶體後提供額外的記憶體寫入資料。msdn只是告訴你載入進記憶體後額外的大小填充0,並沒有什麼矛盾的。 已登出 VirtualSize按照SectionAlignment對齊SizeOfRawData按照FileAli...