摘要:使用框架進行開發(fā)時,我們在的和中定義屬性和方法,在調(diào)用時直接使用或的形式,而不是用或的方式。項目的地址,后續(xù)會持續(xù)更新,分析的源碼,爭取實現(xiàn)一個精簡版的。中的所有方法都直接在實例重新定義了引用。
使用Vue框架進行開發(fā)時,我們在option的data和methods中定義屬性和方法,在調(diào)用時直接使用 vm.attr 或 vm.func()的形式,而不是用vm.data.attr或vm.methods.func()的方式。
項目的git地址: https://github.com/xubaodian/... ,后續(xù)會持續(xù)更新,分析Vue的源碼,爭取實現(xiàn)一個精簡版的Vue。
Vue解析系列文章如下:
Vue源碼解析(二)Vue的雙向綁定講解及實現(xiàn)
我們傳入Vue的options對象一般為以下這種形式,
{ data: { name: "xxx" }, mounted() { //調(diào)用方法,沒有使用this.methods.getInfo(); this.getInfo(); }, methods: { getInfo() { //獲取屬性,沒有使用this.data.name this.name = "xxxx2314"; //操作等等.... } }, computed: { getName() { return this.name; } }, watch: { "name"(val, oldVal) { //這是操作 } } }
在vue實例中,我們無論data還是method,都直接調(diào)用,這是因為一下vue初始化時做了下面兩點操作:
1、給data中的屬性做了代理,所有訪問和設(shè)置vm[key]時,最終操作的是vm._data[key],而Vue在初始化時,會vm._data其實是options中data的引用。
2、methods中的所有方法都直接在vue實例重新定義了引用。
看下我的實現(xiàn)代碼,是對Vue源碼的精簡,如下:
//vue構(gòu)造函數(shù) class Vue { constructor(options) { //$options存儲構(gòu)造選項 this.$options = options || {}; //data保存構(gòu)造設(shè)置中的data,暫時忽略data為函數(shù)的情況 let data = options.data; this._data = data; //初始化 this._init(); } _init() { //映射key mapKeys(this); //在vue實例上重新定義方法的引用 initMethods(this, this.$options.methods) } } //重新定義方法的引用,注意修改調(diào)用函數(shù)時的上下文環(huán)境,這里用bind,當然也可以用apply和call function initMethods (vm, methods) { for (const key in methods) { vm[key] = typeof methods[key] !== "function" ? noop : methods[key].bind(vm); } } //重新定義data的get和set function mapKeys(vm) { let data = vm._data; if (null !== data && typeof data === "object") { const keys = Object.keys(data); let i = keys.length; while (i-- >= 0) { //所有屬性的操作就重新定向到了_data上 proxy(vm, `_data`, keys[i]); } } } //使用defineProperty重新定義get和set function proxy (target, sourceKey, key) { sharedPropertyDefinition.get = function proxyGetter () { return this[sourceKey][key] } sharedPropertyDefinition.set = function proxySetter (val) { this[sourceKey][key] = val } Object.defineProperty(target, key, sharedPropertyDefinition) } const sharedPropertyDefinition = { enumerable: true, configurable: true, get: noop, set: noop } //空函數(shù),占位用 function noop () {} //使用 let options = { data: { name: "xxx", age: 18 }, methods: { sayName() { console.log(this.name); } } } let vm = new Vue(options); vm.sayName();//控制臺打印了xxx,可以把代碼直接復(fù)制出去試一下
上面代碼就完成了屬性的重新映射和方法的引用重新定義。
看下vue中源碼,,如下,我做了注釋,應(yīng)該比較好懂:
簡單說明一下,源碼中使用了flow作為js代碼的靜態(tài)檢查工具,原理和typescript類似,所以代碼看起來會有些不同,不影響整體閱讀
//初始化,參數(shù)是vue實例 function initData (vm: Component) { //獲取options中的 let data = vm.$options.data //設(shè)置vm._data,判斷data是obj還是函數(shù) data = vm._data = typeof data === "function" ? getData(data, vm) : data || {} if (!isPlainObject(data)) { data = {} process.env.NODE_ENV !== "production" && warn( "data functions should return an object: " + "https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function", vm ) } // proxy data on instance const keys = Object.keys(data) const props = vm.$options.props const methods = vm.$options.methods let i = keys.length while (i--) { const key = keys[i] //這是在開發(fā)環(huán)境打印的一些提示不用關(guān)心 if (process.env.NODE_ENV !== "production") { if (methods && hasOwn(methods, key)) { warn( `Method "${key}" has already been defined as a data property.`, vm ) } } if (props && hasOwn(props, key)) { process.env.NODE_ENV !== "production" && warn( `The data property "${key}" is already declared as a prop. ` + `Use prop default value instead.`, vm ) } else if (!isReserved(key)) { //代理訪問,這就是為何操作vm[key]被定位到vm._data[key]的原因 proxy(vm, `_data`, key) } } const sharedPropertyDefinition = { enumerable: true, configurable: true, get: noop, set: noop } //代理函數(shù) export function proxy (target: Object, sourceKey: string, key: string) { sharedPropertyDefinition.get = function proxyGetter () { return this[sourceKey][key] } sharedPropertyDefinition.set = function proxySetter (val) { this[sourceKey][key] = val } //利用defineProperty設(shè)置對象的get和set,操作屬性時,target[key]會映射到target[sourceKey][key] Object.defineProperty(target, key, sharedPropertyDefinition) } //方法映射 function initMethods (vm: Component, methods: Object) { const props = vm.$options.props for (const key in methods) { //這些都是開發(fā)環(huán)境的提示信息,可以忽略 if (process.env.NODE_ENV !== "production") { if (typeof methods[key] !== "function") { warn( `Method "${key}" has type "${typeof methods[key]}" in the component definition. ` + `Did you reference the function correctly?`, vm ) } if (props && hasOwn(props, key)) { warn( `Method "${key}" has already been defined as a prop.`, vm ) } if ((key in vm) && isReserved(key)) { warn( `Method "${key}" conflicts with an existing Vue instance method. ` + `Avoid defining component methods that start with _ or $.` ) } } //關(guān)鍵在這,重新定義了引用 vm[key] = typeof methods[key] !== "function" ? noop : bind(methods[key], vm) } }
有疑問可以給我留言,或發(fā)郵件至[email protected],歡迎大家來討論
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/100595.html
摘要:上篇文章,我們講解了的屬性映射和方法的重定義,鏈接地址如下源碼解析一屬性映射和函數(shù)引用的重定義這篇文章給大家?guī)淼氖堑碾p向綁定講解。這就是的雙向綁定。使用定時器定時檢查的值,發(fā)生變化就通知訂閱者。這個方法不好,定時器不能實時反應(yīng)變化。 文章中的代碼時階段,可以下載源碼測試一下。git項目地址:https://github.com/xubaodian/...項目使用webpack構(gòu)建,下...
摘要:圖在中應(yīng)用三數(shù)據(jù)渲染過程數(shù)據(jù)綁定實現(xiàn)邏輯本節(jié)正式分析從到數(shù)據(jù)渲染到頁面的過程,在中定義了一個的構(gòu)造函數(shù)。一、概述 vue已是目前國內(nèi)前端web端三分天下之一,也是工作中主要技術(shù)棧之一。在日常使用中知其然也好奇著所以然,因此嘗試閱讀vue源碼并進行總結(jié)。本文旨在梳理初始化頁面時data中的數(shù)據(jù)是如何渲染到頁面上的。本文將帶著這個疑問一點點追究vue的思路??傮w來說vue模版渲染大致流程如圖1所...
摘要:注意指令前面需要加,對指令傳遞數(shù)據(jù)賦值使用例如約定速成加上,表示自定義指令不要使用駝峰式命名。需要通過方法實現(xiàn)自定義指令注冊完成。 vue Vue.js 構(gòu)建數(shù)據(jù)驅(qū)動的web界面庫。集中實現(xiàn)MVVM 的 VM層。容易與其他庫或項目整合 通過盡可能簡單的API實現(xiàn)相應(yīng)的數(shù)據(jù)綁定和組合的視圖組件核心:相應(yīng)的數(shù)據(jù)綁定系統(tǒng), 數(shù)據(jù)與DOM保持同步數(shù)據(jù)驅(qū)動的視圖,普通的HTML模板中使用特殊的語...
摘要:無論是還是都提倡單向數(shù)據(jù)流管理狀態(tài),那我們今天要談的雙向綁定是否和單向數(shù)據(jù)流理念有所違背我覺得不是,從上篇文章語法樹轉(zhuǎn)函數(shù)了解到,雙向綁定,實質(zhì)是的單向綁定和事件偵聽的語法糖。源碼解析今天涉及到的代碼全在文件夾下。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語法樹 AST語法樹轉(zhuǎn)rend...
摘要:無論是還是都提倡單向數(shù)據(jù)流管理狀態(tài),那我們今天要談的雙向綁定是否和單向數(shù)據(jù)流理念有所違背我覺得不是,從上篇文章語法樹轉(zhuǎn)函數(shù)了解到,雙向綁定,實質(zhì)是的單向綁定和事件偵聽的語法糖。源碼解析今天涉及到的代碼全在文件夾下。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語法樹 AST語法樹轉(zhuǎn)rend...
閱讀 965·2021-11-17 09:33
閱讀 424·2019-08-30 11:16
閱讀 2479·2019-08-29 16:05
閱讀 3362·2019-08-29 15:28
閱讀 1402·2019-08-29 11:29
閱讀 1958·2019-08-26 13:51
閱讀 3396·2019-08-26 11:55
閱讀 1214·2019-08-26 11:31