vue初始化data方法有兩種:1、object方式,語法「var data = { 鍵值對}」;2、function方式,語法「data: function () {return { 鍵值對} }」。要注意元件和extend中的data初始化不能是Object,否則會報錯。元件中data用function方式是為了防止多個元件實例物件之間共用一個data,產生資料污染。
本教學操作環境:windows7系統、vue3版,DELL G3電腦。
vue data有兩種初始化的方式,function和object,但這兩種情況適用場景有哪些?能不能通用?帶著這兩個問題咱們一起分析下
data初始化
#// 代码来源于官网示例 // 第一种定义方式 var data = { a: 1 } // 直接创建一个实例 var vm = new Vue({ data: data }) // Vue.extend() 中 data 必须是函数 var Component = Vue.extend({ // 第二种定义方式 data: function () { return { a: 1 } } })
上述程式碼簡單描述了data定義的兩種方式
function
object
官網demo中也著重說了extend中data初始化不能用object 。那為什麼呢?
原始碼分析
依照官網demo,Vue.extend中的data初始化不能是Object,如果我們強制寫成Object會出現什麼?
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.
透過分析原始碼以及報錯訊息,當觸發Vue.extend的時候,他會做一個合併操作,把一個基礎元件(裡面vmode, transtion等)和你定義在extend內的信息,透過mergeField往options上合併,當合併到data的時候,他會觸發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 { ... // 在这里会触发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对象内包含components、filter,、directive for (key in parent) { mergeField(key) } // child对象内对应的是Vue.extend内定义的参数 for (key in child) { if (!hasOwn(parent, key)) { mergeField(key) } } function mergeField (key) { // 这一步是根据传入的key找到不同的合并策略filter、components、directives用到合并策略是这个方法mergeAssets和data用到的不一样,当合并到data的时候会进入专属的合并策略方法内 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) };
其他情況
其實我們上述程式碼只是一個簡單的流程,在實際開發中同類情況有:子元件內、路由內都不可以把data定義為一個對象,因為他們底層都呼叫了mergeOptions方法
什麼時候可以定義成一個物件
在vue初始化的時候,如下
new Vue({ data: { linke: '//sinker.club' } })
意義
ok,上面說了這麼多,那麼這麼做的意義是什麼?為什麼那幾種情況不可以定義為物件? 其實回答這個問題,需要回到js本身,眾所周知js資料型別分為引用和基本,引用型別包含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在記憶體中都是指向一個位址,那麼obj2的修改會影響到obj3,當然處理這種問題可以用深copy來做到
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屬性既可以是一個對象,也可以是一個函數const app = new Vue({ el:"#app", // 对象格式 data:{ foo:"foo" }, // 函数格式 data(){ return { foo:"foo" } } })元件中定義data屬性,只能是一個函數如果為元件data直接定義為一個物件
Vue.component('component1',{ template:`<div>组件</div>`, data:{ foo:"foo" }})則會得到警告訊息
說明:
以上是vue初始化data方法有哪些的詳細內容。更多資訊請關注PHP中文網其他相關文章!