亚洲最大看欧美片,亚洲图揄拍自拍另类图片,欧美精品v国产精品v呦,日本在线精品视频免费

  • 站長(zhǎng)資訊網(wǎng)
    最全最豐富的資訊網(wǎng)站

    vue組件中data為啥是函數(shù)

    原因:防止多個(gè)組件實(shí)例對(duì)象之間共用一個(gè)data,產(chǎn)生數(shù)據(jù)污染;采用函數(shù)的形式,initData時(shí)會(huì)將其作為工廠函數(shù)都會(huì)返回全新data對(duì)象。當(dāng)將組件中的data寫成一個(gè)函數(shù),數(shù)據(jù)以函數(shù)返回值形式定義,這樣每復(fù)用一次組件,就會(huì)返回一份新的data,擁有自己的作用域,類似于給每個(gè)組件實(shí)例創(chuàng)建一個(gè)私有的數(shù)據(jù)空間,讓各個(gè)組件實(shí)例維護(hù)各自的數(shù)據(jù)。

    vue組件中data為啥是函數(shù)

    前端(vue)入門到精通課程,老師在線輔導(dǎo):聯(lián)系老師
    Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調(diào)試工具:點(diǎn)擊使用

    本教程操作環(huán)境:windows7系統(tǒng)、vue3版,DELL G3電腦。

    一、實(shí)例和組件定義data的區(qū)別

    vue實(shí)例的時(shí)候定義data屬性既可以是一個(gè)對(duì)象,也可以是一個(gè)函數(shù)

    const app = new Vue({     el:"#app",     // 對(duì)象格式     data:{         foo:"foo"     },     // 函數(shù)格式     data(){         return {              foo:"foo"         }     } })
    登錄后復(fù)制

    組件中定義data屬性,只能是一個(gè)函數(shù)

    如果為組件data直接定義為一個(gè)對(duì)象

    Vue.component('component1',{     template:`<div>組件</div>`,     data:{         foo:"foo"     }})
    登錄后復(fù)制

    則會(huì)得到警告信息

    vue組件中data為啥是函數(shù)

    警告說(shuō)明:返回的data應(yīng)該是一個(gè)函數(shù)在每一個(gè)組件實(shí)例中

    二、組件data定義函數(shù)與對(duì)象的區(qū)別

    上面講到組件data必須是一個(gè)函數(shù),不知道大家有沒(méi)有思考過(guò)這是為什么呢?

    在我們定義好一個(gè)組件的時(shí)候,vue最終都會(huì)通過(guò)Vue.extend()構(gòu)成組件實(shí)例

    這里我們模仿組件構(gòu)造函數(shù),定義data屬性,采用對(duì)象的形式

    function Component(){   } Component.prototype.data = { 	count : 0 }
    登錄后復(fù)制

    創(chuàng)建兩個(gè)組件實(shí)例

    const componentA = new Component() const componentB = new Component()
    登錄后復(fù)制

    修改componentA組件data屬性的值,componentB中的值也發(fā)生了改變

    console.log(componentB.data.count)  // 0 componentA.data.count = 1 console.log(componentB.data.count)  // 1
    登錄后復(fù)制

    產(chǎn)生這樣的原因這是兩者共用了同一個(gè)內(nèi)存地址,componentA修改的內(nèi)容,同樣對(duì)componentB產(chǎn)生了影響?!緦W(xué)習(xí)視頻分享:vue視頻教程、web前端視頻】

    如果我們采用函數(shù)的形式,則不會(huì)出現(xiàn)這種情況(函數(shù)返回的對(duì)象內(nèi)存地址并不相同)

    function Component(){ this.data = this.data() } Component.prototype.data = function (){     return {    count : 0     } }
    登錄后復(fù)制

    修改componentA組件data屬性的值,componentB中的值不受影響

    console.log(componentB.data.count)  // 0 componentA.data.count = 1 console.log(componentB.data.count)  // 0
    登錄后復(fù)制

    vue組件可能會(huì)有很多個(gè)實(shí)例,采用函數(shù)返回一個(gè)全新data形式,使每個(gè)實(shí)例對(duì)象的數(shù)據(jù)不會(huì)受到其他實(shí)例對(duì)象數(shù)據(jù)的污染

    三、原理分析

    首先可以看看vue初始化data的代碼,data的定義可以是函數(shù)也可以是對(duì)象

    源碼位置:/vue-dev/src/core/instance/state.js

    function initData (vm: Component) {   let data = vm.$options.data   data = vm._data = typeof data === 'function'     ? getData(data, vm)     : data || {}     ... }
    登錄后復(fù)制

    data既能是object也能是function,那為什么還會(huì)出現(xiàn)上文警告呢?

    別急,繼續(xù)看下文

    組件在創(chuàng)建的時(shí)候,會(huì)進(jìn)行選項(xiàng)的合并

    源碼位置:/vue-dev/src/core/util/options.js

    自定義組件會(huì)進(jìn)入mergeOptions進(jìn)行選項(xiàng)合并

    Vue.prototype._init = function (options?: Object) {     ...     // merge options     if (options && options._isComponent) {       // optimize internal component instantiation       // since dynamic options merging is pretty slow, and none of the       // internal component options needs special treatment.       initInternalComponent(vm, options)     } else {       vm.$options = mergeOptions(         resolveConstructorOptions(vm.constructor),         options || {},         vm       )     }     ...   }
    登錄后復(fù)制

    定義data會(huì)進(jìn)行數(shù)據(jù)校驗(yàn)

    源碼位置:/vue-dev/src/core/instance/init.js

    這時(shí)候vm實(shí)例為undefined,進(jìn)入if判斷,若data類型不是function,則出現(xiàn)警告提示

    strats.data = function (   parentVal: any,   childVal: any,   vm?: Component ): ?Function {   if (!vm) {     if (childVal && typeof childVal !== "function") {       process.env.NODE_ENV !== "production" &&         warn(           'The "data" option should be a function ' +             "that returns a per-instance value in component " +             "definitions.",           vm         );       return parentVal;     }     return mergeDataOrFn(parentVal, childVal);   }   return mergeDataOrFn(parentVal, childVal, vm); };
    登錄后復(fù)制

    四、結(jié)論

    根實(shí)例對(duì)象data可以是對(duì)象也可以是函數(shù)(根實(shí)例是單例),不會(huì)產(chǎn)生數(shù)據(jù)污染情況

    組件實(shí)例對(duì)象data必須為函數(shù),目的是為了防止多個(gè)組件實(shí)例對(duì)象之間共用一個(gè)data,產(chǎn)生數(shù)據(jù)污染。采用函數(shù)的形式,initData時(shí)會(huì)將其作為工廠函數(shù)都會(huì)返回全新data對(duì)象

    說(shuō)明:

    • vue中組件是用來(lái)復(fù)用的,為了防止data復(fù)用,將其定義為函數(shù)。

    • vue組件中的data數(shù)據(jù)都應(yīng)該是相互隔離,互不影響的,組件每復(fù)用一次,data數(shù)據(jù)就應(yīng)該被復(fù)制一次,之后,當(dāng)某一處復(fù)用的地方組件內(nèi)data數(shù)據(jù)被改變時(shí),其他復(fù)用地方組件的data數(shù)據(jù)不受影響,就需要通過(guò)data函數(shù)返回一個(gè)對(duì)象作為組件的狀態(tài)。

    • 當(dāng)我們將組件中的data寫成一個(gè)函數(shù),數(shù)據(jù)以函數(shù)返回值形式定義,這樣每復(fù)用一次組件,就會(huì)返回一份新的data,擁有自己的作用域,類似于給每個(gè)組件實(shí)例創(chuàng)建一個(gè)私有的數(shù)據(jù)空間,讓各個(gè)組件實(shí)例維護(hù)各自的數(shù)據(jù)。

    • 當(dāng)我們組件的date單純的寫成對(duì)象形式,這些實(shí)例用的是同一個(gè)構(gòu)造函數(shù),由于JavaScript的特性所導(dǎo)致,所有的組件實(shí)例共用了一個(gè)data,就會(huì)造成一個(gè)變了全都會(huì)變的結(jié)果。

    (學(xué)習(xí)視頻分享:web前端開(kāi)發(fā)、編程基礎(chǔ)視頻)

    贊(0)
    分享到: 更多 (0)
    網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)