1.對(duì)MVC 闰蚕、MVVM、MVP的理解
答:
1. MVC
M?表示 Model , 專門用來處理數(shù)據(jù)模型。
V?表示View敦冬, 專注頁面布局和數(shù)據(jù)顯示。
C?表示Controller 專注于控制唯沮,執(zhí)行業(yè)務(wù)邏輯匪补,操作模型和視圖伞辛。
MVC的數(shù)據(jù)之間通信都是單向的
View(視圖層) 傳送指令到 Controller(控制層)
Controller(控制層) 完成業(yè)務(wù)邏輯后,要求 Model(模型層) 改變狀態(tài)
Model(模型層) 將新的數(shù)據(jù)發(fā)送到 View(視圖層)夯缺,用戶得到反饋
在MVC中蚤氏,雖然View與Model之間的耦合度非常小,只需要Model修改的時(shí)候通知View發(fā)生改變即可踊兜,但是它們之間還有有很重要的聯(lián)系竿滨,于是,就有了MVP
(2)MVP
M?表示 Model捏境,專門用來處理數(shù)據(jù)模型
V?表示View于游,專門用來處理用戶視圖
P?表示Presenter,用來處理業(yè)務(wù)邏輯垫言,在MVC的基礎(chǔ)上贰剥,修改了通信方向
MVP中,View和Model之間沒有任何通信關(guān)系筷频,所有的通信和業(yè)務(wù)邏輯都放在Presenter層中
View(視圖層) 發(fā)送指令到 Presenter層蚌成,
Presenter層 處理業(yè)務(wù)邏輯,要求 Model(模型層) 改變狀態(tài)
Model(模型層) 修改狀態(tài)之后凛捏,發(fā)送指令到 Presenter層
Presenter層通知View(視圖層)做出改變
在MVP中担忧,所有的通信都是雙向的,View和Model不會(huì)直接發(fā)生通信坯癣,都通過Presenter層進(jìn)行傳遞
在MVP中瓶盛,所有的業(yè)務(wù)邏輯都寫在Presenter層中,會(huì)導(dǎo)致Presenter層過于臃腫
在MVP中示罗,View只負(fù)責(zé)顯示視圖惩猫,不包含任何業(yè)務(wù)邏輯,導(dǎo)致View層過薄蚜点,不具備任何主動(dòng)性
由于在MVP模式中轧房,所有的業(yè)務(wù)邏輯都放在Presenter層中,必須通過Presenter層來修改View層的界面禽额,所以出現(xiàn)了MVVM
3.MVVM
M表示 Model锯厢,專門用來處理數(shù)據(jù)模型
V表示View,專門用來處理用戶視圖
VM表示ViewModel脯倒,用來使的View視圖層與Model層雙向綁定实辑,View的任何變動(dòng)都會(huì)通知ViewModel,而Model的任何變動(dòng)藻丢,也都會(huì)通知ViewModel剪撬,而不論哪一項(xiàng)發(fā)生改變,都會(huì)使對(duì)應(yīng)的視圖/數(shù)據(jù)模型同步發(fā)生改變
在MVVM中悠反,與MVP一樣残黑,所有的通信都是雙向的馍佑,數(shù)據(jù)與視圖不直接發(fā)生依賴,全部通過VM層來進(jìn)行雙向綁定
所有的業(yè)務(wù)邏輯都由VM來進(jìn)行處理梨水,但是在View層和Model層修改都會(huì)通過VM來雙向的綁定修改
2.詳述Vuex工作流程
答: 首先通過dispatch提交一個(gè)action
在action中我們可以執(zhí)行一些異步的操作拭荤,或者根據(jù)不同的情況分發(fā)不同的mutation
接著在action中調(diào)用commit,觸發(fā)一個(gè)mutation
所有修改state的操作疫诽,全部應(yīng)該放在mutation中來做
而state更新之后舅世,會(huì)調(diào)用Vue的底層方法,通知視圖進(jìn)行更新渲染
3.談?wù)剬?duì)對(duì)$nextTick的理解及使用場(chǎng)景
答:
如果要在created()鉤子函數(shù)中進(jìn)行的DOM操作奇徒,由于created()鉤子函數(shù)中還未對(duì)DOM進(jìn)行任何渲染雏亚,所以無法直接操作,需要通過$nextTick()來完成摩钙。在created()鉤子函數(shù)中進(jìn)行的DOM操作罢低,不使用$nextTick()會(huì)報(bào)錯(cuò)
更新數(shù)據(jù)后,想要使用js對(duì)新的視圖進(jìn)行操作時(shí)
在使用某些第三方插件時(shí) 胖笛,這些插件需要dom動(dòng)態(tài)變化后重新應(yīng)用該插件网持,這3時(shí)候就需要使用$nextTick()來重新應(yīng)用插件的方法
nextTick原理
1、異步說明
nextTick的使用場(chǎng)景
Vue 實(shí)現(xiàn)響應(yīng)式并不是數(shù)據(jù)發(fā)生變化之后 DOM 立即變化匀钧,而是按一定的策略進(jìn)行 DOM 的更新
2翎碑、事件循環(huán)說明
簡(jiǎn)單來說谬返,Vue 在修改數(shù)據(jù)后之斯,視圖不會(huì)立刻更新,而是等同一事件循環(huán)中的所有數(shù)據(jù)變化完成之后遣铝,再統(tǒng)一進(jìn)行視圖更新佑刷。
created、mounted
在 created 和 mounted 階段酿炸,如果需要操作渲染后的試圖瘫絮,也要使用 nextTick 方法。
注意 mounted 不會(huì)承諾所有的子組件也都一起被掛載填硕。如果你希望等到整個(gè)視圖都渲染完畢麦萤,可以用 vm.$nextTick 替換掉 mounted
mounted: function () {
? this.$nextTick(function () {
? ? // Code that will run only after the
? ? // entire view has been rendered
? })
}
以下使用nexttick的三種情況
(1)? 點(diǎn)擊按鈕顯示原本以 v-show = false 隱藏起來的輸入框,并獲取焦點(diǎn)扁眯。
showsou(){
? this.showit = true //修改 v-show
? document.getElementById("keywords").focus()? //在第一個(gè) tick 里壮莹,獲取不到輸入框,自然也獲取不到焦點(diǎn)
}
修改為:
showsou(){
? this.showit = true
? this.$nextTick(function () {
? ? // DOM 更新了
? ? document.getElementById("keywords").focus()
? })
}
(2.)點(diǎn)擊獲取元素寬度姻檀。
<div id="app">
? ? <p ref="myWidth" v-if="showMe">{{ message }}</p>
? ? <button @click="getMyWidth">獲取p元素寬度</button>
</div>
getMyWidth() {
? ? this.showMe = true;
? ? //this.message = this.$refs.myWidth.offsetWidth;
? ? //報(bào)錯(cuò) TypeError: this.$refs.myWidth is undefined
? ? this.$nextTick(()=>{
? ? ? ? //dom元素更新后執(zhí)行命满,此時(shí)能拿到p元素的屬性
? ? ? ? this.message = this.$refs.myWidth.offsetWidth;
? })
}
(3.)使用 swiper 插件通過 ajax 請(qǐng)求圖片后的滑動(dòng)問題。
應(yīng)用場(chǎng)景
需要在視圖更新之后绣版,基于新的視圖進(jìn)行操作
1胶台、如果要在created()鉤子函數(shù)中進(jìn)行的DOM操作歼疮,由于created()鉤子函數(shù)中還未對(duì)DOM進(jìn)行任何渲染,所以無法直接操作诈唬,需要通過$nextTick()來完成韩脏。
created(){
? ? this.$nextTick(()=>{
? ? ? ? this.$refs.myP.innerText = "我是一只小小小小鳥,想要飛铸磅,卻怎么樣也飛不高骤素!";
? ? });
}
注:在created()鉤子函數(shù)中進(jìn)行的DOM操作,不使用$nextTick()會(huì)報(bào)錯(cuò):
//? Error in created hook: "TypeError: Cannot set property 'innerText' of undefined"
created(){
? ? this.$refs.myP.innerText = "我是一只小小小小鳥愚屁,想要飛济竹,卻怎么樣也飛不高!";
}
2霎槐、更新數(shù)據(jù)后送浊,想要使用js對(duì)新的視圖進(jìn)行操作時(shí)。
3丘跌、在使用某些第三方插件時(shí) 袭景,這些插件需要dom動(dòng)態(tài)變化后重新應(yīng)用該插件,這時(shí)候就需要使用$nextTick()來重新應(yīng)用插件的方法闭树。
4.漸進(jìn)式框架的理解
答:對(duì)于漸進(jìn)式框架來說耸棒,主要就代表著它的主張性最小,沒有多做職責(zé)之外的事报辱。
什么是主張性与殃?
在你使用一個(gè)框架的時(shí)候,如果你使用了它的一部分碍现,你就必須使用它的全部幅疼,或是很大一部分東西,這個(gè)就叫強(qiáng)主張
而說Vue的主張性最小昼接,是因?yàn)槟憧梢灾皇褂盟囊徊糠謻|西爽篷,它可以很容易的集成到你原有的項(xiàng)目中去,甚至說你只是用它來改造一下一些公共的組件慢睡,你可以在傳統(tǒng)的html頁面中使用它逐工,也可以使用腳手架工具來搭建一個(gè)大型的項(xiàng)目
在學(xué)習(xí)方面,Vue的學(xué)習(xí)代價(jià)也不是很大漂辐,你可以非常容易的上手泪喊,我們沒有必要一上來就搞明白Vue的所有功能,可以先從核心功能擴(kuò)展者吁,然后在逐步學(xué)習(xí)窘俺,當(dāng)你需要的時(shí)候,你再去使用它的其他功能,并且你可以非常容易的使用Vue結(jié)合其他的框架來進(jìn)行搭配
5.組件樣式屬性 scoped 問題及解決方法
答:在Vue組件中瘤泪,為了使樣式私有化(模塊化)灶泵,不對(duì)全局造成污染,可以在style標(biāo)簽上添加scoped屬性以表示它的只屬于當(dāng)下的模塊对途,局部有效赦邻。
Vue中的scoped屬性的效果主要通過PostCSS轉(zhuǎn)譯實(shí)現(xiàn),給所有的樣式動(dòng)態(tài)的生成一個(gè)屬性实檀,然后通過在編譯后使用屬性選擇器加原有選擇器的方式來設(shè)置樣式傅蹂,這樣就不會(huì)對(duì)其它組件造成影響帘靡,當(dāng)前組件的樣式只對(duì)當(dāng)前組件生效
然而,我們?cè)谑褂胹coped的時(shí)候,經(jīng)常會(huì)遇到樣式問題限嫌,比如說
要在父組件中修改子組件的布局樣式等
要修改v-html渲染出的內(nèi)容的樣式時(shí)
使用一些UI框架時(shí)肯污,修改樣式的問題
對(duì)于這些問題的解決方案:
1.同時(shí)使用scoped局部樣式和全局樣式
<style>
/*全局樣式*/
</style>
<style scoped>
/*局部樣式*/
</style>
2. 子組件的根節(jié)點(diǎn)元素會(huì)同時(shí)被設(shè)置了scoped的父css樣式和設(shè)置了scoped的子css樣式影響碍遍,這么設(shè)計(jì)的目的是父組件可以對(duì)子組件根元素進(jìn)行布局噪叙。
3. 使用深選擇器豺旬,>>>或者/deep/進(jìn)行樣式穿透
在Vue中,可以使用>>>或者/deep/來進(jìn)行樣式穿透篓跛,達(dá)到修改樣式的功能
在sass或者less這種預(yù)編譯器中坦刀,不支持>>>求泰,可以使用/deep/
<style scoped>
.el-form? >>>? .el-input {
? ? // 修改樣式
}
.el-form? /deep/? .el-input {
? ? // 修改樣式
}
</style>
建議使用第三種方法计盒,這樣既不會(huì)對(duì)全局樣式造成污染北启,也可以達(dá)到修改樣式的功能