1况凉、vue是一套漸進式框架的理解
- 在我看來,漸進式代表的含義是:主張最少各拷。
- 每個框架都不可避免會有自己的一些特點刁绒,從而會對使用者有一定的要求,這些要求就是主張烤黍,主張有強有弱知市,它的強勢程度會影響在業(yè)務開發(fā)中的使用方式。
- 比如說速蕊,Angular嫂丙,它兩個版本都是強主張的,如果你用它规哲,必須接受以下東西:
必須使用它的模塊機制- 必須使用它的依賴注入- 必須使用它的特殊形式定義組件(這一點每個視圖框架都有跟啤,難以避免)
所以Angular是帶有比較強的排它性的,如果你的應用不是從頭開始唉锌,而是要不斷考慮是否跟其他東西集成隅肥,這些主張會帶來一些困擾。 - 比如React袄简,它也有一定程度的主張腥放,它的主張主要是函數(shù)式編程的理念,比如說绿语,你需要知道什么是副作用秃症,什么是純函數(shù),如何隔離副作用吕粹。它的侵入性看似沒有Angular那么強伍纫,主要因為它是軟性侵入。
- Vue可能有些方面是不如React昂芜,不如Angular莹规,但它是漸進的,沒有強主張泌神,你可以在原有大系統(tǒng)的上面良漱,把一兩個組件改用它實現(xiàn)舞虱,當jQuery用;也可以整個用它全家桶開發(fā)母市,當Angular用矾兜;還可以用它的視圖,搭配你自己設計的整個下層用患久。你可以在底層數(shù)據(jù)邏輯的地方用OO和設計模式的那套理念椅寺,也可以函數(shù)式,都可以蒋失,它只是個輕量視圖而已返帕,只做了自己該做的事,沒有做不該做的事篙挽,僅此而已荆萤。
漸進式的含義,我的理解是:沒有多做職責之外的事铣卡。
2链韭、Vue常用的指令
3、v-if VS v-show區(qū)別
4煮落、Vue常用修飾符
5敞峭、v-on可以監(jiān)聽多個方法嗎
可以,代碼如下:
<input type="text" :value="name" @input="onInput" @focus="onFocus" @blur="onBlur" />
6蝉仇、vue中key值的作用
- 需要使用key來給每個節(jié)點做一個唯一標識儡陨,Diff算法就可以正確的識別此節(jié)點兢卵,找到正確的位置區(qū)插入新的節(jié)點瑟蜈。
- 其實不只是vue逸邦,react中在執(zhí)行列表渲染時也會要求給每個組件添加上key這個屬性。
要解釋key的作用呀枢,不得不先介紹一下虛擬DOM的Diff算法了。
vue和react的虛擬DOM的Diff算法大致相同笼痛。
虛擬DOM見“68題” 裙秋,diff算法見“69題”
7、$nextTick的作用
8缨伊、Vue組件中的data為什么必須是函數(shù)
當我們定義一個 組件時( <button-counter>)摘刑,你可能會發(fā)現(xiàn)它的 data 并不是像這樣直接提供一個對象:
data: {
count: 0
}
取而代之的是,一個組件的 data 選項必須是一個函數(shù)刻坊,因此每個實例可以維護一份被返回對象的獨立的拷貝:
data: function () {
return {
count: 0
}
}
9枷恕、v-for和v-if的優(yōu)先級
當它們處于同一節(jié)點,v-for 的優(yōu)先級比 v-if 更高谭胚,這意味著 v-if 將分別重復運行于每個 v-for 循環(huán)中徐块。當你想為僅有的一些項渲染節(jié)點時未玻,這種優(yōu)先級的機制會十分有用。
10胡控、詳述組件通信
11扳剿、keep-alive組件的作用
當在這些組件之間切換的時候,你有時會想保持這些組件的狀態(tài)昼激,以避免反復重渲染導致的性能問題庇绽。例如我們來展開說一說這個多標簽界面:
你會注意到,如果你選擇了一篇文章橙困,切換到 Archive 標簽瞧掺,然后再切換回 Posts,是不會繼續(xù)展示你之前選擇的文章的纷宇。這是因為你每次切換新標簽的時候夸盟,Vue 都創(chuàng)建了一個新的 currentTabComponent 實例。
重新創(chuàng)建動態(tài)組件的行為通常是非常有用的像捶,但是在這個案例中上陕,我們更希望那些標簽的組件實例能夠被在它們第一次被創(chuàng)建的時候緩存下來。為了解決這個問題拓春,我們可以用一個 <keep-alive> 元素將其動態(tài)組件包裹起來释簿。
<!-- 失活的組件將會被緩存!-->
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
現(xiàn)在這個 Posts 標簽保持了它的狀態(tài) (被選中的文章) 甚至當它未被渲染時也是如此
12硼莽、Vue生命周期詳解
- 什么是Vue的生命周期
Vue實例有一個完整的生命周期庶溶,也就是說從開始創(chuàng)建、初始化數(shù)據(jù)懂鸵、編譯模板偏螺、掛載DOM、渲染-更新-渲染匆光、卸載等一系列過程套像,我們稱為Vue實例的生命周期。鉤子就是在某個階段給你一個做某些處理的機會终息。 - 生命周期的作用
就是在某個階段給你一個做某些處理的機會夺巩。 - 生命周期總共有幾個階段
beforeCreate(創(chuàng)建前):在實例初始化之后,數(shù)據(jù)觀測和事件配置之前被調(diào)用周崭,此時組件的選項對象還未創(chuàng)建柳譬,因此無法訪問methods,data续镇,computed等上的方法和數(shù)據(jù)美澳。
created(創(chuàng)建后):實例已經(jīng)創(chuàng)建完成之后被調(diào)用,在這一步,實例已完成了以下配置:數(shù)據(jù)觀測人柿、屬性和方法的運算柴墩,watch/event事件回調(diào)。然而凫岖,掛載階段還沒有開始江咳,$el屬性目前不可見。created鉤子可以獲取Vue的data哥放,調(diào)用Vue方法歼指,獲取原本HTML上的直接加載出來的DOM,但是無法獲取到通過掛載模板生成的DOM甥雕。這是一個常用的生命周期踩身,因為你可以調(diào)用methods中的方法、改變data中的數(shù)據(jù)社露,并且修改可以通過vue的響應式綁定體現(xiàn)在頁面上挟阻、獲取computed中的計算屬性等等。通常我們可以在這里對實例進行預處理峭弟。也有一些童鞋喜歡在這里發(fā)ajax請求附鸽,值得注意的是,這個周期中是沒有什么方法來對實例化過程進行攔截的瞒瘸。因此假如有某些數(shù)據(jù)必須獲取才允許進入頁面的話坷备,并不適合在這個頁面發(fā)請求。
建議在組件路由勾子beforeRouteEnter中來完成情臭。
beforeMonut:掛載開始之前被調(diào)用:虛擬dom已經(jīng)創(chuàng)建完成省撑,馬上就要渲染,在這里也可以更改數(shù)據(jù)俯在,相關的 render 函數(shù)首次被調(diào)用(虛擬DOM)竟秫,實例已完成以下的配置:編譯模板,把data里面的數(shù)據(jù)和模板生成html跷乐。注意此時還沒有掛載html到頁面上肥败。
mounted[?ma?nt?d]:掛載完成,也就是模板中的HTML渲染到了HTML頁面中劈猿,此時一般可以做一些ajax操作,組件已經(jīng)出現(xiàn)在頁面中潮孽,數(shù)據(jù)揪荣、真實dom都已經(jīng)處理好了,事件都已經(jīng)掛載好了mounted只會執(zhí)行一次往史。
beforeUpdate(更新前):在數(shù)據(jù)更新之前調(diào)用仗颈,發(fā)生在虛擬DOM重新渲染和打補丁之前。可以在該鉤子中進一步地更改狀態(tài)挨决,不會觸發(fā)附加的重渲染過程请祖。然后vue的虛擬dom機制會重新構建虛擬dom與上一次的虛擬dom樹利用diff算法進行對比之后重新渲染。
updated[?p'de?t?d](更新后):在由于數(shù)據(jù)更改導致的虛擬DOM重新渲染和打補丁之后調(diào)用脖祈。調(diào)用時肆捕,組件DOM已經(jīng)更新,所以可以執(zhí)行依賴于DOM的操作盖高。然而在大多數(shù)情況下慎陵,應該避免在此期間更改狀態(tài),因為這可能會導致更新無限循環(huán)喻奥。該鉤子在服務器端渲染期間不被調(diào)用席纽。
beforeDestroy[d??str??](銷毀前):在實例銷毀之前調(diào)用。實例仍然完全可用撞蚕。1.這一步還可以用this來獲取實例润梯。2.一般在這一步做一些重置的操作。比如清除掉組件中的 定時器 和 監(jiān)聽的dom事件甥厦。
destroyed[d?s'tr??d](銷毀后):在實例銷毀之后調(diào)用纺铭。調(diào)用后,所有的事件監(jiān)聽器會被移除矫渔,所有的子實例也會被銷毀彤蔽。該鉤子在服務器端渲染期間不被調(diào)用。 - 第一次頁面加載會觸發(fā)哪幾個鉤子
beforeCreate - DOM 渲染在哪個周期中就已經(jīng)完成
mounted - 生命周期使用場景舉例
beforeCreate:可以在這里加一個loading
created:loading結束做一些初始化操作
mounted:ajax請求庙洼,配合路由鉤子做一些事情
beforeDestory:你確認刪除嗎顿痪?
destoryed:當前組件已被刪除,清空相關內(nèi)容
13油够、Vue如何監(jiān)聽鍵盤事件中的按鍵
14蚁袭、Vue中的過濾器有什么用?
Vue.js 允許你自定義過濾器石咬,可被用于一些常見的文本格式化揩悄。過濾器可以用在兩個地方:雙花括號插值和 v-bind 表達式。過濾器應該被添加在 JavaScript 表達式的尾部鬼悠,由“管道”符號指示
15删性、單頁面應用和多頁面應用區(qū)別及優(yōu)缺點
單頁面應用(SPA),通俗一點說就是指只有一個主頁面的應用焕窝,瀏覽器一開始要加載所有必須的 html, js, css蹬挺。所有的頁面內(nèi)容都包含在這個所謂的主頁面中。但在寫的時候它掂,還是會分開寫(頁面片段)巴帮,然后在交互的時候由路由程序動態(tài)載入,單頁面的頁面跳轉(zhuǎn),僅刷新局部資源榕茧。多應用于pc端垃沦。
多頁面(MPA),就是指一個應用中有多個頁面用押,頁面跳轉(zhuǎn)時是整頁刷新
- 單頁面的優(yōu)點:
- 用戶體驗好肢簿,快,內(nèi)容的改變不需要重新加載整個頁面只恨,基于這一點spa對服務器壓力較小
- 前后端分離
- 頁面效果會比較炫酷(比如切換頁面內(nèi)容時的專場動畫)
- 單頁面缺點:
- 不利于seo
- 導航不可用译仗,如果一定要導航需要自行實現(xiàn)前進、后退官觅。(由于是單頁面不能用瀏覽器的前進后退功能纵菌,所以需要自己建立堆棧管理)
- 初次加載時耗時多
- 頁面復雜度提高很多
姓名 | 單頁面應用(SinglePage Web Application,SPA) | 多頁面應用(MultiPage Application休涤,MPA) |
---|---|---|
組成 | 一個外殼頁面和多個頁面片段組成 | 多個完整頁面構成 |
資源共用(css,js) | 共用咱圆,只需在外殼部分加載 | 不共用,每個頁面都需要加載 |
刷新方式 | 頁面局部刷新或更改 | 整頁刷新 |
url 模式 | a.com/#/pageone | a.com/pageone.html |
用戶體驗 | 頁面片段間的切換快功氨,用戶體驗良好 | 頁面切換加載緩慢序苏,流暢度不夠,用戶體驗比較差 |
轉(zhuǎn)場動畫 | 容易實現(xiàn) | 無法實現(xiàn) |
數(shù)據(jù)傳遞 | 容易 | 依賴 url傳參捷凄、或者cookie 忱详、localStorage等 |
搜索引擎優(yōu)化(SEO) | 需要單獨方案、實現(xiàn)較為困難跺涤、不利于SEO檢索 可利用服務器端渲染(SSR)優(yōu)化 | 實現(xiàn)方法簡易 |
試用范圍 | 高要求的體驗度匈睁、追求界面流暢的應用 | 適用于追求高度支持搜索引擎的應用 |
開發(fā)成本 | 較高,常需借助專業(yè)的框架 | 較低 桶错,但頁面重復代碼多 |
維護成本 | 相對容易 | 相對復雜 |
16航唆、什么是計算屬性?什么情況使用院刁?
模板內(nèi)的表達式非常便利糯钙,但是設計它們的初衷是用于簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護退腥,例如:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
在這個地方任岸,模板不再是簡單的聲明式邏輯。你必須看一段時間才能意識到狡刘,這里是想要顯示變量 message 的翻轉(zhuǎn)字符串享潜。當你想要在模板中多次引用此處的翻轉(zhuǎn)字符串時,就會更加難以處理颓帝。
所以米碰,對于任何復雜邏輯,你都應當使用計算屬性购城。
17吕座、vue-cli提供了幾種腳手架模板
六種
https://github.com/vuejs/vue-cli/tree/v2#vue-cli--
18、computed瘪板、methods的區(qū)別
兩種方式的最終結果確實是完全相同的吴趴。然而,不同的是計算屬性是基于它們的依賴進行緩存的侮攀。只在相關依賴發(fā)生改變時它們才會重新求值锣枝。這就意味著只要值還沒有發(fā)生改變,多次訪問 定義的計算屬性會立即返回之前的計算結果兰英,而不必再次執(zhí)行函數(shù)撇叁。
相比之下,每當觸發(fā)重新渲染時畦贸,調(diào)用方法(methods)將總會再次執(zhí)行函數(shù)陨闹。
我們?yōu)槭裁葱枰彺妫考僭O我們有一個性能開銷比較大的計算屬性 A薄坏,它需要遍歷一個巨大的數(shù)組并做大量的計算趋厉。然后我們可能有其他的計算屬性依賴于 A 。如果沒有緩存胶坠,我們將不可避免的多次執(zhí)行 A 的 getter君账!如果你不希望有緩存,請用方法來替代沈善。
19乡数、什么是自定義指令,有哪些鉤子函數(shù)及自定義指令的使用場景
有的情況下矮瘟,你仍然需要對普通 DOM 元素進行底層操作瞳脓,這時候就會用到自定義指令。
一個指令定義對象可以提供如下幾個鉤子函數(shù) (均為可選):
bind:只調(diào)用一次澈侠,指令第一次綁定到元素時調(diào)用劫侧。在這里可以進行一次性的初始化設置。
inserted:被綁定元素插入父節(jié)點時調(diào)用 (僅保證父節(jié)點存在哨啃,但不一定已被插入文檔中)烧栋。
update:所在組件的 VNode 更新時調(diào)用,但是可能發(fā)生在其子 VNode 更新之前拳球。指令的值可能發(fā)生了改變审姓,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新 (詳細的鉤子函數(shù)參數(shù)見下)祝峻。
componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用魔吐。
unbind:只調(diào)用一次扎筒,指令與元素解綁時調(diào)用。
20酬姆、父組件獲取異步動態(tài)數(shù)據(jù)傳遞給子組件
在父組件中使用axios獲取異步數(shù)據(jù)傳給子組件嗜桌,但是發(fā)現(xiàn)子組件在渲染的時候并沒有數(shù)據(jù),在created里面打印也是空的辞色,結果發(fā)現(xiàn)一開始子組件綁定的數(shù)據(jù)是空的骨宠,在請求數(shù)據(jù)沒有返回數(shù)據(jù)時,子組件就已經(jīng)加載了相满,并且他綁定的值也是空的层亿,問題找到了,怎么解決呢立美?
- 開始的時候讓子組件隱藏,然后等數(shù)據(jù)返回的時候匿又,讓子組件顯示
通過v-if,也就是判斷數(shù)據(jù)是否為空建蹄,為空就不渲染琳省,也能解決了 - 為不能讀取的屬性添加一個默認值,就可以很好的解決了
21躲撰、vue-router導航解析流程
22针贬、vue-router實現(xiàn)原理
這里指的路由并不是指我們平時所說的硬件路由器,這里的路由就是SPA(單頁應用)的路徑管理器拢蛋。 換句話說桦他,vue-router就是WebApp的鏈接路徑管理系統(tǒng)。
vue-router是Vue.js官方的路由插件谆棱,它和vue.js是深度集成的快压,適合用于構建單頁面應用。
那與傳統(tǒng)的頁面跳轉(zhuǎn)有什么區(qū)別呢垃瞧?
1.vue的單頁面應用是基于路由和組件的蔫劣,路由用于設定訪問路徑,并將路徑和組件映射起來个从。
2.傳統(tǒng)的頁面應用脉幢,是用一些超鏈接來實現(xiàn)頁面切換和跳轉(zhuǎn)的。
在vue-router單頁面應用中嗦锐,則是路徑之間的切換嫌松,也就是組件的切換。路由模塊的本質(zhì) 就是建立起url和頁面之間的映射關系奕污。
至于為啥不能用a標簽萎羔,這是因為用Vue做的都是單頁應用,就相當于只有一個主的index.html頁面碳默,所以你寫的標簽是不起作用的贾陷,必須使用vue-router來進行管理缘眶。
SPA(single page application):單一頁面應用程序,有且只有一個完整的頁面髓废;當它在加載頁面的時候磅崭,不會加載整個頁面的內(nèi)容,而只更新某個指定的容器中內(nèi)容瓦哎。
單頁面應用(SPA)的核心之一是:
- 更新視圖而不重新請求頁面;
- vue-router在實現(xiàn)單頁面前端路由時,提供了三種方式:Hash模式柔逼、History模式蒋譬、abstract模式,根據(jù)mode參數(shù)來決定采用哪一種方式愉适。
路由模式
vue-router 提供了三種運行模式:
● hash: 使用 URL hash 值來作路由犯助。默認模式。
● history: 依賴 HTML5 History API 和服務器配置维咸。查看 HTML5 History 模式剂买。
● abstract: 支持所有 JavaScript 運行環(huán)境,如 Node.js 服務器端癌蓖。
Hash模式
vue-router 默認模式是 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL瞬哼,當 URL 改變時,頁面不會去重新加載租副。
hash(#)是URL 的錨點坐慰,代表的是網(wǎng)頁中的一個位置,單單改變#后的部分(/#/..)用僧,瀏覽器只會加載相應位置的內(nèi)容,不會重新加載網(wǎng)頁,也就是說 #是用來指導瀏覽器動作的俱饿,對服務器端完全無用琉兜,HTTP請求中不包括#;同時每一次改變#后的部分院仿,都會在瀏覽器的訪問歷史中增加一個記錄秸抚,使用”后退”按鈕,就可以回到上一個位置歹垫;所以說Hash模式通過錨點值的改變耸别,根據(jù)不同的值,渲染指定DOM位置的不同數(shù)據(jù)县钥。
JavaScript實現(xiàn)SPA路由hash模式詳解
History模式
HTML5 History API提供了一種功能秀姐,能讓開發(fā)人員在不刷新整個頁面的情況下修改站點的URL,就是利用 history.pushState API 來完成 URL 跳轉(zhuǎn)而無須重新加載頁面若贮;
由于hash模式會在url中自帶#省有,如果不想要很丑的 hash痒留,我們可以用路由的 history 模式,只需要在配置路由規(guī)則時蠢沿,加入"mode: 'history'",這種模式充分利用 history.pushState API 來完成 URL 跳轉(zhuǎn)而無須重新加載頁面伸头。
//main.js文件中
const router = new VueRouter({
mode: 'history',
routes: [...]
})
當使用 history 模式時,URL 就像正常的 url舷蟀,例如 yoursite.com/user/id恤磷,比較好… 不過這種模式有點問題,還需要后臺配置支持野宜。你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源扫步,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面匈子,如果不這么做河胎,直接訪問頁面空白
配置Apache
第一步:新建:.htaccess文件放在服務器根目錄下 (命令type null>.htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
除了 mod_rewrite,你也可以使用 FallbackResource虎敦。
第二步: src/router/index.js
mode: 'history',
base: '/dist/',
第三步:訪問:地址進行測試
abstract模式
abstract模式是使用一個不依賴于瀏覽器的瀏覽歷史虛擬管理后端游岳。
根據(jù)平臺差異可以看出,在 Weex 環(huán)境中只支持使用 abstract 模式其徙。 不過胚迫,vue-router 自身會對環(huán)境做校驗,如果發(fā)現(xiàn)沒有瀏覽器的 API唾那,vue-router 會自動強制進入 abstract 模式晌区,所以 在使用 vue-router 時只要不寫 mode 配置即可,默認會在瀏覽器環(huán)境中使用 hash 模式通贞,在移動端原生環(huán)境中使用 abstract 模式朗若。 (當然,你也可以明確指定在所有情況下都使用 abstract 模式)
23昌罩、vue-router有哪幾種導航鉤子
24哭懈、vue-router參數(shù)傳遞方法詳述及區(qū)別
25、如何定義嵌套路由
26茎用、router-link是什么及其常用屬性配置
27遣总、如何實現(xiàn)路由懶加載有什么好處
28、vue-router共有幾種模式轨功,有什么區(qū)別旭斥?
29、什么是Vuex及使用場景
30古涧、vuex的常用屬性有哪幾個垂券,分別是做什么的
31、簡述vuex更新數(shù)據(jù)流程或機制
用戶在組件中發(fā)起動作羡滑,然后從API中拿數(shù)據(jù)菇爪,就會牽扯到異步操作算芯,所以我們通過dispatch來提交一個action,在action里面發(fā)起ajax請求凳宙,拿到數(shù)據(jù)以后我們只需要通過commit提交mutations改變我的state狀態(tài)就可以了熙揍,狀態(tài)改變后視圖就會改變因為Vuex是響應式的,這就是Vuex的運作流程機制
32氏涩、vuex中如何異步修改數(shù)據(jù)
Action 類似于 mutation届囚,不同在于:
Action 提交的是 mutation,而不是直接變更狀態(tài)是尖。
Action 可以包含任意異步操作意系。
33、axios析砸、fetch和ajax有什么區(qū)別?
34爆袍、axios有哪些特點
35首繁、組件樣式中的scoped有什么用
36、vue中常用的UI組件庫有哪些陨囊?
37弦疮、如何優(yōu)化首屏加載速度
-
路由懶加載
vue項目作為一個單頁面應用,如果不對路由進行處理蜘醋,在加載首頁的時候胁塞,就會將所有組件全部加載,并向服務器請求數(shù)據(jù)压语,這必將拖慢加載速度啸罢;當打包構建應用時,Javascript 包會變得非常大胎食,影響頁面加載扰才。如果我們能把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應組件厕怜,這樣就更加高效了衩匣。
圖片資源的壓縮
嚴格說來這一步不算在編碼技術范圍內(nèi),但是卻對頁面的加載速度影響很大粥航,特別是對于移動端的項目來說琅捏。
對于非logo的圖片文件,讓UI設計師提供jpg格式的递雀,不要用png
對于所有的圖片文件柄延,都可以在一個叫tinypng的網(wǎng)站上去壓縮一下或采用webpack插件進行壓縮-
使用cdn
在Vue項目中,引入到工程中的所有js缀程、css文件拦焚,編譯時都會被打包進vendor.js蜡坊,瀏覽器在加載該文件之后才能開始顯示首屏。若是引入的庫眾多赎败,那么vendor.js文件體積將會相當?shù)拇箫跹茫绊懯组_的體驗。
解決方法是僵刮,將引用的外部js据忘、css文件剝離開來,不編譯到vendor.js中搞糕,而是用資源的形式引用勇吊,這樣瀏覽器可以使用多個線程異步將vendor.js、外部的js等加載下來窍仰,達到加速首開的目的汉规。
外部的庫文件,可以使用CDN資源驹吮,或者別的服務器資源等针史。
下面,以引入vue碟狞、vuex啄枕、vue-router為例,說明處理流程族沃。
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
externals:{
'vue':'Vue',
'vue-router':'VueRouter',
'vuex':'Vuex'
},
// 格式為'aaa':'bbb'频祝,其中,aaa表示要引入的資源的名字脆淹,bbb表示該模塊提供給外部引用的名字常空,由對應的庫自定。例如盖溺,vue為Vue窟绷,vue-router為VueRouter
去掉原有的引用直接使用就可以了,否則還是會打包
具體步驟為
1咐柜、引入
在bulid/webpack.base.conf.js文件中兼蜈,增加externals,將引用的外部模塊導入拙友,如下:
module.exports = {
entry: {
app: './src/main.js'
},
externals:{
'vue': 'Vue',
'vue-router': 'VueRouter',
'vuex':'Vuex'
}
2为狸、在index.html中引入cdn。推薦引入 百度靜態(tài)資源庫的
地址為:https://www.bootcdn.cn/
<body>
<div id="app"></div>
<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
</body>
注意一點:
格式為 'aaa' : 'bbb', 其中遗契,aaa表示要引入的資源的名字辐棒,bbb表示該模塊提供給外部引用的名字,由對應的庫自定。例如漾根,vue為Vue泰涂,vue-router為VueRouter.
3、去掉原有的引用
main.js中
// import Vue from 'vue'
// import Router from 'vue-router'
去掉Vue.use(XXX)辐怕,如:
// Vue.use(Router)
4逼蒙、重新npm run build,會看到 vendor.js體積有所下降了
通過開發(fā)者模式的Network工具寄疏,可以看到vue.js是牢、vuex.js、vendor.js等文件會分別由一個線程進行加載陕截。且因為使用了CDN驳棱,減輕了帶寬壓力。
-
前流行的UI框架如iview,muse-ui,Element UI都支持按需加載,
-
gzip壓縮
38农曲、打包命令是什么社搅?
39、打包后會生成哪些文件乳规?
40形葬、如何配置打包后生成的文件路徑錯誤問題
41、簡述MVVM驯妄、MVP荷并、MVC模式及區(qū)別
- MVVM
MVVM 是 Model-View-ViewModel 的縮寫合砂。
Model代表數(shù)據(jù)模型青扔,也可以在Model中定義數(shù)據(jù)修改和操作的業(yè)務邏輯。
View 代表UI 組件翩伪,它負責將數(shù)據(jù)模型轉(zhuǎn)化成UI 展現(xiàn)出來微猖。
ViewModel 監(jiān)聽模型數(shù)據(jù)的改變和控制視圖行為、處理用戶交互缘屹,簡單理解就是一個同步View 和 Model的對象凛剥,連接Model和View。
在MVVM架構下轻姿,View 和 Model 之間并沒有直接的聯(lián)系犁珠,而是通過ViewModel進行交互,Model 和 ViewModel 之間的交互是雙向的互亮, 因此View 數(shù)據(jù)的變化會同步到Model中犁享,而Model 數(shù)據(jù)的變化也會立即反應到View 上。
ViewModel 通過雙向數(shù)據(jù)綁定把 View 層和 Model 層連接了起來豹休,而View 和 Model 之間的同步工作完全是自動的炊昆,無需人為干涉,因此開發(fā)者只需關注業(yè)務邏輯,不需要手動操作DOM, 不需要關注數(shù)據(jù)狀態(tài)的同步問題凤巨,復雜的數(shù)據(jù)狀態(tài)維護完全由 MVVM 來統(tǒng)一管理视乐。
42、MVVM模式的理解
- MVVM 由 Model敢茁、View佑淀、ViewModel 三部分構成,Model 層代表數(shù)據(jù)模型卷要,也可以在Model中定義數(shù)據(jù)修改和操作的業(yè)務邏輯渣聚;View 代表UI 組件,它負責將數(shù)據(jù)模型轉(zhuǎn)化成UI 展現(xiàn)出來僧叉,ViewModel 是一個同步View 和 Model的對象奕枝。
- 在MVVM架構下,View 和 Model 之間并沒有直接的聯(lián)系瓶堕,而是通過ViewModel進行交互隘道,Model 和 ViewModel 之間的交互是雙向的, 因此View 數(shù)據(jù)的變化會同步到Model中郎笆,而Model 數(shù)據(jù)的變化也會立即反應到View 上谭梗。
- ViewModel 通過雙向數(shù)據(jù)綁定把 View 層和 Model 層連接了起來,而View 和 Model 之間的同步工作完全是自動的宛蚓,無需人為干涉激捏,因此開發(fā)者只需關注業(yè)務邏輯,不需要手動操作DOM凄吏, 不需要關注數(shù)據(jù)狀態(tài)的同步問題远舅,復雜的數(shù)據(jù)狀態(tài)維護完全由 MVVM 來統(tǒng)一管理。
43痕钢、Vue中的雙向數(shù)據(jù)綁定是如何實現(xiàn)的
分成兩個進程图柏,一個進程是對掛載目標元素模板里的v-model和{{ }}這兩個指令進行編譯(綠色)。另一個進程是對傳進去的data對象里面的數(shù)據(jù)進行監(jiān)聽(紅色)任连。
紅色:
- 當你把一個普通的 JavaScript 對象傳給 Vue 實例的
data
選項蚤吹,Vue 將遍歷此對象所有的屬性,并使用 Object.defineProperty 把這些屬性全部加上set和get訪問器随抠,這樣在設置data的屬性值的時候裁着,會觸發(fā)set方法,那么set方法主要有兩個作用拱她,一是改變data里面的屬性值二驰,二是發(fā)出數(shù)據(jù)變化的通知。Observer作為數(shù)據(jù)的觀察者椭懊,讓數(shù)據(jù)對象的讀寫操作都處于自己的監(jiān)管之下诸蚕,Dep作為Watcher(訂閱器)的收集者步势,當數(shù)據(jù)發(fā)生變化set會發(fā)出通知,會被Observer觀察到背犯,然后由Dep通知到Watcher坏瘩,最后更新視圖。
綠色:
指令解析器Compile漠魏,對每個節(jié)點元素進行掃描和解析倔矾,將相關指令對應初始化成一個訂閱者Watcher,同樣由Dep進行收集柱锹,然后由Dep通知到Watcher哪自,最后更新視圖。
節(jié)點介紹
數(shù)據(jù)監(jiān)聽器觀察者Observer禁熏,能夠?qū)?shù)據(jù)對象的所有屬性進行監(jiān)聽壤巷,讓數(shù)據(jù)對象的讀寫操作都處于自己的監(jiān)管之下,當數(shù)據(jù)發(fā)生變化set會發(fā)出通知瞧毙,會被Observer觀察到胧华,然后由Dep通知到Watcher,最后更新視圖宙彪。
實現(xiàn)數(shù)據(jù)的雙向綁定矩动,首先要對數(shù)據(jù)進行劫持監(jiān)聽,所以我們需要設置一個監(jiān)聽器Observer释漆,用來監(jiān)聽所有屬性Watcher將數(shù)據(jù)監(jiān)聽器和指令解析器連接起來悲没,數(shù)據(jù)的屬性變動時,執(zhí)行指令綁定的相應回調(diào)函數(shù)男图,
1.如果屬性發(fā)上變化了示姿,就需要告訴訂閱者Watcher看是否需要更新。指令解析器Compile享言,
對每個節(jié)點元素進行掃描和解析峻凫,將相關指令對應初始化成一個訂閱者WatcherDep:因為訂閱者是有很多個渗鬼,所以我們需要有一個消息訂閱器Dep來專門收集這些訂閱者览露,然后在監(jiān)聽器Observer和訂閱者Watcher之間進行統(tǒng)一管理的
43、Object.defineProperty()方法做什么用
44譬胎、vue-cli中常用的配置
45差牛、簡述vue內(nèi)部運作機制
46、vuex內(nèi)部運作機制
47堰乔、axios內(nèi)部運作機制
48偏化、vue-router內(nèi)部運作機制
49、在vue-cli中怎么使用scss
50镐侯、vue和jquery有什么區(qū)別侦讨?
51、vue的雙向數(shù)據(jù)綁定原理是什么?
52韵卤、你是怎么理解組件化開發(fā)的
53骗污、簡述vue-cli每個目錄的作用
54、為什么選擇vue沈条?和其它框架對比的優(yōu)劣勢在哪需忿?
55、route和router的區(qū)別
56蜡歹、vue兩個核心點是什么屋厘?
數(shù)據(jù)驅(qū)動、組件系統(tǒng)
57月而、用Vuex和不用vuex有什么區(qū)別汗洒?
58、第一次頁面加載會觸發(fā)哪幾個鉤子
59父款、v-model是什么仲翎?
60、vue中的數(shù)組和原生js中的數(shù)組有什么區(qū)別铛漓?
61溯香、簡述$set及使用場景
62、ajax應該放在組件中還是視圖中或是vuex中
63浓恶、你覺得什么樣的項目比較適合用vue框架
64玫坛、列舉vue中觸發(fā)視圖更新的方法
65、Vue不能檢測數(shù)組或?qū)ο笞儎訂栴}的解決方法有哪些
66包晰、vue-router湿镀,history模式下打包后訪問空白
67、打包后訪問某個視圖伐憾,刷新404問題
68勉痴、詳述虛擬DOM
第一種:
1、state數(shù)據(jù)
2树肃、JSX模板
3蒸矛、 數(shù)據(jù) + 模板 結合,生成真實的DOM -> 視圖
4胸嘴、state發(fā)生了變化
5雏掠、數(shù)據(jù) + 模板 結合,生成真實的DOM劣像,替換原始的DOM
缺陷:
1乡话、第一次生成了完整的DOM片段
2、第二次生成了完整的DOM片段
3耳奕、第二次的DOM替換第一次的DOM绑青,非常耗費性能
第二種:
1诬像、state數(shù)據(jù)
2、JSX模板
3闸婴、數(shù)據(jù) + 模板 結合颅停, 生成真實的DOM -> 視圖
4、state發(fā)生變化
5掠拳、數(shù)據(jù) + 模板 結合癞揉,生成真實的DOM,并不直接替換原始的DOM
6溺欧、新的DOM(DocumentFragment)和原始的DOM做比對喊熟,找差異
7、找出input框發(fā)生了變化
8姐刁、只用新的DOM中的input元素芥牌,替換掉老的DOM中input元素
缺陷:
雖然DOM只是局部替換,但是在比對時候的計算是比較耗費性能的聂使,因此壁拉,性能的提升并不明顯
第三種:
1、state數(shù)據(jù)
2柏靶、JSX模板
3弃理、數(shù)據(jù) + 模板 生成虛擬DOM(虛擬DOM就是一個JS對象,用它來描述真實DOM)(損耗一點性能)
虛擬DOM:['div', {id: 'abc'}, ['span', '', 'hello world']]
4屎蜓、用虛擬DOM的結構生成真實的DOM -> 視圖顯示
真實DOM:<div id='abc'><span></span></div>
5痘昌、state發(fā)生了變化
6、數(shù)據(jù) + 模板 生成新的虛擬DOM:['div', {id: 'abc'}, ['span', '', 'hi world']](極大提升性能)
7、比較原始虛擬DOM和新的虛擬DOM的區(qū)別,找到的區(qū)別是span中的內(nèi)容發(fā)生了變化(極大提升了性能)
8潮瓶、直接操作DOM,改變span中的內(nèi)容
總結:
減少了真實DOM的創(chuàng)建及對比弹惦,創(chuàng)建都是JS對象,對比的也都是JS的對象,在JS底層實現(xiàn)了極大的性能飛越
組件生成流程:
JSX -> JS對象(虛擬DOM) -> 真實的DOM
用React.createElement改寫JSX模板:
JSX:return <div><span>{ item }</span></div>
JSX -> JS對象(虛擬DOM) -> 真實的DOM
React.createElement('div', {}, React.createElement('span', {}, 'item'))
JSX -> createElement -> JS對象(虛擬DOM) -> 真實的DOM
虛擬DOM優(yōu)點:
1、性能提升了
2骑冗、它使得跨端應用得以實現(xiàn),Ract Native
React可以寫原生應用了捍靠,得益于React中的虛擬DOM沐旨,如果沒有虛擬DOM是不能寫原生應用的森逮。原生系統(tǒng)是不支持DOM不存在DOm這個概念的榨婆,但是支持虛擬DOM(虛擬DOM就是一個JS對象);虛擬DOM可以在瀏覽器端被解析為真實的DOM褒侧,在原生端可以被解析原生所支持的組件等格式
69良风、詳述虛擬DOM中的diff算法
虛擬DOM對比時谊迄,會用到diff算法
虛擬DOM什么時候會被比對?
當數(shù)據(jù)發(fā)生變化的時候就會被比對
那什么時候數(shù)據(jù)會發(fā)生改變呢烟央?
要么改變了state统诺,要么改變了props(props的改變其實是他的父組件的state發(fā)生了改變)
setState方法,其實是異步的疑俭,為什么是異步的粮呢?實際為了提升React底層的性能,假設:調(diào)用三次setState變更三組數(shù)據(jù)钞艇,大家想頁面會怎么做或者說React會怎么做啄寡?我們想的是React可能會做三次比對更新三次視圖。又假設三次更新間隔非常小哩照,這樣會耗費性能挺物,React可以把三次合并為一次,只去做一次虛擬DOM的比對飘弧,然后更新一次視圖识藤,這樣的話就可以省去兩次比對性能上的耗費。
同層比對次伶,如果一致痴昧,那么繼續(xù)比對第二層,如果比對一樣了冠王,繼續(xù)往下比對剪个。
如果比對到不一樣了,React會這么做版确,它不會再繼續(xù)往下比對了,而是從不一樣的這一層開始直接用新的覆蓋掉就得DOM節(jié)點扣囊,這樣的話豈不是性能并未得到最大提升?這樣的話會造成重復節(jié)點的浪費绒疗,侵歇。那這樣比對會有什么好處呢?同層比對帶來的好處就是比對的算法特別簡單吓蘑,雖然可能會造成DOM上的重新渲染的浪費惕虑,但是大大的減少了虛擬DOM之間比對的算法上的性能消耗,所以React中采用了同層比對的算法磨镶。
遍歷時候key的問題:
假如:數(shù)組中有五條數(shù)據(jù)溃蔫,渲染到頁面,然后生成五個虛擬DOM樹琳猫,接下來我往里面增加了一條數(shù)據(jù)于是數(shù)據(jù)發(fā)生變化會生成一個新的虛擬DOM樹伟叛,然后我們會做兩個虛擬DOM的比對也就是上下進行比對匹配關系,如果每一個虛擬DOM的節(jié)點沒有一個key值脐嫂,它就沒有一個自己的名字统刮,當我們在做兩個虛擬DOM樹的比對的時候節(jié)點和節(jié)點之間的關系就很難被確立紊遵,我們得做兩層循環(huán)的比較,這樣的話比較起來就很麻煩了侥蒙,當然也是很耗費性能的暗膜。
我們可以這樣優(yōu)化,假如我們在做DOM節(jié)點的循環(huán)的時候鞭衩,我們可以給每個節(jié)點起個名字学搜,A、B论衍、C恒水、D、E在第二次循環(huán)的時候我們有六個饲齐,以前的ABCDE還存在還是叫做ABCDE钉凌,我又增加了一個節(jié)點Z進來這個時候比對就很簡單了,我們根據(jù)他們的名字進行比對捂人,馬上就能知道ABCDE都一致御雕,可以繼續(xù)復用,只有Z不同滥搭,我們快速的建立關聯(lián)后把Z增加到這個DOM樹上就可以了酸纲。所以極大的提升了虛擬DOM比對的性能。
如果提升性能有個前提我們盡量不要用下標瑟匆,因為大家看按照下標的話右圖ABCDE闽坡,下面新的DOM樹ABCDE和上面的其實不再是對應的關系了,對導致key值不穩(wěn)定愁溜,key值是變化的疾嗅,失去了存在的意義了。那用什么比較合適呢冕象?唯一不變化的代承、穩(wěn)定的值。