談?wù)勔騐ue.js引發(fā)關(guān)于getter和setter的思考
起因
當(dāng)我打印出Vue實(shí)例下的data對象里的屬性時(shí),發(fā)現(xiàn)了一個(gè)有趣的事情:
它的每個(gè)屬性都有兩個(gè)相對應(yīng)的get
和set
方法,我覺的這是多此一舉的,于是去網(wǎng)上查了查Vue雙向綁定的實(shí)現(xiàn)原理,才發(fā)現(xiàn)它和Angular.js雙向綁定的實(shí)現(xiàn)原理完全不同,Angular是用的數(shù)據(jù)臟檢測,當(dāng)Model發(fā)生變化,會(huì)檢測所有視圖是否綁定了相關(guān)數(shù)據(jù),再更改視圖。而Vue使用的發(fā)布訂閱模式,是點(diǎn)對點(diǎn)的綁定數(shù)據(jù)。
Vue的數(shù)據(jù)綁定只有兩個(gè)步驟,compile=>link
。
我一直在想,vue是通過什么去監(jiān)聽用戶對Model的修改,直到我發(fā)現(xiàn)Vue的data里,每個(gè)屬性都有set
和get
屬性,我才明白過來。
在平時(shí),我們創(chuàng)建一個(gè)對象,并修改它的屬性,是這樣的:
var obj = { val:99 } obj.val = 100; console.log(obj.val)//100
沒有任何問題,但是如果要你去監(jiān)測,當(dāng)我修改了這個(gè)對象的屬性時(shí),要去做一些事,你會(huì)怎么做?
相關(guān)思考
這就要用到getter
和setter
了。
假設(shè)我現(xiàn)在要給一個(gè)碼農(nóng)對象添加一個(gè)name
屬性,而且每次更新name
屬性時(shí),我要去完成一些事,我們可以這樣做:
var Coder = function() { var that = this; return { get name(){ if(that.name){ return that.name } return '你還沒有取名' }, set name(val){ console.log('你把名字修成了'+val) that.name = val } } } var isMe = new Coder() console.log(isMe.name) isMe.name = '周神' console.log(isMe.name) console.log(isMe)
輸出:
你會(huì)發(fā)現(xiàn)這個(gè)對象和最上面的Vue中的data
對象,打印出來的效果是一樣的,都擁有get
和set
屬性。
我們來一步步分析下上面的代碼,很有趣。
我們先創(chuàng)建一個(gè)對象字面量:
var Coder = function() {...}
再把this
緩存一下:
var that = this;
接下來是最重要的,我們return
了一個(gè)對象回去:
{ get name(){...}, set name(val){...} }
顧名思義,get為取值,set為賦值,正常情況下,我們?nèi)≈岛唾x值是用obj.prop
的方式,但是這樣做有一個(gè)問題,我如何知道對象的值改變了?所以就輪到set登場了。
你可以把get
和set
理解為function
,當(dāng)然,只是可以這么理解,這是完全不一樣的兩個(gè)東西。
接下來創(chuàng)建一個(gè)碼農(nóng)的實(shí)例,isMe;此時(shí),isMe是沒有name
屬性的,當(dāng)我們調(diào)用isMe.name
時(shí),我們會(huì)進(jìn)入到get name(){...}
中,先判斷isMe是否有name
屬性,答案是否定的,那麼就添加一個(gè)name
屬性,并給它賦值:"你還沒有取名";如果有name
屬性,那就返回name
屬性。
看到這里你一定知道get
怎么使用了,對,你可以把get
看成一個(gè)取值的函數(shù),函數(shù)的返回值就是它拿到的值。
我感覺比較重要的是set
屬性,當(dāng)我給實(shí)例賦值:
isMe.name="周神"
此時(shí),會(huì)進(jìn)入set name(val){...};
形參val就是我賦給name
屬性的值,在這個(gè)函數(shù)里,我就可以做很多事了,比如雙向綁定!因?yàn)檫@個(gè)值的每次改變都必須經(jīng)過set,其他方式是改變不了它的,相當(dāng)于一個(gè)萬能的監(jiān)聽器。
還有另一種方法可以實(shí)現(xiàn)這個(gè)功能。
ES5的對象原型有兩個(gè)新的屬性__defineGetter__
和__defineSetter__
,專門用來給對象綁定get和set。
可以這樣書寫:
var Coder = function() { } Coder.prototype.__defineGetter__('name', function() { if (this.name) { return this.name }else{ return '你還沒有取名' } }) Coder.prototype.__defineSetter__('name', function(val) { this.name = val }) var isMe = new Coder() console.log(isMe.name) isMe.name = '周神' console.log(isMe.name) console.log(isMe)
效果是一樣的,建議使用下面這種方式,因?yàn)槭窃谠蜕蠒鴮?,所以可以繼承和重用。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。
- JavaScript之Getters和Setters 平臺(tái)支持等詳細(xì)介紹
- javascript中的__defineGetter__和__defineSetter__介紹
- JavaScript中setter和getter方法介紹
- Javascript中的getter和setter初識(shí)
- JavaScript的setter與getter方法
- 淺談JS對象添加getter與setter的5種方法
- js中g(shù)etter和setter用法實(shí)例分析
- JavaScript對象訪問器Getter及Setter原理解析
- JavaScript?getter?setter金字塔???????
相關(guān)文章
vue 獲取url參數(shù)、get參數(shù)返回?cái)?shù)組的操作
這篇文章主要介紹了vue 獲取url參數(shù)、get參數(shù)返回?cái)?shù)組的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11Element框架el-tab點(diǎn)擊標(biāo)簽頁時(shí)再渲染問題的解決
本文主要介紹了Element框架el-tab點(diǎn)擊標(biāo)簽頁時(shí)再渲染問題的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04Vue.js?element-plus使用圖標(biāo)不顯示問題的解決方式
近期在學(xué)習(xí)Vue時(shí)用elementUI時(shí)發(fā)現(xiàn)圖標(biāo)在頁面上顯示不出來,所以這篇文章主要給大家介紹了關(guān)于Vue.js?element-plus使用圖標(biāo)不顯示問題的解決方式,需要的朋友可以參考下2022-09-09vue3+ts+echarts實(shí)現(xiàn)按需引入和類型界定方式
這篇文章主要介紹了vue3+ts+echarts實(shí)現(xiàn)按需引入和類型界定方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10vue項(xiàng)目本地開發(fā)使用Nginx配置代理后端接口問題
這篇文章主要介紹了vue項(xiàng)目本地開發(fā)使用Nginx配置代理后端接口問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12