在線訪問(wèn)手冊(cè):
https://hanxueqing.github.io/Web-Front-end-Interview-Q-A/
github地址:
https://github.com/Hanxueqing/Web-Front-end-Interview-Q-A
前端構(gòu)建集成工具(打包)
什么是前端集成解決方案矛紫?
FIS(Front-end Integrated Solution)是專(zhuān)為解決前端開(kāi)發(fā)中自動(dòng)化工具苦囱、性能優(yōu)化像吻、模塊化框架婴渡、開(kāi)發(fā)規(guī)范昨寞、代碼部署践付、開(kāi)發(fā)流程等問(wèn)題的工具框架悄蕾。
前端集成解決方案解決了前端哪些問(wèn)題拣凹?
- 開(kāi)發(fā)團(tuán)隊(duì)代碼風(fēng)格不統(tǒng)一问词,如何強(qiáng)制開(kāi)發(fā)規(guī)范督函。
- 前期開(kāi)發(fā)的組件庫(kù)如何維護(hù)和使用
- 如何模塊化前端項(xiàng)目
- 服務(wù)器部署前必須壓縮,檢查流程如何簡(jiǎn)化激挪,流程如何完善。
你使用過(guò)哪些前端構(gòu)建集成垄分?你用過(guò)什么打包工具宛篇?
- Gulp
gulp是工具鏈、構(gòu)建工具薄湿,可以配合各種插件做js壓縮叫倍,css壓縮,less編譯豺瘤,替代手工實(shí)現(xiàn)自動(dòng)化工作
(1)構(gòu)建工具
(2)自動(dòng)化
(3)提高效率用
- webpack
webpack是文件打包工具吆倦,可以把項(xiàng)目的各種js文、css文件等打包合并成一個(gè)或多個(gè)文件坐求,主要用于模塊化方案蚕泽,預(yù)編譯模塊的方案
(1)打包工具
(2)模塊化識(shí)別
(3)編譯模塊代碼方案用
webpack打包
一款模塊化打包工具,webpack是基于配置的桥嗤,通過(guò)配置一些選項(xiàng)來(lái)讓webpack執(zhí)行打包任務(wù)
webpack在打包的時(shí)候须妻,依靠依賴關(guān)系圖派任,在打包的時(shí)候要告知webpack兩個(gè)概念:入口和出口
plugins:在webpack編譯用的是loader,但是有一些loader無(wú)法完成的任務(wù)璧南,交由插件(plugin)來(lái)完成掌逛,插件的時(shí)候需要在配置項(xiàng)中配置plugins選項(xiàng),值是數(shù)組司倚,可以放入多個(gè)插件使用豆混,而一般的插件都是一個(gè)構(gòu)造器,我們动知,我們只需在plugins數(shù)組中放入該插件的實(shí)例即可皿伺。
loader:在webpack中專(zhuān)門(mén)有一些東西用來(lái)編譯文件、處理文件盒粮,這些東西就叫l(wèi)oader鸵鸥。
webpack都用過(guò)哪些loader?
url-loader 可以將css中引入的圖片(背景圖)丹皱、js中生成的img圖片處理一下妒穴,生成到打包目錄里
url-loader/file-loader 將圖片轉(zhuǎn)成base64
html-withimg-loader 可以將html中img標(biāo)簽引入的img圖片打包到打包目錄
css-loader 可以將引入到j(luò)s中的css代碼給抽離出來(lái)
style-loader 可以將抽離出來(lái)的css代碼放入到style標(biāo)簽中
sass-loader/less-loader sass/less預(yù)編譯
postcss-loader 兼容前綴
babel-loader 將es6轉(zhuǎn)成es5轉(zhuǎn)成大部分瀏覽器可以識(shí)別的語(yǔ)法
vue-loader 把vue組件轉(zhuǎn)換成js模塊
為何要轉(zhuǎn)譯此模塊?
可以動(dòng)態(tài)的渲染一些數(shù)據(jù),對(duì)三個(gè)標(biāo)簽做了優(yōu)化
<template> 寫(xiě)虛擬dom
<script> 寫(xiě)es6語(yǔ)法
<style> 默認(rèn)可以用scss語(yǔ)法摊崭,提供了作用域
并且開(kāi)發(fā)階段提供了熱加載功能
注意:webpack中l(wèi)oader的使用是從后往前的
webpack都用過(guò)哪些plugins讼油?
html-webpack-plugin:這個(gè)插件可以選擇是否依據(jù)模板來(lái)生成一個(gè)打包好的html文件,在里面可以配置呢簸、title矮台、template、filename根时、minify等選項(xiàng)瘦赫。
optimize-css-assets-webpack-plugin:壓縮css插件
extract-text-webpack-plugin:樣式合并
webpack.optimize.UglifyJsPlugin:js合并
webpack入口屬性
entry 入口文件
output出口文件
Gulp打包
gulp:基于流的前端自動(dòng)化構(gòu)建工具,基于流的任務(wù)式工具.pipe()
gulp的特點(diǎn):自動(dòng)化 基于流 插件很多
Gulp 的特點(diǎn):
* 自動(dòng)化 - Gulp 為你的工作流而服務(wù)蛤迎,自動(dòng)運(yùn)行那些費(fèi)事費(fèi)力任務(wù)确虱。
* 平臺(tái)透明 - Gulp 被集成到各種 IDE 中,并且除了 NodeJS 之外忘苛,其他如 PHP蝉娜、.NET、Java 平臺(tái)都可以使用 Gulp扎唾。
* 強(qiáng)大生態(tài)系統(tǒng) - 你可以使用 npm 上 2000+ 的插件來(lái)構(gòu)造你的工作流召川。
* 簡(jiǎn)單 - Gulp 只提供幾個(gè) API程帕,這可以很快地學(xué)習(xí)和上手掖桦。
Gulp 原生API
在進(jìn)階Gulp時(shí),必須熟悉API中的四個(gè)方法的使用擅憔,在這里簡(jiǎn)單概括一下,更多信息查閱API倍阐。
-
gulp.src(globs[, options])
返回符合匹配規(guī)則的虛擬文件對(duì)象流(Vinyl files)概疆。
-
gulp.dest(path[, options])
用來(lái)指定要生成的文件的目錄,目錄路徑為path峰搪。
-
gulp.task(name[, deps], fn)
定義一個(gè)流任務(wù)岔冀,任務(wù)名為name。
-
gulp.watch(glob[, opts], tasks)
監(jiān)視文件的變化概耻,執(zhí)行操作使套。
Gulp插件
gulp-scss 編譯css文件(注意:windows下使用 gulp-sass)
gulp-connect 來(lái)啟動(dòng)一個(gè)服務(wù)器
gulp-concat 合并js文件
gulp-uglify js文件壓縮
gulp-rename重命名
gulp-minify-css 壓縮css
gulp-babel 將es6代碼轉(zhuǎn)成es5
webpack和gulp有什么區(qū)別
-
gulp是基于流的構(gòu)建工具:all in one的打包模式,輸出一個(gè)js文件和一個(gè)css文件鞠柄,優(yōu)點(diǎn)是減少http請(qǐng)求侦高,萬(wàn)金油方案。gulp強(qiáng)調(diào)的是前端開(kāi)發(fā)的工作流程厌杜,我們可以通過(guò)配置一系列的task奉呛,定義task處理的事務(wù)(例如文件壓縮合并、雪碧圖夯尽、啟動(dòng)server瞧壮、版本控制等),然后定義執(zhí)行順序呐萌,來(lái)讓gulp執(zhí)行這些task馁痴,從而構(gòu)建項(xiàng)目的整個(gè)前端開(kāi)發(fā)流程。
PS:簡(jiǎn)單說(shuō)就一個(gè)Task Runner肺孤。
-
webpack是模塊化管理工具:all in js,使用webpack可以對(duì)模塊進(jìn)行壓縮济欢、預(yù)處理赠堵、打包、按需加載等法褥。webpack是一個(gè)前端模塊化方案茫叭,更側(cè)重模塊打包,我們可以把開(kāi)發(fā)中的所有資源(圖片半等、js文件揍愁、css文件等)都看成模塊,通過(guò)loader(加載器)和plugins(插件)對(duì)資源進(jìn)行處理杀饵,打包成符合生產(chǎn)環(huán)境部署的前端資源莽囤。
PS:webpack is a module bundle
雖然都是前端自動(dòng)化構(gòu)建工具,但看他們的定位就知道不是對(duì)等的切距。
gulp嚴(yán)格上講朽缎,模塊化不是他強(qiáng)調(diào)的東西,他旨在規(guī)范前端開(kāi)發(fā)流程。
webpack更是明顯強(qiáng)調(diào)模塊化開(kāi)發(fā)话肖,而那些文件壓縮合并北秽、預(yù)處理等功能,不過(guò)是他附帶的功能最筒。
webpack和gulp有什么關(guān)系
Gulp和webpack在定義和用法上來(lái)說(shuō)都不沖突贺氓,可以結(jié)合來(lái)使用。
gulp應(yīng)該與grunt比較床蜘,而webpack應(yīng)該與browserify(網(wǎng)上太多資料就這么說(shuō)辙培,這么說(shuō)是沒(méi)有錯(cuò),不過(guò)單單這樣一句話并不能讓人清晰明了)悄泥。
gulp與webpack上是互補(bǔ)的虏冻,還是可替換的,取決于你項(xiàng)目的需求弹囚。如果只是個(gè)vue或react的單頁(yè)應(yīng)用厨相,webpack也就夠用;如果webpack某些功能使用起來(lái)麻煩甚至沒(méi)有(雪碧圖就沒(méi)有)鸥鹉,那就可以結(jié)合gulp一起用蛮穿。
Gulp應(yīng)該和Grunt比較
Gulp / Grunt 是一種工具,能夠優(yōu)化前端工作流程毁渗。比如自動(dòng)刷新頁(yè)面践磅、combo、壓縮css灸异、js府适、編譯less等等。簡(jiǎn)單來(lái)說(shuō)肺樟,就是使用Gulp/Grunt檐春,然后配置你需要的插件,就可以把以前需要手工做的事情讓它幫你做了么伯。
devDependencies和dependencies的區(qū)別
區(qū)別是:
dependencies 程序正常運(yùn)行需要的包疟暖。
devDependencies 是開(kāi)發(fā)需要的包,比如 一些單元測(cè)試的包之類(lèi)的田柔。
一個(gè)node package有兩種依賴俐巴,一種是dependencies一種是devDependencies,
其中前者依賴的項(xiàng)該是正常運(yùn)行該包時(shí)所需要的依賴項(xiàng)硬爆,
而后者則是開(kāi)發(fā)的時(shí)候需要的依賴項(xiàng)欣舵,像一些進(jìn)行單元測(cè)試之類(lèi)的包。
如果將包下載下來(lái)在包的根目錄里運(yùn)行npm install默認(rèn)會(huì)安裝兩種依賴摆屯,如果只是單純的使用這個(gè)包而不需要進(jìn)行一些改動(dòng)測(cè)試之類(lèi)的邻遏,可以使用npm install --production糠亩,只安裝dependencies而不安裝devDependencies。
如果是通過(guò)以下命令進(jìn)行安裝npm install packagename那么只會(huì)安裝准验。dependencies赎线,如果想要安裝devDependencies,需要輸入糊饱。npm install packagename --dev垂寥。
參考文章:
gulp與webpack的區(qū)別
https://www.cnblogs.com/lovesong/p/6413546.html
前端集成解決方案(webpack、gulp)
https://blog.csdn.net/qishuixian/article/details/79453343
CSS預(yù)處理器
什么是CSS預(yù)處理器另锋?
CSS 預(yù)處理器定義了一種新的語(yǔ)言滞项,其基本思想是,用一種專(zhuān)門(mén)的編程語(yǔ)言夭坪,為 CSS 增加了一些編程的特性文判,將 CSS 作為目標(biāo)生成文件,然后開(kāi)發(fā)者就只要使用這種語(yǔ)言進(jìn)行編碼工作室梅。
通俗的說(shuō)戏仓,“CSS 預(yù)處理器用一種專(zhuān)門(mén)的編程語(yǔ)言,進(jìn)行 Web 頁(yè)面樣式設(shè)計(jì)亡鼠,然后再編譯成正常的 CSS 文件赏殃,以供項(xiàng)目使用。CSS 預(yù)處理器為 CSS 增加一些編程的特性间涵,無(wú)需考慮瀏覽器的兼容性問(wèn)題”仁热,例如你可以在 CSS 中使用變量、簡(jiǎn)單的邏輯程序勾哩、函數(shù)(如右側(cè)代碼編輯器中就使用了變量$color)等等在編程語(yǔ)言中的一些基本特性抗蠢,可以讓你的 CSS 更加簡(jiǎn)潔、適應(yīng)性更強(qiáng)思劳、可讀性更佳物蝙,更易于代碼的維護(hù)等諸多好處。
都有哪些常用的CSS預(yù)處理器敢艰?
SCSS专肪、LESS因妙、Stylus
Sass預(yù)編譯的特性
它使用自己語(yǔ)法并編譯為可讀的CSS
可以在更少的時(shí)間內(nèi)輕松的編寫(xiě)CSS代碼
是一個(gè)開(kāi)源的預(yù)處理器,被解析為CSS
可以兼容所有的CSS版本
為什么要用sass?
它是預(yù)處理語(yǔ)言,它為CSS提供縮進(jìn)語(yǔ)法(它自己的語(yǔ)法)
它允許更有效的編寫(xiě)代碼和易于維護(hù)
它使用可重復(fù)使用的方法,邏輯語(yǔ)句和一些內(nèi)置的函數(shù)
它提供了比平面CSS好的結(jié)構(gòu)格式和文檔樣式
Sass和Scss有什么區(qū)別?
Sass 和 SCSS 其實(shí)是同一種東西徽诲,我們平時(shí)都稱之為 Sass森瘪,兩者之間不同之處有以下兩點(diǎn):
文件擴(kuò)展名不同牡属,Sass 是以“.sass后綴為擴(kuò)展名,而 SCSS 是以“.scss”后綴為擴(kuò)展名扼睬;
語(yǔ)法書(shū)寫(xiě)方式不同逮栅,Sass 是以嚴(yán)格的縮進(jìn)式語(yǔ)法規(guī)則來(lái)書(shū)寫(xiě)悴势,不帶大括號(hào)({})和分號(hào)(;),而 SCSS 的語(yǔ)法書(shū)寫(xiě)和我們的 CSS 語(yǔ)法書(shū)寫(xiě)方式非常類(lèi)似措伐。
Sass語(yǔ)法
(1)聲明變量
普通變量:$美元符號(hào)+變量名稱:變量值特纤,定義之后可以在全局范圍內(nèi)使用
默認(rèn)變量:sass 的默認(rèn)變量?jī)H需要在值后面加上*!default 即可。sass 的默認(rèn)變量一般是用來(lái)設(shè)置默認(rèn)值侥加,然后根據(jù)需求來(lái)覆蓋的捧存,覆蓋的方式也很簡(jiǎn)單,只需要重新聲明下變量即可
特殊變量:一般情況下担败,我們定義的變量都是屬性值昔穴,可以直接使用,但是如果變量作為屬性或者其他的特殊情況下提前,必須使用#{$variable}的形式進(jìn)行調(diào)用吗货。
#{$variable} 就是取值的一種特殊形式,符合特殊用法狈网。
全局變量:全局變量——在變量的后面加上[!global]即可聲明全局變量宙搬。
(2)sass嵌套-選擇器嵌套
SASS 中的嵌套主要說(shuō)的是選擇器嵌套和屬性嵌套兩種方式,正常項(xiàng)目中通常使用的都是選擇器嵌套方案
【注】在嵌套的過(guò)程中孙援,如果需要用到父元素害淤,在 SASS 中通過(guò)&符號(hào)引用父屬性
(3)sass嵌套-屬性嵌套
嵌套屬性——不常用
所謂屬性嵌套,是指某些屬性擁有同樣的單詞開(kāi)頭拓售,如:border-left,border-color
都是以 border 開(kāi)頭的窥摄,所以就出現(xiàn)了屬性嵌套語(yǔ)法
(4)sass混合-Mixin
sass 中可以通過(guò)@mixin 聲明混合,可以傳遞參數(shù)础淤,參數(shù)名稱以$開(kāi)始崭放,多個(gè)參數(shù)之間使用
逗號(hào)分隔,@mixin 的混合代碼塊由@include 來(lái)調(diào)用
混合能使我們重用一整段sass代碼鸽凶,同時(shí)也可以給其傳遞參數(shù)币砂。
定義一個(gè)混合,需用到@mixin關(guān)鍵字玻侥,后面跟自己定義的名字决摧,若需要傳參,則在名字之后加一對(duì)單括號(hào)()凑兰,同時(shí)在里面定義參數(shù)變量掌桩。通過(guò)調(diào)用@include關(guān)鍵字,來(lái)調(diào)用這段混合姑食。
(5)sass繼承拓展-@extend
在 SASS 中波岛,通過(guò)繼承/擴(kuò)展來(lái)減少重復(fù)代碼,可以讓一個(gè)選擇器去繼承另一個(gè)選擇中所有
的樣式音半。
繼承某個(gè)樣式的同時(shí)则拷,也會(huì)繼承樣式的擴(kuò)展贡蓖。
(6)Partitials和@import
Partials 是用來(lái)定義公共樣式或者組件的樣式的,專(zhuān)門(mén)用于被其他的 scss 文件 import進(jìn)行使用的煌茬,在 SCSS 文件中引入指令@import 在引入 Partials 文件時(shí)斥铺,不需要添加下劃線。詳細(xì)參考案例代碼宣旱。
(7)sass注釋
SASS 中提供了三種注釋
多行注釋 在編譯輸出的 css 文件中會(huì)保留仅父,壓縮輸出格式中不會(huì)保留 --style compressed
/*
* 多行注釋
*/
單行注釋 在輸出 css 文件時(shí)不保留
? // 單行注釋
強(qiáng)制注釋 在多行注釋的開(kāi)頭,添加感嘆號(hào)浑吟!表示強(qiáng)制保留
/*!
* 強(qiáng)制注釋
*/
混合樣式笙纤,怎么調(diào)用,調(diào)用需不需要攜帶參數(shù)
無(wú)參數(shù)混合
版本控制工具
SVN優(yōu)缺點(diǎn)(集中式版本管理控制工具)
優(yōu)點(diǎn):
1组力、 管理方便省容,邏輯明確,符合一般人思維習(xí)慣燎字。
2腥椒、 易于管理,集中式服務(wù)器更能保證安全性候衍。
3笼蛛、 代碼一致性非常高。
4蛉鹿、 適合開(kāi)發(fā)人數(shù)不多的項(xiàng)目開(kāi)發(fā)滨砍。
缺點(diǎn):
1、 服務(wù)器壓力太大妖异,數(shù)據(jù)庫(kù)容量暴增惋戏。
2、 如果不能連接到服務(wù)器上他膳,基本上不可以工作响逢,看上面第二步,如果服務(wù)器不能連接上棕孙,就不能提交舔亭,還原,對(duì)比等等蟀俊。
3分歇、 不適合開(kāi)源開(kāi)發(fā)(開(kāi)發(fā)人數(shù)非常非常多,但是Google app engine就是用svn的)欧漱。但是一般集中式管理的有非常明確的權(quán)限管理機(jī)制(例如分支訪問(wèn)限制),可以實(shí)現(xiàn)分層管理葬燎,從而很好的解決開(kāi)發(fā)人數(shù)眾多的問(wèn)題误甚。
Git優(yōu)缺點(diǎn)(分布式版本管理控制工具)
優(yōu)點(diǎn):
1缚甩、適合分布式開(kāi)發(fā),強(qiáng)調(diào)個(gè)體窑邦。
2擅威、公共服務(wù)器壓力和數(shù)據(jù)量都不會(huì)太大。
3冈钦、速度快郊丛、靈活。
4瞧筛、任意兩個(gè)開(kāi)發(fā)者之間可以很容易的解決沖突厉熟。
5、可以離線工作较幌。
缺點(diǎn):
1揍瑟、學(xué)習(xí)周期相對(duì)而言比較長(zhǎng)。
2乍炉、不符合常規(guī)思維绢片。
3、代碼保密性差岛琼,一旦開(kāi)發(fā)者把整個(gè)庫(kù)克隆下來(lái)就可以完全公開(kāi)所有代碼和版本信息底循。
GIT常用命令
git add * /文件名 將想要快照的內(nèi)容寫(xiě)入緩存區(qū)
git commit -m "當(dāng)前提交的日志"
git push -u origin master 提交代碼
git status 查看當(dāng)前工作區(qū)提交狀態(tài)
git diff 比對(duì) 暫存區(qū)和工作區(qū)版本的區(qū)別
git checkout 切換分支命令
git reset --hard 版本號(hào) 恢復(fù)到指定的版本
GIT解決沖突
Git在push時(shí)如果版本比服務(wù)器上的舊,會(huì)提示先進(jìn)行pull槐瑞。問(wèn)題是pull時(shí)如果服務(wù)器上的版本與你本地的版本在源文件修改上有沖突熙涤,那么在解決沖突前push都會(huì)失敗。用git status可以查看沖突文件随珠。
接下來(lái)用git diff指令查看具體哪里起沖突
這里還有一些其他指令灭袁,在沖突規(guī)模比較大的時(shí)候可以很方便的確認(rèn)哪里不對(duì)殿遂。
git diff --ours:看本體分支對(duì)源文件的改動(dòng)
git diff --theirs:看服務(wù)器分支對(duì)源文件的改動(dòng)
git diff --base:看雙方對(duì)源文件的改動(dòng)阵漏,base和不加base的區(qū)別就是base選項(xiàng)會(huì)現(xiàn)實(shí)雙方改動(dòng)中即使不沖突的部分顷扩,默認(rèn)diff則只會(huì)顯示沖突部分孵运。
參考:
Git 沖突的解決方法
http://www.reibang.com/p/9382a0e3402a
git沖突解決的方法
https://www.cnblogs.com/nicknailo/p/9044238.html
GIT和SVN的區(qū)別
最核心的區(qū)別Git是分布式的怎爵,而Svn不是分布的
Git把內(nèi)容按元數(shù)據(jù)方式存儲(chǔ)锹杈,而SVN是按文件
Git的內(nèi)容的完整性要優(yōu)于SVN: GIT的內(nèi)容存儲(chǔ)使用的是SHA-1哈希算法闯割。這能確保代碼內(nèi)容的完整性曙咽,確保在遇到磁盤(pán)故障和網(wǎng)絡(luò)問(wèn)題時(shí)降低對(duì)版本庫(kù)的破壞拉讯。
SVN的特點(diǎn)是簡(jiǎn)單涤浇,只是需要一個(gè)放代碼的地方時(shí)用是OK的。
Git的特點(diǎn)版本控制可以不依賴網(wǎng)絡(luò)做任何事情魔慷,對(duì)分支和合并有更好的支持(當(dāng)然這是開(kāi)發(fā)者最關(guān)心的地方)只锭,不過(guò)想各位能更好使用它,需要花點(diǎn)時(shí)間嘗試下
SVN和Git對(duì)比結(jié)果
git是分布式的scm,svn是集中式的院尔。(最核心)
git是每個(gè)歷史版本都存儲(chǔ)完整的文件,便于恢復(fù),svn是存儲(chǔ)差異文件,歷史版本不可恢復(fù)蜻展。(核心)
git可離線完成大部分操作,svn則不能喉誊。
git有著更優(yōu)雅的分支和合并實(shí)現(xiàn)。
git有著更強(qiáng)的撤銷(xiāo)修改和修改歷史版本的能力
git速度更快,效率更高纵顾。
基于以上區(qū)別,git有了很明顯的優(yōu)勢(shì),特別在于它具有的本地倉(cāng)庫(kù)伍茄。
JQuery
JQuery中獲取網(wǎng)頁(yè)元素的方法
//$的數(shù)據(jù)類(lèi)型是一個(gè)函數(shù)
//alert(typeof $); //function
//$("#div1").css("background-color","red"); //id是div1
//$(".box").css("background-color","blue"); //classname是box
//$("ul .box").css("background-color","blue");//ul下的classname為box
//$("div").css("background-color","green");//div標(biāo)簽
//$("[name=hello]").css("background-color","orange");//name為hello
//$("div[id=div1]").css("background-color","orange");
JQuery中的工具方法
? type() 輸出當(dāng)前常量/變量的數(shù)據(jù)類(lèi)型
? trim() 刪除字符串的首尾空格
? inArray() 查找某一個(gè)元素,在數(shù)組中的下標(biāo)
? proxy() 功能類(lèi)似bind,預(yù)設(shè)this
? noConflict() 給$起一個(gè)別名
? parseJSON() 功能類(lèi)似JSON.parse()
? $.makeArray() 將偽數(shù)組轉(zhuǎn)成數(shù)組施逾。
JQuery插件方法
$.extend() 拓展工具方法
$.fn.extend() 拓展JQ的方法
設(shè)計(jì)思想:高內(nèi)聚低耦合
談一下Jquery中的bind敷矫、live、delegate汉额、on的區(qū)別曹仗?
on()方法-1.9版本整合了之前的三種方式的新事件綁定機(jī)制
.on( events [, selector ] [, data ], handler(eventObject) )
- 使用.bind()方法是很浪費(fèi)資源的,因?yàn)樗ヅ溥x擇器中的每一項(xiàng)并且挨個(gè)設(shè)置相同的事件處理程序
- 建議停止使用.live()方法闷愤,因?yàn)樗呀?jīng)被棄用了整葡,由于他有很多的問(wèn)題
- .delegate()方法“很劃算”用來(lái)處理性能和響應(yīng)動(dòng)態(tài)添加元素的時(shí)候
- 新的.on()方法主要是可以實(shí)現(xiàn).bind() .live() 甚至 .delegate()的功能
- 建議使用.on()方法,如果你的項(xiàng)目使用了1.7+的jQuery的話
參考:jQuery方法區(qū)別:click() bind() live() delegate()區(qū)別
https://www.cnblogs.com/zagelover/articles/2840762.html
關(guān)于jquery的事件委托-bind讥脐,live遭居,delegate,on的區(qū)別
https://blog.csdn.net/qq_42164670/article/details/83450066
拖拽的三劍客
mousedown:記錄被拖拽物體和鼠標(biāo)按下位置相對(duì)距離
mousemove:讓拖拽物體跟隨鼠標(biāo)去走旬渠,保持按下相對(duì)距離
mouseup:結(jié)束拖拽
Window.onload與$(document).ready(function(){})的區(qū)別是什么俱萍?
Window.onload:頁(yè)面中只會(huì)出現(xiàn)一次,頁(yè)面中所有元素都必須加載完畢才會(huì)去執(zhí)行 告丢。 $(document).ready()是JQ中的枪蘑,可以執(zhí)行多次 并且可以簡(jiǎn)寫(xiě)為:
$(function(){})
,不需要等頁(yè)面中所有元素加載岖免,只需要dom掛載進(jìn)來(lái)就可以執(zhí)行回調(diào)函數(shù)岳颇。
1、執(zhí)行時(shí)間上的區(qū)別:window.onload必須等到頁(yè)面內(nèi)(包括圖片的)所有元素加載到瀏覽器中后才能執(zhí)行颅湘。而$(document).ready(function(){})是DOM結(jié)構(gòu)加載完畢后就會(huì)執(zhí)行话侧。
2、編寫(xiě)個(gè)數(shù)不同:window.onload不能同時(shí)寫(xiě)多個(gè)闯参,如果有多個(gè)window.onload瞻鹏,則只有最后一個(gè)會(huì)執(zhí)行,它會(huì)把前面的都覆蓋掉鹿寨。$(document).ready(function(){})則不同新博,它可以編寫(xiě)多個(gè),并且每一個(gè)都會(huì)執(zhí)行脚草。
3赫悄、簡(jiǎn)寫(xiě)方法:window.onload沒(méi)有簡(jiǎn)寫(xiě)的方法,$(document).ready(function(){})可以簡(jiǎn)寫(xiě)為$(function(){})。
另外:由于在$(document).ready()方法內(nèi)注冊(cè)的事件涩蜘,只要DOM就緒就會(huì)被執(zhí)行嚼贡,因此可能此時(shí)元素的關(guān)聯(lián)文件未下載完,例如與圖片有關(guān)的HTML下載完畢同诫,并且已經(jīng)解析為DOM樹(shù)了,但很有可能圖片還未加載完畢樟澜,所以例如圖片的高度和寬度這樣的屬性此時(shí)不一定有效误窖。
要解決這個(gè)問(wèn)題,可以使用JQuery中另一個(gè)關(guān)于頁(yè)面加載的方法---load()方法秩贰。load()方法會(huì)在元素的onload事件中綁定一個(gè)處理函數(shù)霹俺。如果處理函數(shù)綁定在元素上,則會(huì)在元素的內(nèi)容加載完畢后觸發(fā)毒费。如:$(window).load(function(){})=====window.onload = function(){}
Jquery中如何將數(shù)組轉(zhuǎn)化為json字符串丙唧,然后再轉(zhuǎn)化回來(lái)?
var arr = [{usernname:"張三",age:10}]
console.log($.parseJSON(JSON.stringify(arr)));
正則表達(dá)式
電話號(hào)碼
function checkPhone(){
var phone = document.getElementById('phone').value;
if(!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(phone))){
alert("手機(jī)號(hào)碼有誤觅玻,請(qǐng)重填");
return false;
}
}
郵箱號(hào)碼
^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$
Vue—漸進(jìn)式 JavaScript 框架
Vue相關(guān)概念
Vue的誕生
Vue是一個(gè)前端js框架想际,由尤雨溪開(kāi)發(fā),是個(gè)人項(xiàng)目溪厘,目前由餓了么ued團(tuán)隊(duì)進(jìn)行維護(hù)胡本。Vue近幾年來(lái)特別的受關(guān)注,三年前的時(shí)候angularJS霸占前端JS框架市場(chǎng)很長(zhǎng)時(shí)間畸悬,接著react框架橫空出世侧甫,因?yàn)樗幸粋€(gè)特性是虛擬DOM,從性能上碾軋angularJS蹋宦,這個(gè)時(shí)候披粟,vue1.0悄悄的問(wèn)世了,它的優(yōu)雅冷冗,輕便也吸引了一部分用戶守屉,開(kāi)始收到關(guān)注,16年中旬贾惦,VUE2.0問(wèn)世胸梆,這個(gè)時(shí)候vue不管從性能上,還是從成本上都隱隱超過(guò)了react须板,火的一塌糊涂碰镜,這個(gè)時(shí)候,angular開(kāi)發(fā)團(tuán)隊(duì)也開(kāi)發(fā)了angular2.0版本习瑰,并且更名為angular绪颖,吸收了react、vue的優(yōu)點(diǎn),加上angular本身的特點(diǎn)柠横,也吸引到很多用戶窃款,目前已經(jīng)迭代到5.0了。
注意下Vue的誕生時(shí)間牍氛,面試官如果問(wèn)你是從什么時(shí)候開(kāi)始接觸并且使用Vue的晨继,你如果回答用了5、6年了那場(chǎng)面就十分尷尬了搬俊。
Vue漸進(jìn)式框架的理解紊扬?
在聲明式渲染(視圖模板引擎)的基礎(chǔ)上,我們可以通過(guò)添加組件系統(tǒng)(components)唉擂、客戶端路由(vue-router)餐屎、大規(guī)模狀態(tài)管理(vuex)來(lái)構(gòu)建一個(gè)完整的框架。更重要的是玩祟,這些功能相互獨(dú)立腹缩,你可以在核心功能的基礎(chǔ)上任意選用其他的部件,不一定要全部整合在一起空扎〔厝担可以看到,所說(shuō)的“漸進(jìn)式”勺卢,其實(shí)就是Vue的使用方式伙判,同時(shí)也體現(xiàn)了Vue的設(shè)計(jì)的理念。
拓展:Vue2.0 中黑忱,“漸進(jìn)式框架”和“自底向上增量開(kāi)發(fā)的設(shè)計(jì)”這兩個(gè)概念是什么宴抚?
https://www.zhihu.com/question/51907207
虛擬DOM
什么是虛擬DOM?
我們知道操作DOM的代價(jià)是昂貴的甫煞,所以vue2.0采用了虛擬DOM來(lái)代替對(duì)真實(shí)DOM的操作菇曲,最后通過(guò)某種機(jī)制來(lái)完成對(duì)真實(shí)DOM的更新,渲染視圖抚吠。
所謂的虛擬DOM常潮,其實(shí)就是用JS來(lái)模擬DOM結(jié)構(gòu),把DOM的變化操作放在JS層來(lái)做楷力,盡量減少對(duì)DOM的操作 (個(gè)人認(rèn)為主要是因?yàn)椴僮鱆S比操作DOM快了不知道多少倍闷叉,JS運(yùn)行效率高)趁蕊。然后對(duì)比前后兩次的虛擬DOM的變化环揽,只重新渲染變化了的部分鹿蜀,而沒(méi)有變化的部分則不會(huì)重新渲染。
必須要注意一點(diǎn)的是:JS模擬的DOM結(jié)構(gòu)并沒(méi)有模擬所有DOM節(jié)點(diǎn)上的屬性检柬、方法(因?yàn)镈OM節(jié)點(diǎn)本身的屬性非常多献联,這也是DOM操作耗性能的一個(gè)點(diǎn)),而是只模擬了一部分和數(shù)據(jù)操作相關(guān)的屬性和方法。
Virual DOM是用JS對(duì)象記錄一個(gè)dom節(jié)點(diǎn)的副本里逆,當(dāng)dom發(fā)生更改時(shí)候进胯,先用虛擬dom進(jìn)行diff,算出最小差異原押,然后再修改真實(shí)dom胁镐。
當(dāng)用傳統(tǒng)的方式操作DOM的時(shí)候,瀏覽器會(huì)從構(gòu)建DOM樹(shù)開(kāi)始從頭到尾執(zhí)行一遍流程诸衔,效率很低希停。而虛擬DOM是用javascript對(duì)象表示的,而操作javascript是很簡(jiǎn)便高效的署隘。虛擬DOM和真正的DOM有一層映射關(guān)系,很多需要操作DOM的地方都會(huì)去操作虛擬DOM亚隙,最后統(tǒng)一一次更新DOM磁餐,因而可以提高性能。
虛擬DOM的缺點(diǎn)
- 代碼更多阿弃,體積更大
- 內(nèi)存占用增大
- 小量的單一的dom修改使用虛擬dom成本反而更高诊霹,不如直接修改真實(shí)dom快
VUE中虛擬dom操作流程
在內(nèi)存中構(gòu)建虛擬dom樹(shù)
將內(nèi)存中虛擬dom樹(shù)渲染成真實(shí)dom結(jié)構(gòu)
數(shù)據(jù)改變的時(shí)候,將之前的虛擬dom樹(shù)結(jié)合新的數(shù)據(jù)生成新的虛擬dom樹(shù)
將此次生成好的虛擬dom樹(shù)和上一次的虛擬dom樹(shù)進(jìn)行一次比對(duì)(diff算法進(jìn)行比對(duì))
會(huì)將對(duì)比出來(lái)的差異進(jìn)行重新渲染
參考:vue2.0的虛擬DOM渲染思路分析
https://www.jb51.net/article/145319.htm
v-for循環(huán)渲染為什么要設(shè)置key值渣淳?虛擬DOM與key值的關(guān)系脾还?
(1)跟diff算法有關(guān):如果在兩個(gè)元素之間插入新元素,如果沒(méi)有key的話入愧,就需要把原位置的元素卸載了鄙漏,把新元素插進(jìn)來(lái),然后依次卸載棺蛛,會(huì)打亂后續(xù)元素的排列規(guī)則怔蚌,如果有key值,只需要插入到對(duì)應(yīng)位置即可旁赊,不會(huì)改變其他元素的走向桦踊。
(2)為了減免一些出錯(cuò)問(wèn)題:例如在數(shù)組中,本來(lái)第一個(gè)是選中的终畅,這時(shí)候我們?cè)偃ヌ砑有略丶瑁绻麤](méi)有key的話,那么新添加進(jìn)來(lái)的元素就會(huì)被選中离福,加上key就是為了避免出現(xiàn)這樣的問(wèn)題杖狼。
參考:Vue 虛擬DOM與key屬性
https://blog.csdn.net/weixin_42695446/article/details/84680213
虛擬DOM的Diff算法
虛擬DOM中,在DOM的狀態(tài)發(fā)生變化時(shí)术徊,虛擬DOM會(huì)進(jìn)行Diff運(yùn)算本刽,來(lái)更新只需要被替換的DOM,而不是全部重繪。
在Diff算法中子寓,只平層的比較前后兩棵DOM樹(shù)的節(jié)點(diǎn)暗挑,沒(méi)有進(jìn)行深度的遍歷。
computed計(jì)算屬性跟watch監(jiān)聽(tīng)的區(qū)別
computed計(jì)算屬性是根據(jù)現(xiàn)有數(shù)據(jù)生成一個(gè)新的數(shù)據(jù)斜友,并且兩者會(huì)產(chǎn)生關(guān)聯(lián)炸裆,建立永久緩存。當(dāng)無(wú)關(guān)數(shù)據(jù)變化的時(shí)候鲜屏,他不會(huì)重新計(jì)算烹看,而是直接從緩存里面取之前的值。
watch監(jiān)聽(tīng)依賴是單個(gè)的洛史,他每次監(jiān)聽(tīng)只能監(jiān)聽(tīng)一個(gè)變量的改變惯殊。
參考:淺談VUE虛擬dom
https://blog.csdn.net/mrliber/article/details/79036828
設(shè)計(jì)模式
VUE的設(shè)計(jì)模式MVVM
vue中采用了mvvm的設(shè)計(jì)模式,是從mvc/mvp演變過(guò)來(lái)的也殖,mvvm主要解決了mvc反饋不及時(shí)的問(wèn)題土思,或者實(shí)現(xiàn)了自動(dòng)同步的功能。
也就是說(shuō)model層改變的時(shí)候忆嗜,我們不需要手動(dòng)取更改dom己儒。而vm幫助我們實(shí)現(xiàn)了這個(gè)效果,改變屬性后該屬性對(duì)應(yīng)view會(huì)自動(dòng)更新捆毫,view與model之間沒(méi)有必然的聯(lián)系闪湾,靠vm將兩者進(jìn)行關(guān)聯(lián)。
MVC設(shè)計(jì)模式(單向通信)
- 視圖(View):用戶界面绩卤。
- 控制器(Controller):業(yè)務(wù)邏輯
- 模型(Model):數(shù)據(jù)保存
- View 傳送指令到 Controller
- Controller 完成業(yè)務(wù)邏輯后途样,要求 Model 改變狀態(tài)
- Model 將新的數(shù)據(jù)發(fā)送到 View,用戶得到反饋
MVP設(shè)計(jì)模式
MVP 模式將 Controller 改名為 Presenter省艳,同時(shí)改變了通信方向娘纷。
- 各部分之間的通信,都是雙向的跋炕。
- View 與 Model 不發(fā)生聯(lián)系赖晶,都通過(guò) Presenter 傳遞。
- View 非常薄辐烂,不部署任何業(yè)務(wù)邏輯遏插,稱為"被動(dòng)視圖"(Passive View),即沒(méi)有任何主動(dòng)性纠修,而 Presenter非常厚胳嘲,所有邏輯都部署在那里。
MVVM設(shè)計(jì)模式
MVVM 模式將 Presenter 改名為 ViewModel扣草,基本上與 MVP 模式完全一致了牛。
唯一的區(qū)別是颜屠,它采用雙向綁定(data-binding):View的變動(dòng),自動(dòng)反映在 ViewModel鹰祸,反之亦然。Angular 和 Ember 都采用這種模式蛙婴。
參考:MVC粗井,MVP 和 MVVM 的圖示
http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html
MVC、MVP街图、MVVM三種區(qū)別及適用場(chǎng)合
https://blog.csdn.net/victoryzn/article/details/78392128
MVVM解決了什么問(wèn)題
mvvm就是為了解決mvc反饋不及時(shí)的問(wèn)題
MVVM與MVC的區(qū)別
MVVM實(shí)現(xiàn)了View和Model的自動(dòng)同步浇衬,也就是當(dāng)Model屬性改變時(shí),我們不用再自己手動(dòng)操作Dom元素餐济,來(lái)改變View的顯示耘擂,而是改變屬性后該屬性對(duì)應(yīng)View層顯示會(huì)自動(dòng)改變(雙向數(shù)據(jù)綁定原理)。
為什么model層數(shù)據(jù)更改的時(shí)候絮姆,vm就可以知道數(shù)據(jù)改變了呢梳星?(vue的mvm框架的雙向綁定原理是什么)
雙向數(shù)據(jù)綁定:
當(dāng)視圖改變更新模型層
當(dāng)模型層改變更新視圖層
在Vue中,使用了雙向綁定技術(shù)滚朵,就是View的變化能實(shí)時(shí)讓Model發(fā)生變化,而Model的變化也能實(shí)時(shí)更新到View前域。Vue采用數(shù)據(jù)劫持&發(fā)布-訂閱模式的方式辕近,vue在創(chuàng)建vm的時(shí)候,會(huì)將數(shù)據(jù)配置在實(shí)例當(dāng)中匿垄,然后通過(guò)Object.defineProperty對(duì)數(shù)據(jù)進(jìn)行操作移宅,為數(shù)據(jù)動(dòng)態(tài)添加了getter與setter方法,當(dāng)獲取數(shù)據(jù)的時(shí)候會(huì)觸發(fā)對(duì)應(yīng)的getter方法漏峰,當(dāng)設(shè)置數(shù)據(jù)的時(shí)候會(huì)觸發(fā)對(duì)應(yīng)的setter方法埠忘,從而進(jìn)一步觸發(fā)vm的watcher方法疯趟,然后數(shù)據(jù)更改获印,vm則會(huì)進(jìn)一步觸發(fā)視圖更新操作质礼。
參考:剖析Vue原理&實(shí)現(xiàn)雙向綁定MVVM
https://segmentfault.com/a/1190000006599500
雙向數(shù)據(jù)綁定的實(shí)現(xiàn)
要實(shí)現(xiàn)Vue中的雙向數(shù)據(jù)綁定爽航,大致可以劃分三個(gè)模塊:Observer竣况、Compile规惰、Watcher
- Observer 數(shù)據(jù)監(jiān)聽(tīng)器
負(fù)責(zé)對(duì)數(shù)據(jù)對(duì)象的所有屬性進(jìn)行監(jiān)聽(tīng)(數(shù)據(jù)劫持)睬塌,監(jiān)聽(tīng)到數(shù)據(jù)發(fā)生變化后通知訂閱者。 - Compiler 指令解析器
掃描模板歇万,并對(duì)指令進(jìn)行 解析揩晴,然后綁定指定事件。 - Watcher 訂閱者
關(guān)聯(lián)Observer和Compile贪磺,能夠訂閱并收到屬性變動(dòng)的通知硫兰,執(zhí)行指令綁定的相應(yīng)操作,更新視圖寒锚。
let data = {
message:"hello world!"
}
let vm = new Vue({
el:"#app",
data
});
// console.log(data);
// console.log(vm.$data);
//Object.defineProperty es5提供的 ie8不支持 原理
let _data={
}
let middle = 123;
Object.defineProperty(_data,"msg",{ //給某個(gè)對(duì)象賦了一個(gè)屬性 屬性中提供了get方法和set方法
get(){
return middle; 調(diào)用_data.msg相當(dāng)于調(diào)用get方法 直接返回123
},
set(val){
// _data.msg = val;
middle = val; 設(shè)置完之后middle=4
}
});
console.log(_data.msg);//獲取屬性的時(shí)候劫映,就會(huì)執(zhí)行g(shù)etter方法
_data.msg = 4;//設(shè)置屬性的時(shí)候违孝,就會(huì)執(zhí)行setter方法 相當(dāng)于給這個(gè)對(duì)象設(shè)置msg屬性為4
console.log(_data.msg);
this.$nextTick()
用swiper時(shí)涤妒,有沒(méi)有出現(xiàn)圖片劃不動(dòng)的情況轨奄,原因是什么?你怎么解決的务荆?
【VUE】swiper實(shí)例化后會(huì)出現(xiàn)劃不動(dòng)現(xiàn)象祖今,產(chǎn)生的原因是本來(lái)這個(gè)地方是沒(méi)有swiper-slide這個(gè)數(shù)據(jù)的校坑,后續(xù)我們發(fā)送了ajax請(qǐng)求他才會(huì)動(dòng)態(tài)生成swiperslide,banners數(shù)據(jù)立馬改變了千诬,它內(nèi)部會(huì)生成新的虛擬dom和上一次虛擬dom結(jié)構(gòu)作對(duì)比耍目,然后產(chǎn)生新的真實(shí)dom,這個(gè)過(guò)程需要時(shí)間大渤,但是我們立馬實(shí)例化了制妄,所以等到真實(shí)dom渲染完成后實(shí)例化早就結(jié)束了。解決方法就是泵三,我們必須要等到因?yàn)閿?shù)據(jù)改變了引發(fā)新的真實(shí)dom渲染完成后才會(huì)執(zhí)行的操作耕捞,就可以避免這樣的問(wèn)題。
所以我們需要把實(shí)例化的過(guò)程寫(xiě)在this.$nextTick
的回調(diào)函數(shù)中烫幕,在這個(gè)函數(shù)里面進(jìn)行的操作就是等到數(shù)據(jù)更新而引發(fā)的頁(yè)面當(dāng)中新的虛擬dom所渲染成的真實(shí)dom真正渲染出來(lái)之后才執(zhí)行俺抽,簡(jiǎn)單來(lái)說(shuō)就是等到頁(yè)面全部渲染完成后。
created(){
this.$http.get("/api/v2/movie/in_theaters",{
params:{
count:6
}
}).then(res=>{
console.log(res)
this.banners = res.data.subjects
//問(wèn)題:異步請(qǐng)求 數(shù)據(jù)改變了 產(chǎn)生新的虛擬dom 需要與上一次虛擬dom結(jié)構(gòu)對(duì)比 diff算法更新差異對(duì)比需要一定時(shí)間 數(shù)據(jù)渲染完成后直接實(shí)例化 就可能導(dǎo)致虛擬dom對(duì)比完成之后生成新的虛擬dom 這個(gè)實(shí)例化的代碼早就執(zhí)行完畢了
this.$nextTick(()=>{//這個(gè)方法的作用就是 數(shù)據(jù)更改引發(fā)新的虛擬dom更新完畢 生成真實(shí)dom后 才會(huì)進(jìn)入此函數(shù)的回調(diào)函數(shù)中 所以在這個(gè)回調(diào)函數(shù)中就可以拿到因數(shù)據(jù)改變而更新生成的真實(shí)dom
new Swiper(".home-banner",{
loop:true
})
})
})
this.$nextTick() 主要作用是等數(shù)據(jù)改變引發(fā)dom重新渲染完成之后才會(huì)執(zhí)行
可以在實(shí)例化配置項(xiàng)中進(jìn)行如下配置 (自己了解一下较曼,但是面試官一般就想讓你說(shuō)this.$nextTick()這個(gè)知識(shí)點(diǎn))
observer:true,
observeParents:true//修改swiper子元素的話磷斧,會(huì)自動(dòng)幫助我們初始化swiper
生命周期
【初始化階段(4個(gè))】
(1)beforeCreate
此鉤子函數(shù)不能獲取到數(shù)據(jù),dom元素也沒(méi)有渲染出來(lái)捷犹,此鉤子函數(shù)不會(huì)用來(lái)做什么事情弛饭。
(2)created
此鉤子函數(shù),數(shù)據(jù)已經(jīng)掛載了萍歉,但是dom節(jié)點(diǎn)還是沒(méi)有渲染出來(lái)侣颂,在這個(gè)鉤子函數(shù)里面,如果同步更改數(shù)據(jù)的話枪孩,不會(huì)影響運(yùn)行中鉤子函數(shù)的執(zhí)行憔晒。可以用來(lái)發(fā)送ajax請(qǐng)求蔑舞,也可以做一些初始化事件的相關(guān)操作拒担。
(3)beforeMount
代表dom節(jié)點(diǎn)馬上要被渲染出來(lái)了,但是還沒(méi)有真正的渲染出來(lái)攻询,此鉤子函數(shù)跟created鉤子函數(shù)基本一樣从撼,也可以做一些初始化數(shù)據(jù)的配置。
(4)mounted
是生命周期初始化階段的最后一個(gè)鉤子函數(shù)钧栖,數(shù)據(jù)已經(jīng)掛載完畢了谋逻,真實(shí)dom也可以獲取到了呆馁。
【運(yùn)行中階段(2個(gè))】
(5)beforeUpdate
運(yùn)行中鉤子函數(shù)beforeUpdate默認(rèn)是不會(huì)執(zhí)行的,當(dāng)數(shù)據(jù)更改的時(shí)候毁兆,才會(huì)執(zhí)行浙滤。數(shù)據(jù)更新的時(shí)候,先調(diào)用beforeUpdate气堕,然后數(shù)據(jù)更新引發(fā)視圖渲染完成之后纺腊,再會(huì)執(zhí)行updated。運(yùn)行時(shí)beforeUpdate這個(gè)鉤子函數(shù)獲取的數(shù)據(jù)還是更新之前的數(shù)據(jù)(獲取的是更新前的dom內(nèi)容)茎芭,在這個(gè)鉤子函數(shù)里面揖膜,千萬(wàn)不能對(duì)數(shù)據(jù)進(jìn)行更改,會(huì)造成死循環(huán)梅桩。
(6)updated
這個(gè)鉤子函數(shù)獲取的數(shù)據(jù)是更新后的數(shù)據(jù)壹粟,生成新的虛擬dom,跟上一次的虛擬dom結(jié)構(gòu)進(jìn)行比較宿百,比較出來(lái)差異(diff算法)后再渲染真實(shí)dom趁仙,當(dāng)數(shù)據(jù)引發(fā)dom重新渲染的時(shí)候,在updated鉤子函數(shù)里面就可以獲取最新的真實(shí)dom了垦页。
【銷(xiāo)毀階段(2個(gè))】
(7)beforeDestroy
切換路由的時(shí)候雀费,組件就會(huì)被銷(xiāo)毀了,銷(xiāo)毀之前執(zhí)行beforeDestroy痊焊。在這個(gè)鉤子函數(shù)里面盏袄,我們可以做一些善后的操作,例如可以清空一下全局的定時(shí)器(created鉤子函數(shù)綁定的初始化階段的事件)薄啥、清除事件綁定辕羽。
(8)destoryed
組件銷(xiāo)毀后執(zhí)行destroyed,銷(xiāo)毀后組件的雙向數(shù)據(jù)綁定垄惧、事件監(jiān)聽(tīng)watcher相關(guān)的都被移除掉了刁愿,但是組件的真實(shí)dom結(jié)構(gòu)還是存在在頁(yè)面中的。
官網(wǎng)這張生命周期流程圖要熟練掌握赘艳,在面試官問(wèn)到的時(shí)候最好能將這張圖畫(huà)出來(lái),針對(duì)每個(gè)函數(shù)的功能做詳細(xì)解答克握,整個(gè)過(guò)程至少保持在3-5分鐘蕾管。如果面試官很有耐心,還想繼續(xù)聽(tīng)你說(shuō)下去菩暗,可以拓展keep-alive標(biāo)簽的active和deactive這兩個(gè)生命周期函數(shù)掰曾,屬于加分項(xiàng)。
組件
什么是組件停团?
WEB中的組件其實(shí)就是頁(yè)面組成的一部分旷坦,好比是電腦中的每一個(gè)元件(如硬盤(pán)掏熬、鍵盤(pán)、鼠標(biāo))秒梅,它是一個(gè)具有獨(dú)立的邏輯和功能或界面旗芬,同時(shí)又能根據(jù)規(guī)定的接口規(guī)則進(jìn)行相互融合,變成一個(gè)完整的應(yīng)用捆蜀。
頁(yè)面就是由一個(gè)個(gè)類(lèi)似這樣的部分組成的疮丛,比如導(dǎo)航、列表辆它、彈窗誊薄、下拉菜單。頁(yè)面只不過(guò)是這些組件的容器锰茉,組件自由組合形成功能完整的界面呢蔫,當(dāng)不需要某個(gè)組件,或者想要替換某個(gè)組件時(shí)飒筑,可以隨時(shí)進(jìn)行替換和刪除片吊,而不影響整個(gè)應(yīng)用的運(yùn)行。
【注】前端組件化的核心思想就是將一個(gè)巨大復(fù)雜的東西拆分成粒度合理的小東西扬霜。
頁(yè)面中能被復(fù)用的內(nèi)容都被稱之為組件定鸟,你所能看到的一些結(jié)構(gòu),像頭部Header著瓶、Footer联予、Banner都可以被封裝成一個(gè)組件去復(fù)用,組件就是集成了html材原、css沸久、js、image的一個(gè)聚合體余蟹。
使用組件的好處卷胯?
(1)提高開(kāi)發(fā)效率
(2)方便重復(fù)使用
(3)簡(jiǎn)化調(diào)試步驟
(4)提升整個(gè)項(xiàng)目的可維護(hù)性
(5)便于協(xié)同開(kāi)發(fā)
組件的特性
高內(nèi)聚,低耦合
為什么要封裝組件威酒?
(1)解耦
(2)提升組件復(fù)用性
組件封裝的案例
<div id="demo">
<v-header></v-header>
</div>
<template id="header">
<div>
{{msg}}<input/>
</div>
</template>
var Header = {
template:"#header",
data(){
return {
msg:"v-header的msg!!!"
}
}
};
new Vue({
el:"#demo",
components:{
"v-header":Header
}
});
組件中的data是什么類(lèi)型窑睁?為什么是一個(gè)函數(shù)?
實(shí)例中的data是什么類(lèi)型葵孤?
為什么實(shí)例中的data是一個(gè)對(duì)象担钮,組件中的data是一個(gè)函數(shù)?
為了防止組件與組件之間的數(shù)據(jù)共享尤仍,讓作用域獨(dú)立箫津,data是函數(shù)內(nèi)部返回一個(gè)對(duì)象,讓每個(gè)組件或者實(shí)例可以維護(hù)一份被返回對(duì)象的獨(dú)立的拷貝。組件可以被復(fù)用苏遥,但是數(shù)據(jù)不能共享饼拍,每個(gè)組件管理自己的數(shù)據(jù)更新,不能影響其他組件的數(shù)據(jù)田炭。
參考:data必須是一個(gè)函數(shù)(VUE官網(wǎng))
組件的 data 選項(xiàng)必須是一個(gè)函數(shù)师抄,以便每個(gè)實(shí)例都可以維護(hù)「函數(shù)返回的數(shù)據(jù)對(duì)象」的彼此獨(dú)立的數(shù)據(jù)副本。
vue組件傳值
父子組件通信
1诫肠、父子組件通過(guò)prop傳遞數(shù)據(jù)
父組件可以將一條數(shù)據(jù)傳遞給子組件司澎,這條數(shù)據(jù)可以是動(dòng)態(tài)的,父組件的數(shù)據(jù)更改的時(shí)候栋豫,子組件接收的也會(huì)變化
子組件被動(dòng)的接收父組件的數(shù)據(jù),子組件不要再更改這條數(shù)據(jù)了挤安。
組件實(shí)例的作用域是孤立的,父組件不能直接使用子組件的數(shù)據(jù),子組件也不能直接使用父組件的數(shù)據(jù)丧鸯。
父組件在調(diào)用子組件的時(shí)候給子組件傳遞數(shù)據(jù):
<template id="father">
<div class="father">
<p>我是父組件蛤铜,這是我的fMsg:{{fMsg}}</p>
<input type = "text" v-model = "fMsg">
<hr>
<son msg = "你好"></son>
</div>
</template>
父組件給子組件傳遞數(shù)據(jù)的時(shí)候,子組件需要利用props的屬性來(lái)確定自己的預(yù)期數(shù)據(jù)丛肢,如果兒子沒(méi)有通過(guò)props屬性接受傳遞過(guò)來(lái)的數(shù)據(jù)映之,則數(shù)據(jù)會(huì)以自定義屬性的方式盅弛,放在兒子最外層的根元素上面。
子組件通過(guò)props來(lái)接受父組件傳遞過(guò)來(lái)的數(shù)據(jù),并且通過(guò){{msg}}使用
components:{
son:{
template:"<div>我是son子組件昭躺!這是父組件傳遞給我的msg:{{msg}}</div>",
//接收父組件傳遞來(lái)的屬性 msg
props:["msg"]
}
}
2赁严、父組件通過(guò)v-bind指令傳遞自身變量給子組件
我們可以用 v-bind 來(lái)動(dòng)態(tài)地將 prop 綁定到父組件的數(shù)據(jù)孩锡。每當(dāng)父組件的數(shù)據(jù)變化時(shí)员帮,該變化也會(huì)傳導(dǎo)給子組件。
<template id="father">
<div class="father">
<p>我是父組件幽歼,這是我的fMsg:{{fMsg}}</p>
<input type = "text" v-model = "fMsg">
<hr>
<!-- <son msg = "你好"></son> -->
<son :msg = "fMsg"></son>
</div>
</template>
如果如果父組件傳遞屬性給子組件的時(shí)候鍵名有'-'
<son :f-msg = "fMsg"></son>
子組件接收朵锣、使用的時(shí)候?qū)懗尚●劮宓哪J?/p>
components:{
son:{
template:"<div>我是son子組件!這是父組件傳遞給我的msg:{{fMsg}}</div>",
//接收父組件傳遞來(lái)的屬性 msg
props:["fMsg"]
}
}
3甸私、父子組件依靠應(yīng)用類(lèi)型的地址傳遞共享數(shù)據(jù)
單向數(shù)據(jù)流
Prop 是單向綁定的:當(dāng)父組件的屬性變化時(shí)诚些,將傳遞給子組件,但是反過(guò)來(lái)不會(huì)皇型。這是為了防止子組件無(wú)意間修改了父組件的狀態(tài)诬烹,來(lái)避免應(yīng)用的數(shù)據(jù)流變得難以理解。
<template id="father">
<div class="father">
<input type = "text" v-model = "message">
<hr>
<son :message = "message"></son>
</div>
</template>
<template id = "son">
<div>
<p>這是子組件</p>
<input type = "text" v-model = "message"></input>
</div>
</template>
另外弃鸦,每次父組件更新時(shí)绞吁,子組件的所有 prop 都會(huì)更新為最新值。這意味著你不應(yīng)該在子組件內(nèi)部改變 prop寡键。如果你這么做了掀泳,Vue 會(huì)在控制臺(tái)給出警告。
所以如果我們想實(shí)現(xiàn)父子間的數(shù)據(jù)共享西轩,依靠的就是應(yīng)用類(lèi)型的地址傳遞员舵,應(yīng)將message寫(xiě)成對(duì)象的形式,傳遞的時(shí)候?qū)?duì)象傳遞給子組件藕畔,子組件引用的時(shí)候使用對(duì)象的value值马僻。
<template id="father">
<div class="father">
<input type = "text" v-model = "message.value">
<hr>
<!-- 傳遞的時(shí)候?qū)?duì)象傳遞給子組件 -->
<son :message = "message"></son>
</div>
</template>
<template id = "son">
<div>
<p>這是子組件</p>
<!-- 引用的時(shí)候使用對(duì)象的value值 -->
<input type = "text" v-model = "message.value"></input>
</div>
</template>
這時(shí)候更改父組件的value值,子組件的數(shù)據(jù)同步更改注服,子組件修改value值的時(shí)候也同步修改了父組件的數(shù)據(jù)韭邓。這是因?yàn)椴还苁亲咏M件還是父組件,我們操作的都是同一個(gè)對(duì)象溶弟,父組件直接把引用類(lèi)型的地址傳遞給子組件女淑,子組件沒(méi)有直接修改對(duì)象,只是更改了里面的屬性值辜御。
父組件如果將一個(gè)引用類(lèi)型的動(dòng)態(tài)數(shù)據(jù)傳遞給子組件的時(shí)候鸭你,數(shù)據(jù)會(huì)變成雙向控制的,子組件改數(shù)據(jù)的時(shí)候父組件也能接收到數(shù)據(jù)變化,因?yàn)樽咏M件改的時(shí)候不是在改數(shù)據(jù)(地址)擒权,而是在改數(shù)據(jù)里的內(nèi)容袱巨,也就是說(shuō)引用類(lèi)型數(shù)據(jù)的地址始終沒(méi)有變化,不算改父組件數(shù)據(jù)碳抄。
注意:在 JavaScript 中對(duì)象和數(shù)組是引用類(lèi)型愉老,指向同一個(gè)內(nèi)存空間,如果 prop 是一個(gè)對(duì)象或數(shù)組剖效,在子組件內(nèi)部改變它會(huì)影響父組件的狀態(tài)嫉入。 message:{val:""}
4贱鄙、viewmodel關(guān)系鏈
在組件間可以用過(guò)ref形成ref鏈劝贸,組件還擁有一個(gè)關(guān)系鏈($parent),通過(guò)這兩種鏈;理論來(lái)說(shuō)逗宁,任意的兩個(gè)組件都可以互相訪問(wèn)映九,互相進(jìn)行通信。
$parent:父組件
$children:子組件
$root:根組件
當(dāng)子組件在set方法中修改父組件傳遞過(guò)來(lái)的值時(shí)瞎颗,系統(tǒng)會(huì)報(bào)錯(cuò)件甥,因?yàn)樽咏M件不能修改父組件的數(shù)據(jù)。
Vue.component("bbb",{
template:"#bbb",
props:["msg"],
computed:{
/* ownMessage(){
return this.msg;
} */
ownMessage:{
get(){
return this.msg;
},
set(val){
this.msg = val //系統(tǒng)報(bào)錯(cuò):子組件不能更改父組件傳遞的數(shù)據(jù)
}
}
}
})
所以這時(shí)候要使用$parent哼拔,讓父組件自己更改自己的數(shù)據(jù)
set(val){
// this.msg = val //系統(tǒng)報(bào)錯(cuò):子組件不能更改父組件傳遞的數(shù)據(jù)
// console.log(this)
// 相當(dāng)于父組件自己更改了msg數(shù)據(jù)
this.$parent.msg = val;
}
5引有、父組件通過(guò)ref標(biāo)記獲取子組件的數(shù)據(jù)
父組件在調(diào)用子組件的時(shí)候使用ref做標(biāo)記
<template id="aaa">
<div>
<button @click = "get">點(diǎn)擊獲取bbb數(shù)據(jù)</button>
<!-- 組件間不僅可以用過(guò)$root/$parent/$children來(lái)獲取對(duì)應(yīng)關(guān)系的組件,父組件還可以主動(dòng)的通過(guò)ref為子組件做標(biāo)記 -->
<bbb ref = "b"></bbb>
</div>
</template>
父組件的this屬性上有$refs標(biāo)記倦逐,通過(guò)refs標(biāo)記拿到子組件
// 通過(guò)ref標(biāo)記更改子組件的數(shù)據(jù)
// this.$refs.b.message = "哈哈"
組件間不僅可以用過(guò)$parent/children/root來(lái)獲取對(duì)應(yīng)關(guān)系的組件譬正,父組件還可以主動(dòng)的通過(guò)ref為子組件做標(biāo)記 也可以給dom做標(biāo)記,也會(huì)形成ref鏈,也可以交互.
<button ref="btn" @click="get">get</button>
<bbb ref="b></bbb>
注意多個(gè)子組件標(biāo)記的是同一個(gè)鍵名曾我,獲取到的應(yīng)該是一個(gè)數(shù)組
<bbb ref = "b" v-for = "(item,index) in 3" :key = "index"></bbb>
// 通過(guò)下標(biāo)修改對(duì)應(yīng)的數(shù)值
this.$refs.b[0].message = "哈哈"
子父組件通信
1粉怕、子組件通過(guò)父組件傳遞的方法來(lái)更改父組件的數(shù)據(jù)
父組件可以將更改自身數(shù)據(jù)的方法傳遞給子組件,子組件調(diào)用這個(gè)方法的時(shí)候抒巢,就可以給父組件傳遞數(shù)據(jù)贫贝,父組件被動(dòng)的接收子組件的數(shù)據(jù)。
子組件聲明一條自身的msg
Vue.component("son",{
template:"#son",
// 子組件接收父組件傳遞過(guò)來(lái)的方法
props:["change"],
data(){
return{
msg:"我是子組件"
}
}
})
父組件先聲明一條自己的數(shù)據(jù)
data(){
return{
// 父組件先聲明一條自己的數(shù)據(jù)
parentMsg:""
}
}
再寫(xiě)一個(gè)可以更改自身數(shù)據(jù)的方法
methods:{
// 寫(xiě)一個(gè)可以更改自身數(shù)據(jù)的方法
change(msg){
this.parentMsg = msg
}
}
將寫(xiě)好的change方法傳遞給子組件
<template id="father">
<div>
<p>這是父組件</p>
<p>子組件傳遞過(guò)來(lái)的值是:{{parentMsg}}</p>
<hr>
<!-- 調(diào)用子組件的時(shí)候蛉谜,將更改自身數(shù)據(jù)的方法傳遞給子組件 -->
<son :change = "change"></son>
</div>
</template>
子組件通過(guò)props接收父組件傳遞過(guò)來(lái)的change方法
props:["change"]
給p標(biāo)簽添加點(diǎn)擊事件稚晚,點(diǎn)擊即觸發(fā)change方法,同時(shí)將自身的msg傳遞給父組件型诚,相當(dāng)于父組件的change方法被執(zhí)行客燕。
<template id="son">
<div>
<p>子組件說(shuō):{{msg}}</p>
<p @click = "change(msg)">點(diǎn)擊我觸發(fā)父親的change方法</p>
</div>
</template>
父組件可以在頁(yè)面中渲染子組件傳遞過(guò)來(lái)的數(shù)據(jù)
<p>子組件傳遞過(guò)來(lái)的值是:{{parentMsg}}</p>
2、通過(guò)自定義事件實(shí)現(xiàn)子父通信
每一個(gè)組件或者實(shí)例都會(huì)有自定義事件狰贯,和觸發(fā)事件的能力幸逆,父組件給子組件綁定一個(gè)自定義事件,這個(gè)事件的處理程序卻是父組件的一個(gè)方法暮现,當(dāng)子組件觸發(fā)這個(gè)事件的時(shí)候还绘,相當(dāng)于父組件的方法被執(zhí)行。
父組件想獲取子組件的數(shù)據(jù)時(shí)栖袋,在調(diào)用子組件的時(shí)候給子組件綁定一個(gè)自定義事件change-event
<template id="father">
<div>
<p>這是父組件</p>
<p>子組件傳遞過(guò)來(lái)的值是:{{parentMsg}}</p>
<hr>
<!-- 給子組件綁定一個(gè)自定義事件 -->
<son @change-event = "change"></son>
</div>
</template>
在子組件中定義一個(gè)點(diǎn)擊事件拍顷,點(diǎn)擊p標(biāo)簽執(zhí)行changeWord方法
<p @click = "changeWord">點(diǎn)擊我觸發(fā)父親的change方法</p>
在方法中編寫(xiě)changeWord方法,通過(guò)this.$emit來(lái)觸發(fā)綁定在自己身上的自定義事件塘幅,第一個(gè)參數(shù)為事件名稱change-event昔案,第二個(gè)參數(shù)為觸發(fā)這個(gè)函數(shù)的時(shí)候給他傳遞的數(shù)值:自身的msg。
methods:{
changeWord(){
//觸發(fā)自身綁定的change事件
this.$emit("change-event",this.msg)//第一個(gè)參數(shù)為觸發(fā)事件的名字电媳,第二個(gè)參數(shù)為觸發(fā)這個(gè)函數(shù)的時(shí)候給他傳遞的數(shù)值
}
}
一旦觸發(fā)綁定在自身上的自定義事件踏揣,相當(dāng)于父組件的change方法被執(zhí)行。
兄弟組件通信
1匾乓、通過(guò)viewmodel關(guān)系鏈
定義哥哥組件捞稿,給哥哥組件添加一個(gè)點(diǎn)擊事件,點(diǎn)擊觸發(fā)hitLittle方法
<template id = "big-brother">
<div>
<p>我是哥哥</p>
<button @click = "hitLittle">打弟弟</button>
</div>
</template>
定義弟弟組件拼缝,給弟弟組件添加一個(gè)p標(biāo)簽娱局,由crying數(shù)據(jù)控制其顯示與隱藏
<template id="little-brother">
<div>
<p>我是弟弟</p>
<p v-if = "crying">嗚嗚嗚</p>
</div>
</template>
在弟弟組件的data中聲明crying數(shù)據(jù),默認(rèn)為false
Vue.component("little-brother",{
template:"#little-brother",
data(){
return{
crying:false
}
}
})
在哥哥組件的methods中定義hitLittle方法咧七,通過(guò)viewmodel關(guān)系鏈更改弟弟組件中的crying方法
Vue.component("big-brother",{
template:"#big-brother",
methods:{
hitLittle(){
//在兄弟組件之間的通信衰齐,可以采用關(guān)系鏈和ref鏈去使用,解決兄弟之間通信問(wèn)題继阻。
this.$parent.$children[1].crying = true;//讓littel改變自身的crying狀態(tài)
}
}
})
2耻涛、viewmodel關(guān)系鏈+ref鏈
在弟弟組件中添加ref標(biāo)記
<little-brother ref = "little"></little-brother>
在哥哥組件的hitLittle方法中通過(guò)viewmodel和ref鏈配合使用更改弟弟組件中的crying數(shù)據(jù)
hitLittle(){
//在兄弟組件之間的通信废酷,可以采用關(guān)系鏈和ref鏈去使用,解決兄弟之間通信問(wèn)題抹缕。
// this.$parent.$children[1].crying = true;//讓littel改變自身的crying狀態(tài)
//viewmodel鏈和ref鏈配合使用
this.$parent.$refs.little.crying = true;
}
3锦积、eventbus事件總線
創(chuàng)建一個(gè)空的實(shí)例
var angle = new Vue();
弟弟組件自己定義一個(gè)更改自身狀態(tài)的方法
methods:{
cry(){
this.crying = true
}
}
在mounted生命周期函數(shù)中綁定一個(gè)自定義事件,第一個(gè)參數(shù)為自定義事件名歉嗓,第二個(gè)函數(shù)為需要處理的函數(shù)
mounted(){
// 綁定一個(gè)自定義事件,第一個(gè)參數(shù)為自定義事件名背蟆,第二個(gè)函數(shù)為需要處理的函數(shù)
angle.$on("hit-little",this.cry)
}
在哥哥組件中觸發(fā)自定義事件
hitLittle(){
//觸發(fā)little-brother組件的hit-little事件
angle.$emit("hit-little")
}
keep-alive緩存
keep-alive在項(xiàng)目中如何應(yīng)用鉴分?
當(dāng)在組件之間進(jìn)行切換的時(shí)候,你有時(shí)會(huì)想保持這些組件的狀態(tài)带膀,以避免反復(fù)重渲染導(dǎo)致的性能問(wèn)題志珍。當(dāng)從a頁(yè)面跳轉(zhuǎn)到b頁(yè)面再跳轉(zhuǎn)回a頁(yè)面時(shí),可以不用再次進(jìn)行數(shù)據(jù)請(qǐng)求垛叨,直接從緩存里面獲取數(shù)據(jù)伦糯,減少性能消耗。
例如我們來(lái)展開(kāi)說(shuō)一說(shuō)這個(gè)多標(biāo)簽界面:
你會(huì)注意到嗽元,如果你選擇了一篇文章敛纲,切換到 Archive 標(biāo)簽,然后再切換回 Posts剂癌,是不會(huì)繼續(xù)展示你之前選擇的文章的淤翔。這是因?yàn)槟忝看吻袚Q新標(biāo)簽的時(shí)候,Vue 都創(chuàng)建了一個(gè)新的 currentTabComponent 實(shí)例佩谷。
重新創(chuàng)建動(dòng)態(tài)組件的行為通常是非常有用的旁壮,但是在這個(gè)案例中,我們更希望那些標(biāo)簽的組件實(shí)例能夠被在它們第一次被創(chuàng)建的時(shí)候緩存下來(lái)谐檀。為了解決這個(gè)問(wèn)題抡谐,我們可以用一個(gè) <keep-alive> 元素將其動(dòng)態(tài)組件包裹起來(lái)。
keep-alive的生命周期函數(shù)
當(dāng)組件在<keep-alive>內(nèi)被切換時(shí)桐猬,它的actived和deactived這兩個(gè)生命周期鉤子函數(shù)將會(huì)被對(duì)應(yīng)執(zhí)行麦撵,初始化操作放在actived里面,一旦切換組件溃肪,因?yàn)榻M件沒(méi)有被銷(xiāo)毀厦坛,所以它不會(huì)執(zhí)行銷(xiāo)毀階段的鉤子函數(shù)诞挨,所以移除操作需要放在deactived里面,在里面進(jìn)行一些善后操作惭蟋,這個(gè)時(shí)候created鉤子函數(shù)只會(huì)執(zhí)行一次恳守,銷(xiāo)毀的鉤子函數(shù)一直沒(méi)有執(zhí)行。
keep-alive的屬性
Keep-alive提供了兩個(gè)屬性:允許組件有條件的緩存
include:我只需要緩存哪一些組件
exclude:除了這個(gè)組件之外其他組件都會(huì)被緩存
原理:
在created的時(shí)候伊群,將需要緩存的虛擬dom節(jié)點(diǎn)放到cache中考杉,在render的時(shí)候根據(jù)name再進(jìn)行取出脓匿。
keep-alive只能在組件切換的標(biāo)簽中進(jìn)行緩存
<keep-alive include="indexCom">
<router-view/>
</keep-alive>
使用傳統(tǒng)寫(xiě)法比較麻煩膏燕,我們可以在需要被緩存的頁(yè)面的路由中添加keepAlive:true
字段
{
path: '/',
name: 'index',
meta:{
keepAlive:true //該字段表明頁(yè)面需要緩存
},
component: resolve=>require(["@/page/index"],resolve)
}
在組件切換的時(shí)候果录,檢查下原數(shù)據(jù)上面有沒(méi)有keepAlive這個(gè)屬性讹开,如果有的話就keep-alive緩存一下,沒(méi)有的話就該怎么顯示怎么顯示枕稀。
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
指令
說(shuō)一下vue常用的內(nèi)置指令
1询刹、v-bind:響應(yīng)并更新DOM特性;例如:v-bind:href v-bind:class v-bind:title v-bind:bb
2萎坷、v-on:用于監(jiān)聽(tīng)DOM事件; 例如:v-on:click v-on:keyup
3食铐、v-model:數(shù)據(jù)雙向綁定斟叼;用于表單輸入等绑改;例如:<input v-model="message">
4谢床、v-show:條件渲染指令,為DOM設(shè)置css的style屬性
5厘线、v-if:條件渲染指令识腿,動(dòng)態(tài)在DOM內(nèi)添加或刪除DOM元素
6、v-else:條件渲染指令造壮,必須跟v-if成對(duì)使用
7渡讼、v-for:循環(huán)指令;例如:<li v-for="(item,index) in todos"></li>
8耳璧、v-else-if:判斷多層條件成箫,必須跟v-if成對(duì)使用;
9旨枯、v-text:更新元素的textContent蹬昌;例如:<span v-text="msg"></span> 等同于 <span>{{msg}}</span>;
10攀隔、v-html:更新元素的innerHTML凳厢;
11账胧、v-pre:不需要表達(dá)式,跳過(guò)這個(gè)元素以及子元素的編譯過(guò)程先紫,以此來(lái)加快整個(gè)項(xiàng)目的編譯速度治泥;例如:<span v-pre>{{ this will not be compiled }}</span>;
12遮精、v-cloak:不需要表達(dá)式居夹,這個(gè)指令保持在元素上直到關(guān)聯(lián)實(shí)例結(jié)束編譯;
13本冲、v-once:不需要表達(dá)式准脂,只渲染元素或組件一次,隨后的渲染檬洞,組件/元素以及下面的子元素都當(dāng)成靜態(tài)頁(yè)面不在渲染狸膏。
如何注冊(cè)自定義指令
使用Vue.directive(id,definition)注冊(cè)全局自定義指令,接收兩個(gè)參數(shù)添怔,指令I(lǐng)D以及定義對(duì)象湾戳。使用組件的directives選項(xiàng)注冊(cè)局部自定義指令。
自定義指令的鉤子函數(shù)
一個(gè)指令定義對(duì)象可以提供如下幾個(gè)鉤子函數(shù) (均為可選):
bind:只調(diào)用一次广料,指令第一次綁定到元素時(shí)調(diào)用砾脑。在這里可以進(jìn)行一次性的初始化設(shè)置。
inserted:被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用 (僅保證父節(jié)點(diǎn)存在艾杏,但不一定已被插入文檔中)韧衣。
update:所在組件的 VNode 更新時(shí)調(diào)用,但是可能發(fā)生在其子 VNode 更新之前购桑。指令的值可能發(fā)生了改變畅铭,也可能沒(méi)有。但是你可以通過(guò)比較更新前后的值來(lái)忽略不必要的模板更新 (詳細(xì)的鉤子函數(shù)參數(shù)見(jiàn)下)勃蜘。componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后調(diào)用顶瞒。
unbind:只調(diào)用一次,指令與元素解綁時(shí)調(diào)用元旬。
拓展:自定義指令(VUE官網(wǎng))
https://cn.vuejs.org/v2/guide/custom-directive.html#ad
v-model是什么榴徐?
v-model是用于表單的據(jù)雙向綁定的指令
如何自己去實(shí)現(xiàn)一個(gè)v-model數(shù)據(jù)綁定?
兩個(gè)步驟:
v-bind 綁定了一個(gè)value的屬性
-
v-on 把當(dāng)前元素綁定到了一個(gè)事件上
<template> <div class="logs"> logs!!! <p><input type="text" v-model="msg"></p> <p>{{msg}}</p> <hr> <p><input type="text" :value="msg2" @input="msg2 = $event.target.value"></p> <p>{{msg2}}</p> </div> </template> <script> export default { name:"logs", data(){ return { msg:"helloworld", msg2:"" } } } </script>
v-if和v-show的區(qū)別
v-if 是“真正”的條件渲染匀归,因?yàn)樗鼤?huì)確保在切換過(guò)程中條件塊內(nèi)的事件監(jiān)聽(tīng)器和子組件適當(dāng)?shù)乇讳N(xiāo)毀和重建坑资。 v-if 也是惰性的:如果在初始渲染時(shí)條件為假,則什么也不做——直到條件第一次變?yōu)檎鏁r(shí)穆端,才會(huì)開(kāi)始渲染條件塊袱贮。 相比之下,v-show 就簡(jiǎn)單得多——不管初始條件是什么体啰,元素總是會(huì)被渲染攒巍,并且只是簡(jiǎn)單地基于 CSS 進(jìn)行切換嗽仪。 一般來(lái)說(shuō),v-if 有更高的切換開(kāi)銷(xiāo)柒莉,而 v-show 有更高的初始渲染開(kāi)銷(xiāo)闻坚。因此,如果需要非常頻繁地切換兢孝,則使用 v-show 較好窿凤;如果在運(yùn)行時(shí)條件很少改變,則使用 v-if 較好跨蟹。
路由守衛(wèi)
講一下都有哪些路由守衛(wèi)雳殊?
全局前置守衛(wèi):router.beforeEach 在路由切換開(kāi)始時(shí)候調(diào)用
全局后置守衛(wèi):roter.afterEach 在路由切換離開(kāi)時(shí)候調(diào)用
局部路由守衛(wèi):beforeEnter 寫(xiě)在路由對(duì)象里
組件內(nèi)的守衛(wèi):
beforeRouteEnter 路由進(jìn)入到這個(gè)組件之前調(diào)用,不能獲取當(dāng)前組件對(duì)象 this
beforeRouteUpdate 在組件被復(fù)用時(shí)調(diào)用
beforeRouteLeave 路由離開(kāi)這個(gè)組件之后調(diào)用窗轩,能獲取當(dāng)前組件對(duì)象 this
路由守衛(wèi)中的參數(shù)都是什么意思
每個(gè)鉤子方法接收三個(gè)參數(shù):
- to: Route: 即將要進(jìn)入的目標(biāo)夯秃,路由對(duì)象
- from: Route: 當(dāng)前導(dǎo)航正要離開(kāi)的路由
- next: Function: 一定要調(diào)用該方法來(lái) resolve 這個(gè)鉤子。執(zhí)行效果依賴 next 方法的調(diào)用參數(shù)痢艺。
- next(): 進(jìn)行管道中的下一個(gè)鉤子仓洼。如果全部鉤子執(zhí)行完了,則導(dǎo)航的狀態(tài)就是 confirmed (確認(rèn)的)腹备。
- next(false): 中斷當(dāng)前的導(dǎo)航衬潦。如果瀏覽器的 URL 改變了(可能是用戶手動(dòng)或者瀏覽器后退按鈕)斤蔓,那么 URL 地址會(huì)重置到 from 路由對(duì)應(yīng)的地址植酥。
- next(‘/’) 或者 next({ path: ‘/’ }): 跳轉(zhuǎn)到一個(gè)不同的地址。當(dāng)前的導(dǎo)航被中斷弦牡,然后進(jìn)行一個(gè)新的導(dǎo)航友驮。
確保要調(diào)用 next 方法,否則鉤子就不會(huì)被 resolved驾锰。
具體說(shuō)一下每個(gè)路由守衛(wèi)的功能
導(dǎo)航守衛(wèi)(路由鉤子/路由守衛(wèi)/導(dǎo)航守衛(wèi)/導(dǎo)航鉤子/路由生命周期)
正如其名卸留,
vue-router
提供的導(dǎo)航守衛(wèi)主要用來(lái)通過(guò)跳轉(zhuǎn)或取消的方式守衛(wèi)導(dǎo)航。有多種機(jī)會(huì)植入路由導(dǎo)航過(guò)程中:全局的椭豫,單個(gè)路由獨(dú)享的,耻瑟,或者組件級(jí)的。
在某些情況下赏酥,當(dāng)路由跳轉(zhuǎn)前或跳轉(zhuǎn)后喳整、進(jìn)入、離開(kāi)某一個(gè)路由前裸扶、后框都,需要做某些操作,就可以使用路由鉤子來(lái)監(jiān)聽(tīng)路由的變化呵晨。
全局守衛(wèi)
(1)全局前置守衛(wèi)beforeEach
當(dāng)一個(gè)導(dǎo)航觸發(fā)時(shí)魏保,全局前置守衛(wèi)按照創(chuàng)建順序調(diào)用熬尺。守衛(wèi)是異步解析執(zhí)行,此時(shí)導(dǎo)航在所有守衛(wèi) resolve 完之前一直處于 等待中谓罗,所以頁(yè)面不會(huì)加載任何內(nèi)容粱哼。
一定要在路由守衛(wèi)中調(diào)用next()方法來(lái)resolve這個(gè)鉤子
// 全局前置路由
router.beforeEach((to,from,next)=>{
console.log("beforeEach:全局前置守衛(wèi)")
// 一定要調(diào)用next()方法來(lái)resolve這個(gè)鉤子
next();
})
(2)全局后置守衛(wèi)afterEach
也可以注冊(cè)全局后置鉤子,然而和前置守衛(wèi)不同的是妥衣,這些鉤子不會(huì)接受 next
函數(shù)也不會(huì)改變導(dǎo)航本身:
// 全局后置鉤子
router.afterEach((to,from)=>{
if (to.path === "/list/audio") {
alert("已經(jīng)進(jìn)入list列表audio頁(yè)面")
}
})
局部守衛(wèi)
路由獨(dú)享的守衛(wèi)
在路由配置上直接定義beforeEnter守衛(wèi):
{ path :"/mine",component:()=>import("../views/Mine"),beforeEnter(to,from,next){
console.log("進(jìn)入到mine頁(yè)面了")
next();
}}
組件內(nèi)的守衛(wèi)
最后皂吮,你可以在路由組件內(nèi)直接定義以下路由導(dǎo)航守衛(wèi):
-
beforeRouteEnter
在進(jìn)入該組件之前執(zhí)行,該路由守衛(wèi)中獲取不到實(shí)例this税手,因?yàn)榇藭r(shí)組件實(shí)例還沒(méi)被創(chuàng)建蜂筹。
beforeRouteEnter
守衛(wèi) 不能 訪問(wèn)this
,因?yàn)槭匦l(wèi)在導(dǎo)航確認(rèn)前被調(diào)用,因此即將登場(chǎng)的新組件還沒(méi)被創(chuàng)建芦倒。在Home.vue中添加beforeRouteEnter:
beforeRouteEnter(to,from,next){ console.log("beforeRouteEnter:進(jìn)入組件之前",this) next() }
打印this艺挪,顯示undefined
image不過(guò),你可以通過(guò)傳一個(gè)回調(diào)給
next
來(lái)訪問(wèn)組件實(shí)例兵扬。在導(dǎo)航被確認(rèn)的時(shí)候執(zhí)行回調(diào)麻裳,并且把組件實(shí)例作為回調(diào)方法的參數(shù)。beforeRouteEnter (to, from, next) { next(vm => { // 通過(guò) `vm` 訪問(wèn)組件實(shí)例 }) }
注意
beforeRouteEnter
是支持給next
傳遞回調(diào)的唯一守衛(wèi)器钟。對(duì)于beforeRouteUpdate
和beforeRouteLeave
來(lái)說(shuō)津坑,this
已經(jīng)可用了,所以不支持傳遞回調(diào)傲霸,因?yàn)闆](méi)有必要了疆瑰。
-
beforeRouteLeave
在離開(kāi)該組件之前執(zhí)行,該路由守衛(wèi)中可以訪問(wèn)組件實(shí)例"this"昙啄。
在Home.vue中添加beforeRouteLeave:
beforeRouteLeave(to,from,next){ console.log("beforeRouteLeave:離開(kāi)組件之前",this) next() }
此時(shí)可以打印組件實(shí)例"this"
image這個(gè)離開(kāi)守衛(wèi)通常用來(lái)禁止用戶在還未保存修改前突然離開(kāi)穆役。該導(dǎo)航可以通過(guò)
next(false)
來(lái)取消。
-
beforeRouteUpdate(2.2 新增)
當(dāng)一個(gè)組件被重復(fù)調(diào)用的時(shí)候執(zhí)行該守衛(wèi)
在Deatil.vue中添加beforeRouteUpdate:
beforeRouteUpdate(to,from,next){ console.log("beforeRouteUpdate") next() }
image
在vue項(xiàng)目中哪里用到過(guò)路由守衛(wèi)梳凛?舉一個(gè)使用到路由守衛(wèi)的案例
我們想實(shí)現(xiàn)當(dāng)路由變化的時(shí)候頭部信息動(dòng)態(tài)更改耿币,我們先把內(nèi)容寫(xiě)成這種樣式:
template中:
<div class = "left">
<i :class = "['fa','fa-' + icon]"></i>
<span>{{title}}</span>
</div>
data中:
data(){
return{
icon:"home",
title:"豆瓣首頁(yè)",
}
},
這時(shí)候就需要用到路由守衛(wèi),當(dāng)路由切換的時(shí)候可以做一些業(yè)務(wù)邏輯韧拒,首先需要引入全局路由
import router from "@/router"
在全局前置路由守衛(wèi)router.beforeEach中淹接,使用switch語(yǔ)句來(lái)匹配,根據(jù)路由name屬性來(lái)設(shè)置對(duì)應(yīng)的title和icon:
created(){
router.beforeEach((to,from,next)=>{
switch(to.name){
case "home":
this.title = "豆瓣首頁(yè)"
this.icon = "home"
break;
case "audio":
this.title = "豆瓣影音"
this.icon = "audio-description"
break;
case "broadcast":
this.title = "豆瓣廣播"
this.icon = "caret-square-o-left"
break;
case "group":
this.title = "豆瓣小組"
this.icon = "group"
break;
case "mine":
this.title = "豆瓣我的"
this.icon = "cog"
break;
default:
break;
}
next();
})
}
路由
什么是SPA單頁(yè)應(yīng)用叛溢?你怎么理解單頁(yè)應(yīng)用塑悼?
現(xiàn)在的應(yīng)用都流行SPA(single page application),傳統(tǒng)的項(xiàng)目大多使用多頁(yè)面結(jié)構(gòu)雇初,需要切換內(nèi)容的時(shí)候我們往往會(huì)進(jìn)行單個(gè)html文件的跳轉(zhuǎn)拢肆,這個(gè)時(shí)候受網(wǎng)絡(luò)、性能影響,瀏覽器會(huì)出現(xiàn)不定時(shí)間的空白界面郭怪,用戶體驗(yàn)不好支示。
單頁(yè)面應(yīng)用就是用戶通過(guò)某些操作更改地址欄url之后,動(dòng)態(tài)地進(jìn)行不同模板內(nèi)容的無(wú)刷新切換,用戶體驗(yàn)好。
單頁(yè)應(yīng)用的優(yōu)點(diǎn)
- 更好的用戶體驗(yàn)冰木,讓用戶在web感受natvie的速度和流暢溪北;
- 經(jīng)典MVC開(kāi)發(fā)模式趟畏,前后端各負(fù)其責(zé)。
- 一套Server API,多端使用(web、移動(dòng)APP等)
- 重前端栽渴,業(yè)務(wù)邏輯全部在本地操作,數(shù)據(jù)都需要通過(guò)AJAX同步稳懒、提交闲擦;
Vue切換路由的方法?vue-router的原理场梆?
Vue中會(huì)使用官方提供的vue-router插件來(lái)使用單頁(yè)面墅冷,原理就是通過(guò)檢測(cè)地址欄變化后將對(duì)應(yīng)的路由組件進(jìn)行切換(卸載和安裝)。
- 引入vue-router或油,如果是在腳手架中寞忿,引入VueRouter之后,需要通過(guò)Vue.use來(lái)注冊(cè)插件
- 創(chuàng)建router路由器
- 創(chuàng)建路由表并配置在路由器中
- 在根實(shí)例里注入router,目的是為了讓所有的組件里都能通過(guò)this.$router/route來(lái)使用路由的相關(guān)功能api
- 利用router-view來(lái)指定路由切換的位置
- 使用router-link來(lái)創(chuàng)建切換的工具顶岸,默認(rèn)會(huì)渲染成a標(biāo)簽腔彰,添加to屬性來(lái)設(shè)置要更改的path信息,且會(huì)根據(jù)當(dāng)前路由的變化為a標(biāo)簽添加對(duì)應(yīng)的router-link-active/router-link-exact-active(完全匹配成功)類(lèi)名蜕琴。
router-link標(biāo)簽的屬性
<router-link> 組件支持用戶在具有路由功能的應(yīng)用中(點(diǎn)擊)導(dǎo)航萍桌。 通過(guò) to 屬性指定目標(biāo)地址宵溅,默認(rèn)渲染成帶有正確鏈接的 標(biāo)簽凌简,可以通過(guò)配置 tag 屬性生成別的標(biāo)簽。另外恃逻,當(dāng)目標(biāo)路由成功激活時(shí)雏搂,鏈接元素自動(dòng)設(shè)置一個(gè)表示激活的 CSS 類(lèi)名。
to
router-link的to屬性寇损,默認(rèn)寫(xiě)的是path(路由的路徑)凸郑,可以通過(guò)設(shè)置一個(gè)對(duì)象,來(lái)匹配更多矛市。
<router-link tag = "li" :to = "{name:'detail',params:{id:'1'},query:{title:'最近播放'}}">我的歌單</router-link>
name
name是要跳轉(zhuǎn)的路由的名字芙沥,也可以寫(xiě)path來(lái)指定路徑,但是用path的時(shí)候就不能使用params傳參,params是傳路由參數(shù)而昨,query傳queryString參數(shù)救氯。
replace
路由跳轉(zhuǎn)到不同的url默認(rèn)是push的過(guò)程,當(dāng)用戶點(diǎn)擊瀏覽器后退按鈕式時(shí)歌憨,則回到之前url着憨,replace屬性可以控制router-link的跳轉(zhuǎn)不被記錄。
依次點(diǎn)擊首頁(yè)——列表——音頻——視頻——我的务嫡,點(diǎn)擊返回按鈕時(shí)甲抖,依次返回之前的url。
在List.vue的<router-link>標(biāo)簽中添加replace屬性心铃,則該標(biāo)簽內(nèi)的跳轉(zhuǎn)不會(huì)被記錄
<router-link
v-for = "nav in navs"
:key = "nav.id"
:to = "{name:nav.name}"
active-class = "title"
replace
>
{{nav.title}}
</router-link>
再依次點(diǎn)擊首頁(yè)——列表——音頻——視頻——我的准谚,點(diǎn)擊返回按鈕時(shí),可以看到從音頻——視頻之間的跳轉(zhuǎn)沒(méi)有被記錄去扣。
active-class
<router-link>且會(huì)根據(jù)當(dāng)前路由的變化為a標(biāo)簽添加對(duì)應(yīng)的router-link-active/router-link-exact-active(完全匹配成功)類(lèi)名氛魁,我們可以通過(guò)它來(lái)為標(biāo)簽設(shè)置不同的選中樣式。
<style lang="scss">
.router-link-active{
color:blue;
}
.router-link-exact-active{
color:red;
font-weight:900;
}
</style>
標(biāo)簽切換時(shí)厅篓,選中狀態(tài)的顯示效果:
還可以通過(guò)<router-link>的active-class屬性給a標(biāo)簽添加指定一個(gè)activeClass名秀存,通過(guò)設(shè)置這個(gè)class的樣式,來(lái)設(shè)置標(biāo)簽選中時(shí)的狀態(tài)羽氮,功能類(lèi)似于router-link-exact-active或链。
<router-link
v-for = "nav in navs"
:key = "nav.id"
:to = "nav.path"
active-class = "title"
>
{{nav.title}}
</router-link>
設(shè)置.title樣式
<style lang = "scss" scoped>
.title{
color:aquamarine;
}
</style>
顯示效果:
tag
<router-link>默認(rèn)渲染成帶有正確鏈接的a標(biāo)簽,可以通過(guò)配置 tag 屬性生成別的標(biāo)簽档押。
<ul>
<router-link tag = "li">我的歌單</router-link>
<router-link tag = "li">最近播放</router-link>
</ul>
路由跳轉(zhuǎn)的方式
<router-link> 組件支持用戶在具有路由功能的應(yīng)用中(點(diǎn)擊)導(dǎo)航澳盐。 通過(guò) to 屬性指定目標(biāo)地址,默認(rèn)渲染成帶有正確鏈接的a標(biāo)簽令宿,可以通過(guò)配置 tag 屬性生成別的標(biāo)簽叼耙。另外,當(dāng)目標(biāo)路由成功激活時(shí)粒没,鏈接元素自動(dòng)設(shè)置一個(gè)表示激活的 CSS 類(lèi)名筛婉。
-
編程式導(dǎo)航:this.$router.replace
This.$router.go
一級(jí)路由的實(shí)現(xiàn)
-
如果不是使用腳手架創(chuàng)建的項(xiàng)目,需要手動(dòng)安裝vue-router路由模塊癞松。
cnpm install vue-router -S
-
引入vue-router爽撒,如果是在腳手架中,引入VueRouter之后响蓉,需要通過(guò)Vue.use來(lái)注冊(cè)插件硕勿。
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router)//讓vue可以使用vue-router插件
注冊(cè)vue-router插件之后,this上就有了$route/router屬性枫甲。
-
創(chuàng)建router路由器源武,并導(dǎo)出扼褪。
let router = new Router({ routes:[ ] }) export default router;
-
在根實(shí)例里注入router
new Vue({ //掛載router router,//為了可以讓組件使用this.$route,this.$router的一些api屬性或者方法 store, render: h => h(App) }).$mount('#app')
此時(shí)組件可以通過(guò)this.$router/router來(lái)使用路由相關(guān)功能的api。
image -
創(chuàng)建router路由表
let router = new Router({ routes:[ { path:"/home",component:Home }, { path: "/list", component: List }, { path: "/mine", component: Mine } ] })
-
在App.vue中利用router-view來(lái)指定路由切換的位置
<template> <div id="app"> Hello app.vue! <!-- 顯示路由組件的位置 --> <router-view></router-view> </div> </template>
路由切換效果:
image -
使用router-link來(lái)創(chuàng)建切換路由的工具
<div> <router-link to = "/home">首頁(yè)</router-link> <router-link to = "/list">列表</router-link> <router-link to = "/mine">我的</router-link> </div>
image<router-link>會(huì)渲染成a標(biāo)簽粱栖,添加to屬性來(lái)設(shè)置要更改的path信息
image
二級(jí)路由(路由嵌套)
在創(chuàng)建路由表的時(shí)候迎捺,可以為每一個(gè)路由對(duì)象創(chuàng)建children屬性,值為數(shù)組查排,在這個(gè)里面又可以配置一些路由對(duì)象來(lái)使用多級(jí)路由凳枝,注意:一級(jí)路由path前加'/',二級(jí)路由前不需要加'/'跋核。
{ path :"/list",component:()=>import("../views/List"),children:[
// 二級(jí)路由前不需要加“/”
{ path: "audio", component: () => import("../views/Audio") },
{ path: "video", component: () => import("../views/Video") }
]}
二級(jí)路由組件的切換位置依然由router-view來(lái)指定(指定在父級(jí)路由組件的模板中)岖瑰。
動(dòng)態(tài)路由
在router路由表中配置動(dòng)態(tài)路由,下面的代碼就是給detail路由配置接收id的參數(shù)砂代,多個(gè)參數(shù)繼續(xù)在后面設(shè)置蹋订。
// 配置動(dòng)態(tài)路由
{ path:"/detail/:id",component:()=>import("../views/Detail.vue")}
在頁(yè)面中通過(guò)<router-link>的to屬性傳遞參數(shù):
<ul>
<router-link tag = "li" to = "/detail/1">我的歌單</router-link>
<router-link tag = "li" to = "/detail/2">最近播放</router-link>
</ul>
在Detail.vue中打印this.$route.params.id
export default {
created(){
//獲取動(dòng)態(tài)路由傳遞過(guò)來(lái)的參數(shù)
console.log(this.$route.params.id)
}
}
在頁(yè)面中通過(guò)$route.params.id渲染獲取到的動(dòng)態(tài)id
<template>
<div class = "detail">
我是詳情頁(yè),我的動(dòng)態(tài)id是:{{$route.params.id}}
</div>
</template>
一個(gè)vue組件中能有多個(gè)router-view嗎?為什么
有時(shí)候想同時(shí) (同級(jí)) 展示多個(gè)視圖刻伊,而不是嵌套展示露戒,例如創(chuàng)建一個(gè)布局,有 sidebar
(側(cè)導(dǎo)航) 和 main
(主內(nèi)容) 兩個(gè)視圖捶箱,這個(gè)時(shí)候命名視圖就派上用場(chǎng)了智什。你可以在界面中擁有多個(gè)單獨(dú)命名的視圖,而不是只有一個(gè)單獨(dú)的出口丁屎。如果 router-view
沒(méi)有設(shè)置名字荠锭,那么默認(rèn)為 default
。
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
一個(gè)視圖使用一個(gè)組件渲染晨川,因此對(duì)于同個(gè)路由证九,多個(gè)視圖就需要多個(gè)組件。確保正確使用 components
配置 (帶上 s):
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
參考:命名識(shí)圖(VUE官網(wǎng))
Vue路由傳參有幾種方式
路由參數(shù)
在router路由表中配置動(dòng)態(tài)路由共虑,下面的代碼就是給detail路由配置接收id的參數(shù)愧怜,多個(gè)參數(shù)繼續(xù)在后面設(shè)置。
// 配置動(dòng)態(tài)路由
{ path:"/detail/:id",component:()=>import("../views/Detail.vue")}
在頁(yè)面中通過(guò)<router-link>的to屬性傳遞參數(shù):
<ul>
<router-link tag = "li" to = "/detail/1">我的歌單</router-link>
<router-link tag = "li" to = "/detail/2">最近播放</router-link>
</ul>
在Detail.vue中打印this.$route.params.id
export default {
created(){
//獲取動(dòng)態(tài)路由傳遞過(guò)來(lái)的參數(shù)
console.log(this.$route.params.id)
}
}
在頁(yè)面中通過(guò)$route.params.id渲染獲取到的動(dòng)態(tài)id
<template>
<div class = "detail">
我是詳情頁(yè),我的動(dòng)態(tài)id是:{{$route.params.id}}
</div>
</template>
queryString參數(shù)
queryString參數(shù)不需要在路由表設(shè)置接收妈拌,直接設(shè)置拥坛?后面的內(nèi)容:
<ul>
<router-link tag = "li" to = "/detail/1?title=我的歌單">我的歌單</router-link>
<router-link tag = "li" to = "/detail/2?title=最近播放">最近播放</router-link>
</ul>
在路由組件中通過(guò)this.$route.query接收
export default {
created(){
//獲取動(dòng)態(tài)路由傳遞過(guò)來(lái)的參數(shù)
console.log(this.$route.params.id,this.$route.query.title)
}
}
打印結(jié)果:
頁(yè)面渲染效果:
上面的參數(shù)傳遞也可以寫(xiě)成對(duì)象的形式:
<!-- 寫(xiě)成對(duì)象的形式 -->
<router-link tag = "li" :to = "{path:'/detail/2',query:{title:'最近播放'}}">最近播放</router-link>
通過(guò)prop將路由與組件解耦
在組件中接收路由參數(shù)需要this.$route.params.id,代碼冗余供炎,現(xiàn)在可以在路由表里配置props:true渴逻。
{ path:"/detail/:id",component:()=>import("../views/Detail.vue"),name:"detail",props:true}
在路由組件中可以通過(guò)props接收id參數(shù)去使用
props:["id"],
在頁(yè)面中就可以通過(guò){{id}}的方式來(lái)使用路由傳遞的參數(shù)
我的動(dòng)態(tài)id是:{{id}}
路由模式
為了構(gòu)建SPA(單頁(yè)面應(yīng)用)疾党,需要引入前端路由系統(tǒng)音诫,這也就是Vue-router存在的意義。前端路由的核心雪位,就在于:改變視圖的同時(shí)不會(huì)向后端發(fā)出請(qǐng)求竭钝。
hash和history這兩個(gè)方法應(yīng)用于瀏覽器的歷史記錄站,在當(dāng)前已有的back、forward香罐、go 的基礎(chǔ)之上卧波,它們提供了對(duì)歷史記錄進(jìn)行修改的功能。只是當(dāng)它們執(zhí)行修改是庇茫,雖然改變了當(dāng)前的URL港粱,但你瀏覽器不會(huì)立即向后端發(fā)送請(qǐng)求。
hash:即地址欄URL中的#符號(hào)(此hsah 不是密碼學(xué)里的散列運(yùn)算)
路由有兩種模式:hash旦签、history查坪,默認(rèn)會(huì)使用hash模式
比如這個(gè)URL:http://www.baidu.com/#/hello, hash 的值為#/hello宁炫。它的特點(diǎn)在于:hash 雖然出現(xiàn)URL中偿曙,但不會(huì)被包含在HTTP請(qǐng)求中,對(duì)后端完全沒(méi)有影響羔巢,因此改變hash不會(huì)重新加載頁(yè)面望忆。
history:利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法。(需要特定瀏覽器支持)
如果url里不想出現(xiàn)丑陋hash值(#)竿秆,在new VueRouter的時(shí)候配置mode值為history來(lái)改變路由模式启摄,本質(zhì)使用H5的histroy.pushState方法來(lái)更改url,不會(huì)引起刷新幽钢。
// 默認(rèn)會(huì)使用hash模式
mode:"history",
history模式鞋仍,會(huì)出現(xiàn)404 的情況,需要后臺(tái)配置搅吁。
hash模式和history模式在發(fā)生404錯(cuò)誤時(shí):
-
hash模式下威创,僅hash符號(hào)之前的內(nèi)容會(huì)被包含在請(qǐng)求中,當(dāng)用戶訪問(wèn)https://www.baidu.com/#/home時(shí)實(shí)際請(qǐng)求的是:https://www.baidu.com/谎懦。因此對(duì)于后端來(lái)說(shuō)肚豺,即使沒(méi)有做到對(duì)路由的全覆蓋,頁(yè)面也不會(huì)返回404錯(cuò)誤界拦;
image -
history模式下吸申,前端的url必須和實(shí)際向后端發(fā)起請(qǐng)求的url 一致,因?yàn)槲覀兊膽?yīng)用是個(gè)單頁(yè)客戶端應(yīng)用享甸,如果后臺(tái)沒(méi)有正確的配置截碴,當(dāng)用戶在瀏覽器直接訪問(wèn) https://www.baidu.com/home/detail,缺少對(duì)/home/detail的路由處理蛉威,就會(huì)返回 404錯(cuò)誤日丹,這就不好看了。
image
所以呢蚯嫌,你要在服務(wù)端增加一個(gè)覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源哲虾,則應(yīng)該返回同一個(gè) index.html 頁(yè)面丙躏,這個(gè)頁(yè)面就是你 app 依賴的頁(yè)面。
hash哈希路由的原理
window.onload = function(){
//當(dāng)hash發(fā)生變化的時(shí)候束凑, 會(huì)產(chǎn)生一個(gè)事件 onhashchange
window.onhashchange = function(){
console.log( '你的hash改變了' );
//location對(duì)象是 javascript內(nèi)置的(自帶的)
console.log( location );
}
}
上例晒旅,我們已經(jīng)通過(guò)hash( 就是錨文本 ) 變化, 觸發(fā)了onhashchange事件汪诉, 就可以把hash變化與內(nèi)容切換對(duì)應(yīng)起來(lái)废恋,就實(shí)現(xiàn)了單頁(yè)路由的應(yīng)用!
監(jiān)控hash值變化扒寄,hash一旦變化拴签,頁(yè)面內(nèi)容變化,實(shí)現(xiàn)無(wú)刷新切換旗们。
參考:js單頁(yè)hash路由原理與應(yīng)用實(shí)戰(zhàn)
https://www.cnblogs.com/ghostwu/p/7357381.html
路由的懶加載
當(dāng)打包構(gòu)建應(yīng)用時(shí)蚓哩,JavaScript 包會(huì)變得非常大较剃,影響頁(yè)面加載隘谣。如果我們能把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被訪問(wèn)的時(shí)候才加載對(duì)應(yīng)組件篷扩,這樣就更加高效了稠氮。結(jié)合 Vue 的異步組件和 Webpack 的代碼分割功能曹阔,輕松實(shí)現(xiàn)路由組件的懶加載。
懶加載也叫延遲加載隔披,即在需要的時(shí)候進(jìn)行加載赃份,隨用隨載。在單頁(yè)應(yīng)用中奢米,如果沒(méi)有應(yīng)用懶加載抓韩,運(yùn)用webpack打包后的文件將會(huì)異常的大,造成進(jìn)入首頁(yè)時(shí)鬓长,需要加載的內(nèi)容過(guò)多谒拴,延時(shí)過(guò)長(zhǎng),會(huì)出現(xiàn)長(zhǎng)時(shí)間的白屏涉波,即使做了loading也是不利于用戶體驗(yàn)英上,而運(yùn)用懶加載則可以將頁(yè)面進(jìn)行劃分,需要的時(shí)候加載頁(yè)面啤覆,可以有效的分擔(dān)首頁(yè)所承擔(dān)的加載壓力苍日,減少首頁(yè)加載用時(shí)。簡(jiǎn)單的說(shuō)就是:進(jìn)入首頁(yè)時(shí)不用一次加載過(guò)多資源窗声,造成頁(yè)面加載用時(shí)過(guò)長(zhǎng)相恃。
懶加載寫(xiě)法:
// 路由的懶加載方式
{ path :"/home",component:()=>import("../views/Home")},// 當(dāng)我訪問(wèn)/home首頁(yè)時(shí),頁(yè)面才去加載Home組件嫌佑,減少首頁(yè)加載的時(shí)長(zhǎng)
{ path :"/list",component:()=>import("../views/List")},
{ path :"/mine",component:()=>import("../views/Mine")}
非按需加載則會(huì)把所有的路由組件塊的js包打在一起豆茫。當(dāng)業(yè)務(wù)包很大的時(shí)候建議用路由的按需加載(懶加載)侨歉。 按需加載會(huì)在頁(yè)面第一次請(qǐng)求的時(shí)候屋摇,把相關(guān)路由組件塊的js添加上揩魂。
參考:路由的懶加載(VUE官網(wǎng))
https://router.vuejs.org/zh/guide/advanced/lazy-loading.html
通過(guò)正則匹配路由
// The matching uses path-to-regexp, which is the matching engine used
// by express as well, so the same matching rules apply.
// For detailed rules, see https://github.com/pillarjs/path-to-regexp
const router = new VueRouter({
mode: 'history',
base: __dirname,
routes: [
{ path: '/' },
// params are denoted with a colon ":"
{ path: '/params/:foo/:bar' },
// a param can be made optional by adding "?"
{ path: '/optional-params/:foo?' },
// a param can be followed by a regex pattern in parens
// this route will only be matched if :id is all numbers
{ path: '/params-with-regex/:id(\\d+)' },
// asterisk can match anything
{ path: '/asterisk/*' },
// make part of th path optional by wrapping with parens and add "?"
{ path: '/optional-group/(foo/)?bar' }
]
})
官方例子github地址:https://github.com/vuejs/vue-router/blob/next/examples/route-matching/app.js
Vuex
什么是Vuex?
vuex是一個(gè)專(zhuān)門(mén)為vue構(gòu)建的狀態(tài)集管理工具炮温,vue和react都是基于組件化開(kāi)發(fā)的火脉,項(xiàng)目中包含很多的組件,組件都會(huì)有組件嵌套柒啤,想讓組件中的數(shù)據(jù)被其他組件也可以訪問(wèn)到就需要使用到Vuex倦挂。
Vuex主要解決了什么問(wèn)題?
Vuex主要是為了解決多組件之間狀態(tài)共享問(wèn)題担巩,它強(qiáng)調(diào)的是集中式管理(組件與組件之間的關(guān)系變成了組件與倉(cāng)庫(kù)之間的關(guān)系)把數(shù)據(jù)都放在一個(gè)倉(cāng)庫(kù)中管理方援,使用數(shù)據(jù)的時(shí)候直接從倉(cāng)庫(kù)中獲取,如果倉(cāng)庫(kù)中一個(gè)數(shù)據(jù)改變了涛癌, 那么所有使用這個(gè)數(shù)據(jù)的組件都會(huì)更新犯戏。Vuex把組件與組件之間的關(guān)系解耦成組件與倉(cāng)庫(kù)之間的關(guān)系,方便數(shù)據(jù)維護(hù)拳话。
Vuex的流程先匪?Vuex的核心?
(1)將需要共享的狀態(tài)掛載到state上:this.$store.state來(lái)調(diào)用
創(chuàng)建store弃衍,將狀態(tài)掛載到state上呀非,在根實(shí)例里面配置store,之后我們?cè)诮M件中就可以通過(guò)this.$store.state來(lái)使用state中管理的數(shù)據(jù)镜盯,但是這樣使用時(shí)岸裙,當(dāng)state的數(shù)據(jù)更改的時(shí)候,vue組件并不會(huì)重新渲染速缆,所以我們要通過(guò)計(jì)算屬性computed來(lái)使用哥桥,但是當(dāng)我們使用多個(gè)數(shù)據(jù)的時(shí)候這種寫(xiě)法比較麻煩,vuex提供了mapState輔助函數(shù)激涤,幫助我們?cè)诮M件中獲取并使用vuex的store中保存的狀態(tài)拟糕。
(2)我們通過(guò)getters來(lái)創(chuàng)建狀態(tài):通過(guò)this.$store.getters來(lái)調(diào)用
可以根據(jù)某一個(gè)狀態(tài)派生出一個(gè)新?tīng)顟B(tài),vuex也提供了mapGetters輔助函數(shù)來(lái)幫助我們?cè)诮M件中使用getters里的狀態(tài)倦踢。
(3)使用mutations來(lái)更改state:通過(guò)this.$store.commit來(lái)調(diào)用
我們不能直接在組件中更改state送滞,而是需要使用mutations來(lái)更改,mutations也是一個(gè)純對(duì)象辱挥,里面包含很多更改state的方法犁嗅,這些方法的形參接收到state,在函數(shù)體里更改晤碘,這時(shí)褂微,組件用到的數(shù)據(jù)也會(huì)更改功蜓,實(shí)現(xiàn)響應(yīng)式。vuex提供了mapMutations方法來(lái)幫助我們?cè)诮M件中調(diào)用mutations 的方法宠蚂。
(4)使用actions來(lái)處理異步操作:this.$store.dispatch來(lái)調(diào)用
Actions類(lèi)似于mutations式撼,不同在于:Actions提交的是mutations,而不是直接變更狀態(tài)求厕。Actions可以包含任意異步操作著隆。也就是說(shuō),如果有這樣的需求:在一個(gè)異步操作處理之后呀癣,更改狀態(tài)美浦,我們?cè)诮M件中應(yīng)該先調(diào)用actions,來(lái)進(jìn)行異步動(dòng)作项栏,然后由actions調(diào)用mutations來(lái)更改數(shù)據(jù)浦辨。在組件中通過(guò)this.$store.dispatch方法調(diào)用actions的方法,當(dāng)然也可以使用mapMutations來(lái)輔助使用沼沈。
簡(jiǎn)便版流程:
組件使用數(shù)據(jù)且通過(guò)異步動(dòng)作更改數(shù)據(jù)的一系列事情:
1.生成store,設(shè)置state
2.在根實(shí)例中注入store
3.組件通過(guò)計(jì)算屬性或者mapState來(lái)使用狀態(tài)
4.用戶產(chǎn)生操作流酬,調(diào)用actions的方法,然后進(jìn)行異步動(dòng)作
5.異步動(dòng)作之后庆冕,通過(guò)commit調(diào)用mutations的方法
6.mutations方法被調(diào)用后康吵,更改state
7.state中的數(shù)據(jù)更新之后,計(jì)算屬性重新執(zhí)行來(lái)更改在頁(yè)面中使用的狀態(tài)
8.組件狀態(tài)被更改访递,創(chuàng)建新的虛擬dom
9.組件的模板更新之后重新渲染在dom中
什么情況下用到vuex晦嵌?
使用Vuex的情況:多組件間頻繁通信
目前市場(chǎng)上有兩種使用vuex的情況,
第一種:將需要共享拷姿、需要管理的狀態(tài)放入vuex中管理惭载,也就是說(shuō)在必要時(shí)使用
第二種:將所有的數(shù)據(jù)都交由vuex管理,由vuex來(lái)承擔(dān)更多的責(zé)任响巢,組件變得更輕量級(jí)描滔,視圖層更輕
項(xiàng)目中使用到vuex的一些場(chǎng)景?
(1)購(gòu)物車(chē)數(shù)據(jù)共享
(2)用戶登錄
(3)打開(kāi)窗口踪古,出現(xiàn)一個(gè)表單數(shù)據(jù)含长,然后關(guān)閉窗口,再次打開(kāi)還想出現(xiàn)伏穆,就使用vuex
Vuex的項(xiàng)目結(jié)構(gòu)
Vuex 并不限制你的代碼結(jié)構(gòu)拘泞。但是,它規(guī)定了一些需要遵守的規(guī)則:
- 應(yīng)用層級(jí)的狀態(tài)應(yīng)該集中到單個(gè) store 對(duì)象中枕扫。
- 提交 mutation 是更改狀態(tài)的唯一方法陪腌,并且這個(gè)過(guò)程是同步的。
- 異步邏輯都應(yīng)該封裝到 action 里面。
只要你遵守以上規(guī)則诗鸭,如何組織代碼隨你便染簇。如果你的 store 文件太大,只需將 action强岸、mutation 和 getter 分割到單獨(dú)的文件锻弓。
對(duì)于大型應(yīng)用,我們會(huì)希望把 Vuex 相關(guān)代碼分割到模塊中请唱。下面是項(xiàng)目結(jié)構(gòu)示例:
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API請(qǐng)求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我們組裝模塊并導(dǎo)出 store 的地方
├── actions.js # 根級(jí)別的 action
├── mutations.js # 根級(jí)別的 mutation
└── modules
├── cart.js # 購(gòu)物車(chē)模塊
└── products.js # 產(chǎn)品模塊
來(lái)源:項(xiàng)目結(jié)構(gòu)(VUE官網(wǎng))
https://vuex.vuejs.org/zh/guide/structure.html#%E9%A1%B9%E7%9B%AE%E7%BB%93%E6%9E%84
vuex與local storage有什么區(qū)別
區(qū)別:vuex存儲(chǔ)在內(nèi)存弥咪,localstorage(本地存儲(chǔ))則以文件的方式存儲(chǔ)在本地过蹂,永久保存十绑;sessionstorage( 會(huì)話存儲(chǔ) ) ,臨時(shí)保存酷勺。localStorage和sessionStorage只能存儲(chǔ)字符串類(lèi)型本橙,對(duì)于復(fù)雜的對(duì)象可以使用ECMAScript提供的JSON對(duì)象的stringify和parse來(lái)處理。
應(yīng)用場(chǎng)景:vuex用于組件之間的傳值脆诉,localstorage甚亭,sessionstorage則主要用于不同頁(yè)面之間的傳值。
永久性:當(dāng)刷新頁(yè)面(這里的刷新頁(yè)面指的是 --> F5刷新,屬于清除內(nèi)存了)時(shí)vuex存儲(chǔ)的值會(huì)丟失击胜,sessionstorage頁(yè)面關(guān)閉后就清除掉了亏狰,localstorage不會(huì)。
注:很多同學(xué)覺(jué)得用localstorage可以代替vuex, 對(duì)于不變的數(shù)據(jù)確實(shí)可以偶摔,但是當(dāng)兩個(gè)組件共用一個(gè)數(shù)據(jù)源(對(duì)象或數(shù)組)時(shí)暇唾,如果其中一個(gè)組件改變了該數(shù)據(jù)源,希望另一個(gè)組件響應(yīng)該變化時(shí)辰斋,localstorage策州,sessionstorage無(wú)法做到,原因就是區(qū)別1宫仗。
Slot插槽
vue里提供了一種將父組件的內(nèi)容和子組件的模板整合的方法:內(nèi)容分發(fā)够挂,通過(guò)slot插槽來(lái)實(shí)現(xiàn)。
在組件標(biāo)簽內(nèi)部寫(xiě)入的內(nèi)容默認(rèn)的會(huì)被替換掉藕夫,如果想要在組件的模板里使用這些內(nèi)容孽糖,就在對(duì)應(yīng)的位置寫(xiě)上slot標(biāo)簽,這個(gè)slot標(biāo)簽就代表著這些內(nèi)容毅贮。
匿名槽口
在父組件中使用子組件的時(shí)候办悟,在子組件標(biāo)簽內(nèi)部寫(xiě)的內(nèi)容,在子組件的模板中可以通過(guò)<slot></slot>來(lái)使用
<div id = "app">
<aaa>
<h3>slot槽口插入的內(nèi)容</h3>
</aaa>
</div>
<template id="aaa">
<div class = "aaa">
<slot></slot>
<p>我是aaa組件</p>
</div>
</template>
具名槽口
父組件在子組件標(biāo)簽內(nèi)寫(xiě)的多個(gè)內(nèi)容我們可以給其設(shè)置slot屬性來(lái)命名嫩码,在子組件的模板通過(guò)使用帶有name屬性的slot標(biāo)簽來(lái)放置對(duì)應(yīng)的slot誉尖,當(dāng)slot不存在的時(shí)候,slot標(biāo)簽內(nèi)寫(xiě)的內(nèi)容就出現(xiàn)铸题。
slot上面通過(guò)name屬性指定槽口名稱铡恕,然后使用的時(shí)候通過(guò)slot="槽口名稱"琢感。
<div id = "app">
<aaa>
<!-- <h3>slot槽口插入的內(nèi)容</h3> -->
<p slot = "s1">在上面的內(nèi)容</p>
<p slot = "s2">在下面的內(nèi)容</p>
</aaa>
</div>
<template id="aaa">
<div class = "aaa">
<slot name = "s1"></slot>
<p>我是aaa組件</p>
<slot name = "s2"></slot>
</div>
</template>
slot插槽讓我們?cè)谠心0娴幕A(chǔ)上,定制更加多樣化的組件探熔。
作用域插槽
當(dāng)我們想在父組件中訪問(wèn)子組件內(nèi)部的一些數(shù)據(jù)時(shí)驹针,就需要在子組件內(nèi)部的<slot>元素上動(dòng)態(tài)綁定一個(gè)自定義屬性,將數(shù)據(jù)傳遞到自定義屬性上诀艰,通過(guò)slot傳遞給父組件使用柬甥。
<slot :teacher="teacher"></slot>
綁定到<slot>元素上的屬性我們稱之為slot props。現(xiàn)在其垄,在父組件中我們可以通過(guò)slot-scope給包含所有插槽 prop 的對(duì)象命名為prop苛蒲,之后就可以通過(guò)prop來(lái)使用子組件中的數(shù)據(jù)了。
<template slot-scope="prop">
老師姓名:{{prop.teacher.name}} 老師年齡:{{prop.teacher.age}}
</template>
v-slot
v-slot
指令自 Vue 2.6.0 起被引入绿满,提供更好的支持slot
和slot-scope
特性的 API 替代方案臂外。在接下來(lái)所有的 2.x 版本中slot
和slot-scope
特性仍會(huì)被支持,但已經(jīng)被官方廢棄喇颁,且不會(huì)出現(xiàn)在 Vue 3 中漏健。
現(xiàn)在我們使用 v-slot
重構(gòu)上面的代碼:
<template v-slot:default="prop">
老師姓名:{{prop.teacher.name}} 老師年齡:{{prop.teacher.age}}
</template>
一個(gè)不帶 name
的 <slot>
出口會(huì)帶有隱含的名字“default”,使用時(shí)可以簡(jiǎn)化為v-slot="prop“
橘霎。
具名槽口
子組件中通過(guò)name屬性給槽口設(shè)定名稱
<slot name="student" :student='student'></slot>
父組件中通過(guò)v-slot:名稱
的方式來(lái)使用具名槽口
<template v-slot:student="prop">
學(xué)生姓名:{{prop.student.name}} 學(xué)生年齡:{{prop.student.age}}
</template>
當(dāng)我們?cè)诟附M件中多次調(diào)用子組件時(shí)蔫浆,可以通過(guò)設(shè)置不同的樣式,來(lái)設(shè)定子組件中數(shù)據(jù)的展示形式姐叁。
主流js框架對(duì)比
Vue和React的區(qū)別
(1)react銷(xiāo)毀組件的時(shí)候瓦盛,會(huì)將組件的dom結(jié)構(gòu)也移除,vue則不然七蜘,在調(diào)用destory方法銷(xiāo)毀組件的時(shí)候谭溉,組件的dom結(jié)構(gòu)還是存在于頁(yè)面中的,this.$destory組件結(jié)構(gòu)還是存在的橡卤,只是移除了事件監(jiān)聽(tīng)扮念。
(2)react中沒(méi)有指令
(3)在vue中,data屬性是利用object.defineProperty處理過(guò)的碧库,更改data的數(shù)據(jù)的時(shí)候會(huì)觸發(fā)數(shù)據(jù)的getter和setter柜与,但是react中沒(méi)有做這樣的處理,如果直接更改的話嵌灰,react是無(wú)法得知的弄匕。
react更改狀態(tài):在setState中,傳入一個(gè)對(duì)象沽瞭,就會(huì)將組件的狀態(tài)中鍵值對(duì)的部分更改迁匠,還可以傳入一個(gè)函數(shù),這個(gè)回調(diào)函數(shù)必須向上面方式一樣的一個(gè)對(duì)象函數(shù)可以接受prevState和props。
(4)react中屬性是不允許更改的城丧,狀態(tài)是允許更改的延曙。react中組件不允許通過(guò)this.state這種方式直接更改組件的狀態(tài)。自身設(shè)置的狀態(tài)亡哄,可以通過(guò)setState來(lái)進(jìn)行更改枝缔。
拓展:對(duì)比其他框架(Vue官網(wǎng)給出的詳細(xì)解釋?zhuān)?/p>
https://vue.docschina.org/v2/guide/comparison.html
Vue和JQuery的區(qū)別
jQuery是使用選擇器($)選取DOM對(duì)象,對(duì)其進(jìn)行賦值蚊惯、取值愿卸、事件綁定等操作,其實(shí)和原生的HTML的區(qū)別只在于可以更方便的選取和操作DOM對(duì)象截型,而數(shù)據(jù)和界面是在一起的趴荸。
比如需要獲取label標(biāo)簽的內(nèi)容:$("lable").val();
,它還是依賴DOM元素的值。
Vue則是通過(guò)Vue對(duì)象將數(shù)據(jù)和View完全分離開(kāi)來(lái)了菠劝。對(duì)數(shù)據(jù)進(jìn)行操作不再需要引用相應(yīng)的DOM對(duì)象赊舶,可以說(shuō)數(shù)據(jù)和View是分離的睁搭,他們通過(guò)Vue對(duì)象這個(gè)vm實(shí)現(xiàn)相互的綁定赶诊。這就是傳說(shuō)中的MVVM。
vue適用的場(chǎng)景:復(fù)雜數(shù)據(jù)操作的后臺(tái)頁(yè)面园骆,表單填寫(xiě)頁(yè)面
jquery適用的場(chǎng)景:比如說(shuō)一些html5的動(dòng)畫(huà)頁(yè)面舔痪,一些需要js來(lái)操作頁(yè)面樣式的頁(yè)面
然而二者也是可以結(jié)合起來(lái)一起使用的,vue側(cè)重?cái)?shù)據(jù)綁定锌唾,jquery側(cè)重樣式操作锄码,動(dòng)畫(huà)效果等龙宏,則會(huì)更加高效率的完成業(yè)務(wù)需求
參考:jquery和vue對(duì)比
https://www.cnblogs.com/MR-YY/p/6898464.html
react與vue之間的相同點(diǎn)和不同點(diǎn)捏肢?
相同點(diǎn):
? 1.都支持ssr服務(wù)器端渲染,vue:nuxt疟丙;react:next余黎。
? 2.都有Virtual DOM重窟,組件化開(kāi)發(fā),通過(guò)props參數(shù)進(jìn)行父子組件數(shù)據(jù)的傳遞惧财,都實(shí)現(xiàn)組件之間的模塊化webComponent規(guī)范巡扇。
? 3.數(shù)據(jù)驅(qū)動(dòng)視圖,數(shù)據(jù)改變視圖發(fā)生更改垮衷。
? 4.都有支持native的方案,React的React native,Vue的weex(終端的原生端端解決方案)
? 5.都有管理狀態(tài)集工具厅翔,React有redux,Vue有自己的Vuex(自適應(yīng)vue,量身定做)
不同點(diǎn):
- React嚴(yán)格上只針對(duì)MVC的view層(用戶界面的javascript庫(kù))搀突,Vue則是MVVM模式刀闷。
- virtual DOM不一樣:vue會(huì)跟蹤每一個(gè)組件的依賴關(guān)系,不需要重新渲染整個(gè)組件樹(shù)。而對(duì)于React而言,每當(dāng)應(yīng)用的狀態(tài)被改變時(shí),全部組件都會(huì)重新渲染,所以react中會(huì)需要shouldComponentUpdate這個(gè)生命周期函數(shù)方法來(lái)進(jìn)行控制甸昏。
- 組件寫(xiě)法不一樣:React推薦的做法是 JSX + inline style, 也就是把HTML和CSS全都寫(xiě)進(jìn)JavaScript了,即'all in js';Vue推薦的做法是webpack+vue-loader的單文件組件格式,即html,css,js寫(xiě)在同一個(gè)文件;
- 數(shù)據(jù)綁定: vue實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定戈次,react沒(méi)有實(shí)現(xiàn)。
- state對(duì)象在react應(yīng)用中不可變的筒扒,需要使用setState方法更新?tīng)顟B(tài)怯邪;在vue中,state對(duì)象不是必須的花墩,數(shù)據(jù)由data屬性在vue對(duì)象中管理悬秉。