溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

vue初始化data方法是什么

發(fā)布時間:2022-12-27 10:08:55 來源:億速云 閱讀:143 作者:iii 欄目:web開發(fā)

今天小編給大家分享一下vue初始化data方法是什么的相關(guān)知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

vue初始化data方法有兩種:1、object方式,語法“var data = { 鍵值對 }”;2、function方式,語法“data: function () {return { 鍵值對 }}”。需要注意組件和extend中的data初始化不能是Object,否則會報錯。組件中data用function方式是為了防止多個組件實例對象之間共用一個data,產(chǎn)生數(shù)據(jù)污染。

vue data有兩種初始化的方式,function和object,但是這兩種情況適用場景有哪些?能不能通用?帶著這兩個問題咱們一起分析下

data初始化

// 代碼來源于官網(wǎng)示例

// 第一種定義方式
var data = { a: 1 }

// 直接創(chuàng)建一個實例
var vm = new Vue({
  data: data
})

// Vue.extend() 中 data 必須是函數(shù)
var Component = Vue.extend({
// 第二種定義方式
  data: function () {
    return { a: 1 }
  }
})

上述代碼簡單描述了data定義的兩種方式

  • function

  • object

官網(wǎng)demo中也著重說了extend中data初始化不能用object。那么為什么呢?

源碼分析

按照官網(wǎng)demo,Vue.extend中的data初始化不能是Object,如果我們強制寫成Object會出現(xiàn)什么?

var Component = Vue.extend({
  data: { a: 1 }
})

運行以后chrome的consolo直接報錯,信息如下

vue.esm.js?efeb:591 [Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.

通過分析源碼以及報錯信息,當觸發(fā)Vue.extend的時候,他會做一個合并操作,把一個基礎(chǔ)組件(里面vmode, transtion等)和你定義在extend內(nèi)的信息,通過mergeField往options上合并,當合并到data的時候,他會觸發(fā)strats.data,在這個里面會check data是不是一個function,這里需要注意的是filter、components等和data走的是兩套合并流程,詳細的請看代碼注釋,如下

// vue.extend 源碼地址https://github.com/vuejs/vue/blob/dev/src/core/global-api/extend.js

  Vue.extend = function (extendOptions: Object): Function {
  ...
  // 在這里會觸發(fā)mergeOptions方法
  Sub.options = mergeOptions(
      Super.options,
      extendOptions
    )
  ...
}

// mergeOptions 源碼地址https://github.com/vuejs/vue/blob/dev/src/core/util/options.js

export function mergeOptions (
  parent: Object,
  child: Object,
  vm?: Component
): Object {
  ...

  const options = {}
  let key
  // parent對象內(nèi)包含components、filter,、directive
  for (key in parent) {
    mergeField(key)
  }
  // child對象內(nèi)對應的是Vue.extend內(nèi)定義的參數(shù)
  for (key in child) {
    if (!hasOwn(parent, key)) {
      mergeField(key)
    }
  }
  function mergeField (key) {
  // 這一步是根據(jù)傳入的key找到不同的合并策略filter、components、directives用到合并策略是這個方法mergeAssets和data用到的不一樣,當合并到data的時候會進入專屬的合并策略方法內(nèi)
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
  }
}

// strats.data  源碼地址https://github.com/vuejs/vue/blob/dev/src/core/util/options.js
strats.data = function (
  parentVal,
  childVal,
  vm
) {
  if (!vm) {
  // 如果data不是function的話會直接走下面的報錯信息
    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ā)中同類情況有:子組件內(nèi)、路由內(nèi)都不可以把data定義為一個對象,因為他們底層都調(diào)用了mergeOptions方法

什么時候可以定義成一個對象

在vue初始化的時候,如下

new Vue({
  data: {
    linke: '//sinker.club'
  }
})

意義

ok,上面說了那么多,那么這么做的意義是什么?為什么那幾種情況不可以定義為對象? 其實回答這個問題,需要回到j(luò)s本身,眾所周知js數(shù)據(jù)類型分為引用和基本,引用類型包含Object, Array, Function,何為引用類型就不在這里闡述了

  var obj = {link: '//www.sinker.club'}
  var obj2 = obj
  var obj3 = obj
  obj2.link = "//gitlab.sinker.club"
  console.log(obj3.link) // "//gitlab.sinker.club"

上述代碼反應了一個問題,由于obj3和obj2在內(nèi)存中都是指向一個地址,那么obj2的修改會影響到obj3,當然處理這種問題可以用深copy來做到

  • JSON.parse(JSON.stringify(obj))

  • deepClone(obj)

但是這兩種做法需要開發(fā)或者框架每一次都要深copy一次,當數(shù)據(jù)量大的時候?qū)π阅苁裁炊疾挥押?,那么Vue怎么做的呢?把data定義成一個function

function data() {
  return {
   link: '//sinker.club'
  }
}

var obj = test()
var obj2 = test()

obj2.link ="//gitlab.sinker.club"
console.log(obj.link) '//sinker.club'

為什么這么做?解決的場景是什么呢?

比如我定一個子組件,data是按照對象的方式定義的,這個組件在多個地方引用,如果其中一個引用此組件的data修改了,那么就會造成其余引用此組件的data同時改變, end.

擴展知識:

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

const app = new Vue({
    el:"#app",
    // 對象格式
    data:{
        foo:"foo"
    },
    // 函數(shù)格式
    data(){
        return {
             foo:"foo"
        }
    }
})

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

如果為組件data直接定義為一個對象

Vue.component('component1',{
    template:`<div>組件</div>`,
    data:{
        foo:"foo"
    }})

則會得到警告信息

vue初始化data方法是什么

說明:

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

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

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

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

以上就是“vue初始化data方法是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI