最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue的data為啥只能是函數(shù)原理詳解

 更新時(shí)間:2022年10月19日 14:13:18   作者:當(dāng)然是黑貓警長啦  
這篇文章主要為大家介紹了Vue的data為啥只能是函數(shù)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

在學(xué)習(xí)vue的時(shí)候vue2只有在組件中嚴(yán)格要求data必須是一個(gè)函數(shù),而在普通vue實(shí)例中,data可以是一個(gè)對象,但是在vue3出現(xiàn)后data必須一個(gè)函數(shù),當(dāng)時(shí)看著官方文檔說的是好像是對象的引用問題,但是內(nèi)部原理卻不是很了解,今天通過一個(gè)簡單的例子來說明為啥data必須是一個(gè)函數(shù)

參考 (vue2data描述)

參考: (vue3data描述)

1.Vue3中的data

const { createApp } = Vue
const app = {
    data: {
        a: 1
    },
    template: `
    <h1>{{a}}</h1>
    `
}
createApp(app).mount('#app')

可以看到上來vue就給了警告說明data必須是一個(gè)函數(shù) 下面直接拋錯

2.vue中的data

var app = new Vue({
    el: '#app',
    data: { a: 'hello world' }
})

這種寫法是可以的,前面提過普通實(shí)例data可以是對象,但是在組件中必須是函數(shù), 那么在vue2中難道普通實(shí)例就沒有缺陷嘛?答案:是有缺陷的, 比如這樣

<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個(gè)內(nèi)容為hello world的div標(biāo)簽 那么當(dāng)我們通過實(shí)例去改變messag呢?

 vue1.message = 'hello Vue'

奇怪的事情發(fā)生了,我知識改變了vue1的實(shí)例中的數(shù)據(jù),但是其他實(shí)例的數(shù)據(jù)也發(fā)生了改變,相信很簡單就能看出來這應(yīng)該是共用同一個(gè)對象的引用而導(dǎo)致的,這在開放中是非常不友好的,開發(fā)者很容易就產(chǎn)生連串的錯誤,vue2也知道這種缺陷只是沒有在普通實(shí)例中去體現(xiàn)而已,只在組件中實(shí)現(xiàn)了對于data的約束

為了讓大家更好的立即為啥data必須是一個(gè)函數(shù),黑貓?jiān)诖撕唵螌?shí)現(xiàn)一個(gè)vue的實(shí)例然后來證明為啥data是一個(gè)函數(shù),以及如果data不是一個(gè)函數(shù),我們應(yīng)該如何處理

3.證明data是函數(shù)以及原理實(shí)現(xiàn)

在實(shí)現(xiàn)簡單原理之前,我們需要搞清楚Vue在創(chuàng)建實(shí)例之前,對于data到底做了什么事情簡單來說就是:

vue 在創(chuàng)建實(shí)例的過程中調(diào)用data函數(shù)返回實(shí)例對象通過響應(yīng)式包裝后存儲在實(shí)例的data上并且實(shí)例可以直接越過data上并且實(shí)例可以直接越過data上并且實(shí)例可以直接越過data訪問屬性

1.通過這句描述可以知道Vue是一個(gè)構(gòu)造函數(shù),并且傳入的參數(shù)中有一個(gè)data的屬性,我們可以$data去訪問,也可以直接訪問這個(gè)屬性,并且我們需要對這個(gè)data做代理
那么簡單實(shí)現(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

通過簡單實(shí)現(xiàn)可與看出來,當(dāng)我們的data是一個(gè)函數(shù)的時(shí)候,在Vue的構(gòu)造函數(shù)中,只有有實(shí)例創(chuàng)建就有執(zhí)行data函數(shù),然后返回一個(gè)特別的對象,所以當(dāng)我們修改其中一個(gè)實(shí)例的時(shí)候并不會對其他實(shí)例的數(shù)據(jù)產(chǎn)生變化

那么當(dāng)data不是一個(gè)函數(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

可以看出,由于共用一個(gè)對象,當(dāng)代理的時(shí)候也是對同一個(gè)對象進(jìn)行代理,那么當(dāng)我們通過一個(gè)實(shí)例去改變數(shù)據(jù)的時(shí)候,就會影響其他實(shí)例的狀態(tài)

4.如果data必須是一個(gè)對象呢?

假如有人提出如果data是一個(gè)對象,那么我們應(yīng)該如何處理呢,其實(shí)也非常簡單,在代理的時(shí)候我們可以將傳入的data對象通過深拷貝即可,這樣我們就不會使用相同引用的對象啦。

[深拷貝封裝參考]不一樣的深拷貝 

以上就是Vue的data為啥只能是函數(shù)原理詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue data 函數(shù)原理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

怀化市| 腾冲县| 辽中县| 板桥市| 吴忠市| 广西| 新绛县| 沙雅县| 黄梅县| 浠水县| 都兰县| 日喀则市| 宜君县| 盐亭县| 牡丹江市| 郧西县| 稷山县| 镇坪县| 新化县| 定兴县| 吴旗县| 从化市| 克山县| 噶尔县| 嘉义县| 门源| 启东市| 洛宁县| 宾川县| 那曲县| 苍山县| 大宁县| 开阳县| 闵行区| 肇州县| 瑞金市| 邵武市| 白河县| 乌拉特后旗| 砀山县| 海原县|