從感性的角度講,我是不屑于用VUE,覺得react套件用起來更順手,但是vue現(xiàn)在越來火,所以也不得入vue(雜燴湯)的坑。vue/anguarJS/React,三者對關(guān)系現(xiàn)在就是:
專注于為中小企業(yè)提供成都網(wǎng)站建設(shè)、做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)劍河免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了1000多家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。https://www.zhoulujun.cn/uploadfile/images/2018/0626/20180626214906428779269.jpg
自己ps了下,覺得深有道理,騷年們自己體悟,然后再問軍哥^_^
不過回歸真題,看vue還是先了解下https://cdn.zhoulujun.cn/vue.jpg(太大,自己打開)
vue所有功能的實現(xiàn)都是圍繞其生命周期進(jìn)行的,在生命周期的不同階段調(diào)用對應(yīng)的鉤子函數(shù)可以實現(xiàn)組件數(shù)據(jù)管理和DOM渲染兩大重要功能。學(xué)習(xí)實例的生命周期,能幫助我們理解vue實例的運行機(jī)制,更好地利用鉤子函數(shù)完成我們的業(yè)務(wù)代碼。
create 和 mounted 相關(guān) 的函數(shù)有:
beforecreated》created》beforeMount》mounted》beforeDestroy
beforecreated:el 和 data 并未初始化, 案例:可以在這加個loading事件 及獲取路由參數(shù),但是this.(data|computed|methods)參數(shù)均為undefind(無法訪問到 el 屬性和 data 屬性等)
在beforeCreate和created之間:在這個生命周期之間,進(jìn)行初始化事件,進(jìn)行數(shù)據(jù)的觀測,可以看到在created的時候數(shù)據(jù)已經(jīng)和data屬性進(jìn)行綁定(放在data中的屬性當(dāng)值發(fā)生改變的同時,視圖也會改變)
created:組件實例創(chuàng)建完成,屬性已綁定,但 DOM 還未生成,$el 屬性還不存在(this.$refs.XXX===undfined)。案例:在這結(jié)束loading,還做一些初始化,如根據(jù)父組件props計算當(dāng)前組件數(shù)據(jù)
created和beforeMount之間:首先會判斷對象是否有el選項。如果有的話就繼續(xù)向下編譯,如果沒有el選項,則停止編譯,也就意味著停止了生命周期,直到在該vue實例上調(diào)用vm.$mount(el)。再次判斷template參數(shù)選項的有無(因為vue需要通過el找到對應(yīng)的outer template):
(1)如果vue實例對象中有template參數(shù)選項,則將其作為模板編譯成render函數(shù)。
(2)如果沒有template選項,則將外部HTML作為模板編譯。
(3)可以看到template中的模板優(yōu)先級要高于outer HTML的優(yōu)先級。
如果沒有template,則通過render傳人的createElement編譯
綜合排名優(yōu)先級:render函數(shù)選項 > template選項 > outer HTML.
這里沒有看懂,可以看一下官方文檔 獨立構(gòu)建和運行時構(gòu)建
beforeMount:完成了 el 和 data 初始化 ??樱喝绻苯邮褂脅{msg}} 在生命周期beforeMount期間,此刻的msg數(shù)據(jù)尚未編譯至{{msg}}中,用戶能看到一瞬間的{{msg}} v-cloak
beforeMount和mounted之間:給vue實例對象添加$el成員,并且替換掉掛在的DOM元素
mounted :完成掛載 案例: 在這發(fā)起后端請求,拿回數(shù)據(jù),配合路由鉤子做一些事情
beforeUpdate:可以監(jiān)聽到data的變化但是view層沒有被重新渲染,view層的數(shù)據(jù)沒有變化
beforeUpdate和update之間:當(dāng)vue發(fā)現(xiàn)data中的數(shù)據(jù)發(fā)生了改變,會觸發(fā)對應(yīng)組件的重新渲染(重新渲染虛擬 dom,并通過 diff 算法對比 vnode 節(jié)點差異更新真實 dom (virtual DOM re-render and patch)),先后調(diào)用beforeUpdate和updated鉤子函數(shù)(beforeUpdate:可以監(jiān)聽到data的變化但是view層沒有被重新渲染,view層的數(shù)據(jù)沒有變化,updated: view層才被重新渲染,數(shù)據(jù)更新。此處可回顧下react對更新函數(shù)。
updated:候 view層才被重新渲染,數(shù)據(jù)更新
beforeDestroy 組件銷毀之前,案例:你確認(rèn)刪除XX嗎?第二個:比如走馬燈文字,路由跳轉(zhuǎn)之后,因為組件已經(jīng)銷毀了,但是setInterval還沒有銷毀,還在繼續(xù)后臺調(diào)用,控制臺會不斷報錯,如果運算量大的話,無法及時清除,會導(dǎo)致嚴(yán)重的頁面卡頓。解決辦法:在組件生命周期beforeDestroy停止setInterval
destroyed :當(dāng)前組件已被刪除,清空相關(guān)內(nèi)容 。實例銷毀后雖然 dom 和屬性方法都還存在,但改變他們都將不再生效!
這這里順便回顧下react生命周期
getDefaultProps()+getInitialState() es5≈ es6 contruct()
函數(shù)初始化。定時init state,也可訪問props。 這個階段,相當(dāng)于 vue的create 函數(shù)該做的事情。
componentWillMount()
組件初始化時只調(diào)用,以后組件更新不調(diào)用,整個生命周期只調(diào)用一次,在客戶端也在服務(wù)端,此時可以修改state。這個階段應(yīng)該相當(dāng)于 vue的 beforeMount()
render()
react最重要的步驟,創(chuàng)建虛擬dom,進(jìn)行diff算法,更新dom樹都在此進(jìn)行。此時就不能更改state了。 這個相當(dāng)于 vue mounted
componentDidMount()()
組件渲染之后調(diào)用,只調(diào)用一次,只在客戶端。這個階段,一般的異步數(shù)據(jù)放在這個函數(shù)內(nèi)處理
componentWillReceiveProps(nextProps)
組件初始化時不調(diào)用,組件接受新的props時調(diào)用。
shouldComponentUpdate(nextProps, nextState)
react性能優(yōu)化非常重要的一環(huán)。組件接受新的state或者props時調(diào)用,我們可以設(shè)置在此對比前后兩個props和state是否相同,如果相同則返回false阻止更新,因為相同的屬性狀態(tài)一定會生成相同的dom樹,這樣就不需要創(chuàng)造新的dom樹和舊的dom樹進(jìn)行diff算法對比,節(jié)省大量性能,尤其是在dom結(jié)構(gòu)復(fù)雜的時候。但是state依然會保持更新。
這這里,是vue PK react 的重點。
Vue宣稱可以更快地計算出Virtual DOM的差異,這是由于它在渲染過程中,會跟蹤每一個組件的依賴關(guān)系,不需要重新渲染整個組件樹。
而對于React而言,每當(dāng)應(yīng)用的狀態(tài)被改變時,全部子組件都會重新渲染。當(dāng)然,這可以通過shouldComponentUpdate這個生命周期方法來進(jìn)行控制,但Vue將此視為默認(rèn)的優(yōu)化。
小結(jié):如果你的應(yīng)用中,交互復(fù)雜,需要處理大量的UI變化,那么使用Virtual DOM是一個好主意。如果你更新元素并不頻繁,那么Virtual DOM并不一定適用,性能很可能還不如直接操控DOM。
componentWillUpdata(nextProps, nextState)
組件初始化時不調(diào)用,只有在組件將要更新時才調(diào)用,此時可以修改state。這個一般沒有生命卵用??赡躷oast一下。 大致相當(dāng)于vue的beforeUpdate
componentDidUpdate()
組件初始化時不調(diào)用,組件更新完成后調(diào)用,此時可以獲取dom節(jié)點。
componentWillUnmount()
組件將要卸載時調(diào)用,一些事件監(jiān)聽和定時器需要在此時清除。相當(dāng)于vue的beforeDestroy
相比來講,覺得react的生命周期更加清爽。建議參看:重談react優(yōu)勢——react技術(shù)?;仡?/p>
路由是項目等重點,很多事情可以在路由里面處理好。路由和store等規(guī)劃項目基礎(chǔ)架構(gòu)核心,沒有好的規(guī)劃,工程就是一坨屎。
作用于所有路由切換,一般在main.js里面定義
beforeEach:一般在這個勾子的回調(diào)中,對路由進(jìn)行攔截。比如,未登錄的用戶,直接進(jìn)入了需要登錄才可見的頁面,那么可以用next(false)來攔截,使其跳回原頁面等,值得注意的是,如果沒有調(diào)用next方法,那么頁面將卡在那。
next的四種用法
next() 跳入下一個頁面
next('/path') 改變路由的跳轉(zhuǎn)方向,使其跳到另一個路由
next(false) 返回原來的頁面
next((vm)=>{}) 僅在beforeRouteEnter中可用,vm是組件實例。
afterEach :在所有路由跳轉(zhuǎn)結(jié)束的時候調(diào)用,和beforeEach是類似的,但是它沒有next方法,這里比如做修改標(biāo)簽標(biāo)題: document.title = to.meta.title等工作。
和全局勾子不同的是,它僅僅作用于某個組件,一般在.vue文件中去定義。
beforeRouteEnter
這個是一個很不同的勾子。因為beforeRouterEnter在組件創(chuàng)建之前調(diào)用,所以它無法直接用this來訪問組件實例。
為了彌補(bǔ)這一點,vue-router開發(fā)人員,給他的next方法加了特技,可以傳一個回調(diào),回調(diào)的第一個參數(shù)即是組件實例。
一般我們可以利用這點,對實例上的數(shù)據(jù)進(jìn)行修改,調(diào)用實例上的方法。
我們可以在這個方法去請求數(shù)據(jù),在數(shù)據(jù)獲取到之后,再調(diào)用next就能保證你進(jìn)頁面的時候,數(shù)據(jù)已經(jīng)獲取到了。沒錯,這里next有阻塞的效果。你沒調(diào)用的話,就會一直卡在那
beforeRouteLeave
在離開路由時調(diào)用??梢杂胻his來訪問組件實例。但是next中不能傳回調(diào)。
beforeRouteUpdate:
這個方法是vue-router2.2版本加上的。因為原來的版本中,如果一個在兩個子路由之間跳轉(zhuǎn),是不觸發(fā)beforeRouteLeave的。這會導(dǎo)致某些重置操作,沒地方觸發(fā)。在之前,我們都是用watch $route來hack的。但是通過這個勾子,我們有了更好的方式。
bind:只調(diào)用一次,指令第一次綁定到元素時調(diào)用,用這個鉤子函數(shù)可以定義一個在綁定時執(zhí)行一次的初始化動作。
inserted:被綁定元素插入父節(jié)點時調(diào)用(父節(jié)點存在即可調(diào)用,不必存在于 document 中)。
實際上是插入vnode的時候調(diào)用。
update:被綁定元素所在的模板更新時調(diào)用,而不論綁定值是否變化。通過比較更新前后的綁定值,可以忽略不必要的模板更新。
慎用,如果在指令里綁定事件,并且用這個周期的,記得把事件注銷
componentUpdated:被綁定元素所在模板完成一次更新周期時調(diào)用。
unbind:只調(diào)用一次, 指令與元素解綁時調(diào)用。
一個頁面跳轉(zhuǎn),發(fā)生的事情
路由勾子 (beforeEach、beforeRouteEnter、afterEach)
根組件 (beforeCreate、created、beforeMount)
組件 (beforeCreate、created、beforeMount)
指令 (bind、inserted)
組件 mounted
根組件 mounted
beforeRouteEnter的next的回調(diào)
nextTick
結(jié)論:
路由勾子執(zhí)行周期非常早,甚至在根實例的渲染之前
具體的順序 router.beforeEach > beforeRouteEnter > router.afterEach
tip:在進(jìn)行路由攔截的時候要避免使用實例內(nèi)部的方法或?qū)傩浴?/p>
在開發(fā)項目時候,我們腦門一拍把,具體攔截的程序,寫在了根實例的方法上了,到beforeEach去調(diào)用。結(jié)果導(dǎo)致整個攔截的周期,推遲到實例渲染的之后。
因此對于一些路由組件的beforeRouteEnter里的請求并無法攔截,頁面看上去好像已經(jīng)攔截下來了。
實際上請求依然發(fā)了出去,beforeRouteEnter內(nèi)的函數(shù)依然執(zhí)行了。
指令的綁定在組件mounted之前,組件的beforeMount之后
不得不提的, beforeRouteEnter的next勾子
beforeRouteEnter的執(zhí)行順序是如此靠前,而其中next的回調(diào)勾子的函數(shù),執(zhí)行則非??亢螅趍ounted之后??!
我們通常是在beforeRouteEnter中加載一些首屏用數(shù)據(jù),待數(shù)據(jù)收到后,再調(diào)用next勾子,通過回調(diào)的參數(shù)vm將數(shù)據(jù)綁定到實例上。
因此,請注意next的勾子是非??亢蟮?。
nextTick:越早注冊的nextTick觸發(fā)越早
上文講了這么多的router,順勢總結(jié)下:
:to :相當(dāng)于a標(biāo)簽中的"herf"屬性,后面跟跳轉(zhuǎn)鏈接所用
replace:replace在routre-link標(biāo)簽中添加后,頁面切換時不會留下歷史記錄
tag:具有tag屬性的router-link會被渲染成相應(yīng)的標(biāo)簽
active-class:這個屬性是設(shè)置激活鏈接時class屬性,也就是當(dāng)前頁面所有與當(dāng)前地址所匹配的的鏈接都會被添加class屬性
exact:開啟router-link的嚴(yán)格模式
用了vue-router,證明項目工程還是蠻大的,建議使用vuex來做全局?jǐn)?shù)據(jù)管理(可能用redux習(xí)慣了吧?。?/p>
vuex的store天生自帶modules概念,同時也需要thunk中間件,action處理異步數(shù)據(jù)。下面copy一點我項目code demo:
const store = new Vuex.Store({ modules: { authForm: authFormStore, BankAdd:BankAddFormStore } });
下面是store的示范
const authFormStore = { state: { name: "" }, mutations: { update: function (state, obj) { //我原來也是寫了N多個update函數(shù),圖樣圖森破啊 state[obj.name] = obj.value; }, }, action: { setData: function (context, obj) { //TODO Vue.http.post("api", params, {emulateJSON: true}).then(function (res) { // 處理業(yè)務(wù) // 調(diào)用上面setAgree方法更新點贊數(shù) context.commit(obj.name, obj.value); }, function () { }) }, }, getters: { getNews(state){ //TODO return new value } } }
在vue組件mapState
computed: { memberType: function () { let memberType = this.$route.params.memberType; this.initWeChat(window.location.href, memberType); return memberType; }, ...mapState({ authForm: state => state.authForm, epCertType: state => state.authForm.epCertType }) },
這里有坑:表單的v-model屬性值是Vuex的state時,如果時嚴(yán)格模式,因為用戶輸入時,v-model會試圖修改v-model的值,由于修改并非mutation執(zhí)行的,嚴(yán)格模式下會拋出錯誤。
針對這種情況,有兩個處理方法:一個是雙向綁定的計算屬性,一個是給表單綁定value,然后偵聽input或change事件,在事件中調(diào)用action。
computed:{ message:{ get(){ return this.$store.obj.message }, set(value){ this.$store.commit('updateMessage',value) } } }
第二種方法
computed:{ ...mapState({ message: state => state.obj.message }) }, methods:{ updateMessage(e){ this.$store.commit('updateMessage',e.target.value) } } mutations:{ //store mutation函數(shù) updateMessage(state,message){ state.obj.message=message } }
Vue.js 最核心的功能有兩個,一是響應(yīng)式的數(shù)據(jù)綁定系統(tǒng),二是組件系統(tǒng)
所謂雙向綁定,指的是vue實例中的data與其渲染的DOM元素的內(nèi)容保持一致,無論誰被改變,另一方會相應(yīng)的更新為相同的數(shù)據(jù)。這是通過設(shè)置屬性訪問器實現(xiàn)的。
Vue 的依賴追蹤是【原理上不支持雙向綁定,v-model 只是通過監(jiān)聽 DOM 事件實現(xiàn)的語法糖】
vue的依賴追蹤是通過 Object.defineProperty 把data對象的屬性全部轉(zhuǎn)為 getter/setter來實現(xiàn)的;當(dāng)改變數(shù)據(jù)的某個屬性值時,會觸發(fā)set函數(shù),獲取該屬性值的時候會觸發(fā)get函數(shù),通過這個特性來實現(xiàn)改變數(shù)據(jù)時改變視圖;也就是說只有當(dāng)數(shù)據(jù)改變時才會觸發(fā)視圖的改變,反過來在操作視圖時,只能通過DOM事件來改變數(shù)據(jù),再由此來改變視圖,以此來實現(xiàn)雙向綁定
雙向綁定是在同一個組件內(nèi),將數(shù)據(jù)和視圖綁定起來,和父子組件之間的通信并無什么關(guān)聯(lián);
組件之間的通信采用單向數(shù)據(jù)流是為了組件間更好的解耦,在開發(fā)中可能有多個子組件依賴于父組件的某個數(shù)據(jù),假如子組件可以修改父組件數(shù)據(jù)的話,一個子組件變化會引發(fā)所有依賴這個數(shù)據(jù)的子組件發(fā)生變化,所以vue不推薦子組件修改父組件的數(shù)據(jù),直接修改props會拋出警告
這里推薦閱讀《Vue.js雙向綁定的實現(xiàn)原理》
react沒有數(shù)據(jù)雙向綁定
react是單向數(shù)據(jù)流:對應(yīng)任何可變數(shù)據(jù)理應(yīng)只有一個單一“數(shù)據(jù)源”,數(shù)據(jù)源狀態(tài)提升至父組件中
react中通過將state(Model層)與View層數(shù)據(jù)進(jìn)行雙向綁定達(dá)數(shù)據(jù)的實時更新變化,具體來說就是在View層直接寫JS代碼Model層中的數(shù)據(jù)拿過來渲染,一旦像表單操作、觸發(fā)事件、ajax請求等觸發(fā)數(shù)據(jù)變化,則進(jìn)行雙同步
angular也是雙向數(shù)據(jù)綁定(一次做完所有數(shù)據(jù)變更,然后整體應(yīng)用到界面上)
安利下:再談angularJS數(shù)據(jù)綁定機(jī)制及背后原理—angularJS常見問題總結(jié)
三者中,我還是更推崇react+redux模式(自上而下的數(shù)據(jù)流,業(yè)務(wù)聚焦于數(shù)據(jù)樹設(shè)計)
這里面不得不提的就是,vuejs對data中數(shù)組的原生方法進(jìn)行了封裝,所以在改變數(shù)組時能夠觸發(fā)視圖更新。這個我在寫日期控件對時候遇到很多坑,比如:
通過索引直接修改數(shù)組的元素,例如vm.items[0] = {title: 'title'}
無法直接修改數(shù)組的長度,例如vm.items.length = 0
解決方案: 對于第一種vue提供了set方法vm.items.set(0,{title: ‘title’}) 或vm.$set(‘items[0]’,{title: ‘title’})。另外一個列表渲染的時候的有一個性能的小技巧: 如果數(shù)組中本身自帶一個唯一的標(biāo)識 id ,那么在渲染的時候,通過trace-by給數(shù)組設(shè)定唯一的標(biāo)識,這樣vuejs在渲染過程中會盡量重復(fù)原有對象的作用域和dom元素。
關(guān)于用“箭頭函數(shù)精簡你的 Vue 模塊”(建議點擊閱讀),精簡出來就是:
methods: { method(){//todo} //不用: method:()=>{//todo} method:function(){//todo} }
參考文章:
Vue2.0 探索之路——生命周期和鉤子函數(shù)的一些理解
詳解vue生命周期
vue生命周期
vue生命周期探究
vue安裝,router-link的一些屬性,用法,tag active-class,to,replace,exex等等
Vuex下Store的模塊化拆分實踐
Vue.js與React的全面對比
Vue.js 2.0源碼解析之前端渲染篇
用箭頭函數(shù)精簡你的 Vue 模塊 – dotdev
轉(zhuǎn)載請注明來源,vue2.x入坑總結(jié)-回顧對比angularJS/React - vue入坑總結(jié) - 周陸軍的個人網(wǎng)站,:https://www.zhoulujun.cn/html/webfront/ECMAScript/vue/8125.html。不妥之處,望告之,謝謝!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
文章題目:vue2.x入坑總結(jié)—回顧對比angularJS/React-創(chuàng)新互聯(lián)
當(dāng)前鏈接:http://jinyejixie.com/article18/dijhgp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、動態(tài)網(wǎng)站、網(wǎng)站設(shè)計、虛擬主機(jī)、定制網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容