offer收割機(jī)-Web前端面試寶典【精編版-3】

image

在線訪問(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)題拣凹?

  1. 開(kāi)發(fā)團(tuán)隊(duì)代碼風(fēng)格不統(tǒng)一问词,如何強(qiáng)制開(kāi)發(fā)規(guī)范督函。
  2. 前期開(kāi)發(fā)的組件庫(kù)如何維護(hù)和使用
  3. 如何模塊化前端項(xiàng)目
  4. 服務(wù)器部署前必須壓縮,檢查流程如何簡(jiǎn)化激挪,流程如何完善。

你使用過(guò)哪些前端構(gòu)建集成垄分?你用過(guò)什么打包工具宛篇?

  1. Gulp

gulp是工具鏈、構(gòu)建工具薄湿,可以配合各種插件做js壓縮叫倍,css壓縮,less編譯豺瘤,替代手工實(shí)現(xiàn)自動(dòng)化工作

(1)構(gòu)建工具

(2)自動(dòng)化

(3)提高效率用

  1. 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倍阐。

  1. gulp.src(globs[, options])

    返回符合匹配規(guī)則的虛擬文件對(duì)象流(Vinyl files)概疆。

  2. gulp.dest(path[, options])

    用來(lái)指定要生成的文件的目錄,目錄路徑為path峰搪。

  3. gulp.task(name[, deps], fn)

    定義一個(gè)流任務(wù)岔冀,任務(wù)名為name。

  4. 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ù)混合

image
image
image

版本控制工具

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é)果

  1. git是分布式的scm,svn是集中式的院尔。(最核心)

  2. git是每個(gè)歷史版本都存儲(chǔ)完整的文件,便于恢復(fù),svn是存儲(chǔ)差異文件,歷史版本不可恢復(fù)蜻展。(核心)

  3. git可離線完成大部分操作,svn則不能喉誊。

  4. git有著更優(yōu)雅的分支和合并實(shí)現(xiàn)。

  5. git有著更強(qiáng)的撤銷(xiāo)修改和修改歷史版本的能力

  6. 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)

  1. 代碼更多阿弃,體積更大
  2. 內(nèi)存占用增大
  3. 小量的單一的dom修改使用虛擬dom成本反而更高诊霹,不如直接修改真實(shí)dom快

VUE中虛擬dom操作流程

  1. 在內(nèi)存中構(gòu)建虛擬dom樹(shù)

  2. 將內(nèi)存中虛擬dom樹(shù)渲染成真實(shí)dom結(jié)構(gòu)

  3. 數(shù)據(jù)改變的時(shí)候,將之前的虛擬dom樹(shù)結(jié)合新的數(shù)據(jù)生成新的虛擬dom樹(shù)

  4. 將此次生成好的虛擬dom樹(shù)和上一次的虛擬dom樹(shù)進(jìn)行一次比對(duì)(diff算法進(jìn)行比對(duì))

  5. 會(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ì)模式(單向通信)

image
  • 視圖(View):用戶界面绩卤。
  • 控制器(Controller):業(yè)務(wù)邏輯
  • 模型(Model):數(shù)據(jù)保存
  1. View 傳送指令到 Controller
  2. Controller 完成業(yè)務(wù)邏輯后途样,要求 Model 改變狀態(tài)
  3. Model 將新的數(shù)據(jù)發(fā)送到 View,用戶得到反饋

MVP設(shè)計(jì)模式

MVP 模式將 Controller 改名為 Presenter省艳,同時(shí)改變了通信方向娘纷。

image
  1. 各部分之間的通信,都是雙向的跋炕。
  2. View 與 Model 不發(fā)生聯(lián)系赖晶,都通過(guò) Presenter 傳遞。
  3. View 非常薄辐烂,不部署任何業(yè)務(wù)邏輯遏插,稱為"被動(dòng)視圖"(Passive View),即沒(méi)有任何主動(dòng)性纠修,而 Presenter非常厚胳嘲,所有邏輯都部署在那里。

MVVM設(shè)計(jì)模式

MVVM 模式將 Presenter 改名為 ViewModel扣草,基本上與 MVP 模式完全一致了牛。

image

唯一的區(qū)別是颜屠,它采用雙向綁定(data-binding):View的變動(dòng),自動(dòng)反映在 ViewModel鹰祸,反之亦然。AngularEmber 都采用這種模式蛙婴。

參考: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)。

image

組件

什么是組件停团?

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))

https://vue.docschina.org/v2/guide/components.html#data-%E5%BF%85%E9%A1%BB%E6%98%AF%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0

組件的 data 選項(xiàng)必須是一個(gè)函數(shù)师抄,以便每個(gè)實(shí)例都可以維護(hù)「函數(shù)返回的數(shù)據(jù)對(duì)象」的彼此獨(dú)立的數(shù)據(jù)副本。

image

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ì)以自定義屬性的方式盅弛,放在兒子最外層的根元素上面。

image

子組件通過(guò)props來(lái)接受父組件傳遞過(guò)來(lái)的數(shù)據(jù),并且通過(guò){{msg}}使用

components:{
            son:{
                template:"<div>我是son子組件昭躺!這是父組件傳遞給我的msg:{{msg}}</div>",
                //接收父組件傳遞來(lái)的屬性  msg
                props:["msg"]
            }
        }
image

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)給出警告。

image

所以如果我們想實(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:""}

父子間數(shù)據(jù)共享(雙向控制),基本不會(huì)使用,違背了單向數(shù)據(jù)流(父=》子)

4贱鄙、viewmodel關(guān)系鏈

在組件間可以用過(guò)ref形成ref鏈劝贸,組件還擁有一個(gè)關(guān)系鏈($parent),通過(guò)這兩種鏈;理論來(lái)說(shuō)逗宁,任意的兩個(gè)組件都可以互相訪問(wèn)映九,互相進(jìn)行通信。

$parent:父組件

$children:子組件

$root:根組件

image

當(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ù)
                }
            }
        }
    })
image

所以這時(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)記拿到子組件

image
// 通過(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>  
image

注意多個(gè)子組件標(biāo)記的是同一個(gè)鍵名曾我,獲取到的應(yīng)該是一個(gè)數(shù)組

<bbb ref = "b" v-for = "(item,index) in 3" :key = "index"></bbb>
image
// 通過(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í)桐猬,它的activeddeactived這兩個(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è)步驟:

  1. v-bind 綁定了一個(gè)value的屬性

  2. 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)容粱哼。

image

一定要在路由守衛(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();
})
image

(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è)面")
  }
})
image

局部守衛(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();
    }}
image

組件內(nèi)的守衛(wèi)

最后皂吮,你可以在路由組件內(nèi)直接定義以下路由導(dǎo)航守衛(wèi):

  1. 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ì)于 beforeRouteUpdatebeforeRouteLeave 來(lái)說(shuō)津坑,this 已經(jīng)可用了,所以不支持傳遞回調(diào)傲霸,因?yàn)闆](méi)有必要了疆瑰。

  1. 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)取消。

  1. 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)

  1. 更好的用戶體驗(yàn)冰木,讓用戶在web感受natvie的速度和流暢溪北;
  2. 經(jīng)典MVC開(kāi)發(fā)模式趟畏,前后端各負(fù)其責(zé)。
  3. 一套Server API,多端使用(web、移動(dòng)APP等)
  4. 重前端栽渴,業(yè)務(wù)邏輯全部在本地操作,數(shù)據(jù)都需要通過(guò)AJAX同步稳懒、提交闲擦;

Vue切換路由的方法?vue-router的原理场梆?

Vue中會(huì)使用官方提供的vue-router插件來(lái)使用單頁(yè)面墅冷,原理就是通過(guò)檢測(cè)地址欄變化后將對(duì)應(yīng)的路由組件進(jìn)行切換(卸載和安裝)。

  1. 引入vue-router或油,如果是在腳手架中寞忿,引入VueRouter之后,需要通過(guò)Vue.use來(lái)注冊(cè)插件
  2. 創(chuàng)建router路由器
  3. 創(chuàng)建路由表并配置在路由器中
  4. 在根實(shí)例里注入router,目的是為了讓所有的組件里都能通過(guò)this.$router/route來(lái)使用路由的相關(guān)功能api
  5. 利用router-view來(lái)指定路由切換的位置
  6. 使用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。

image

在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)有被記錄去扣。

image

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)的顯示效果:

image

還可以通過(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>

顯示效果:

image

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>
image

路由跳轉(zhuǎn)的方式

  1. <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)名筛婉。

  2. 編程式導(dǎo)航:this.$router.replace

    This.$router.go

一級(jí)路由的實(shí)現(xiàn)

  1. 如果不是使用腳手架創(chuàng)建的項(xiàng)目,需要手動(dòng)安裝vue-router路由模塊癞松。

     cnpm install vue-router -S
    
  2. 引入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屬性枫甲。

image
  1. 創(chuàng)建router路由器源武,并導(dǎo)出扼褪。

    let router = new Router({
      routes:[
    
      ]
    })
    
    export default router;
    
  2. 在根實(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
  3. 創(chuàng)建router路由表

    let router = new Router({
      routes:[
        {
          path:"/home",component:Home
        },
        {
          path: "/list", component: List
        },
        {
          path: "/mine", component: Mine
        }
      ]
    })
    
  4. 在App.vue中利用router-view來(lái)指定路由切換的位置

    <template>
      <div id="app">
        Hello app.vue!
        <!-- 顯示路由組件的位置 -->
        <router-view></router-view>
      </div>
    </template>
    

    路由切換效果:

    image
  5. 使用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>
image

一個(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))

https://router.vuejs.org/zh/guide/essentials/named-views.html#%E5%B5%8C%E5%A5%97%E5%91%BD%E5%90%8D%E8%A7%86%E5%9B%BE

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>
image

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é)果:

image

頁(yè)面渲染效果:

image

上面的參數(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模式

image

比如這個(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",
image

history模式鞋仍,會(huì)出現(xiàn)404 的情況,需要后臺(tái)配置搅吁。

hash模式和history模式在發(fā)生404錯(cuò)誤時(shí):

  1. 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

  2. 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的核心?

image

(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ī)則:

  1. 應(yīng)用層級(jí)的狀態(tài)應(yīng)該集中到單個(gè) store 對(duì)象中枕扫。
  2. 提交 mutation 是更改狀態(tài)的唯一方法陪腌,并且這個(gè)過(guò)程是同步的。
  3. 異步邏輯都應(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ū)別

  1. 區(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)處理。

  2. 應(yīng)用場(chǎng)景:vuex用于組件之間的傳值脆诉,localstorage甚亭,sessionstorage則主要用于不同頁(yè)面之間的傳值。

  3. 永久性:當(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>
image

具名槽口

父組件在子組件標(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>
image

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>
image

v-slot

v-slot 指令自 Vue 2.6.0 起被引入绿满,提供更好的支持 slotslot-scope 特性的 API 替代方案臂外。在接下來(lái)所有的 2.x 版本中slotslot-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):

  1. React嚴(yán)格上只針對(duì)MVC的view層(用戶界面的javascript庫(kù))搀突,Vue則是MVVM模式刀闷。
  2. 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)行控制甸昏。
  3. 組件寫(xiě)法不一樣:React推薦的做法是 JSX + inline style, 也就是把HTML和CSS全都寫(xiě)進(jìn)JavaScript了,即'all in js';Vue推薦的做法是webpack+vue-loader的單文件組件格式,即html,css,js寫(xiě)在同一個(gè)文件;
  4. 數(shù)據(jù)綁定: vue實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定戈次,react沒(méi)有實(shí)現(xiàn)。
  5. state對(duì)象在react應(yīng)用中不可變的筒扒,需要使用setState方法更新?tīng)顟B(tài)怯邪;在vue中,state對(duì)象不是必須的花墩,數(shù)據(jù)由data屬性在vue對(duì)象中管理悬秉。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市冰蘑,隨后出現(xiàn)的幾起案子和泌,更是在濱河造成了極大的恐慌,老刑警劉巖祠肥,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件武氓,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡仇箱,警方通過(guò)查閱死者的電腦和手機(jī)县恕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)剂桥,“玉大人忠烛,你說(shuō)我怎么就攤上這事∪ǘ海” “怎么了美尸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)斟薇。 經(jīng)常有香客問(wèn)我师坎,道長(zhǎng),這世上最難降的妖魔是什么堪滨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任胯陋,我火速辦了婚禮,結(jié)果婚禮上椿猎,老公的妹妹穿的比我還像新娘惶岭。我一直安慰自己,他們只是感情好犯眠,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布按灶。 她就那樣靜靜地躺著,像睡著了一般筐咧。 火紅的嫁衣襯著肌膚如雪鸯旁。 梳的紋絲不亂的頭發(fā)上噪矛,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音铺罢,去河邊找鬼艇挨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛韭赘,可吹牛的內(nèi)容都是我干的缩滨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼泉瞻,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼脉漏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起袖牙,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤侧巨,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后鞭达,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體司忱,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年畴蹭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坦仍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撮胧,死狀恐怖桨踪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芹啥,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布铺峭,位于F島的核電站墓怀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏卫键。R本人自食惡果不足惜傀履,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望莉炉。 院中可真熱鬧钓账,春花似錦、人聲如沸絮宁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)绍昂。三九已至啦粹,卻和暖如春偿荷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背唠椭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工跳纳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贪嫂。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓寺庄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親力崇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铣揉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一:什么是閉包?閉包的用處餐曹? (1)閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)逛拱。在本質(zhì)上,閉包就 是將函數(shù)內(nèi)部和函數(shù)外...
    xuguibin閱讀 9,631評(píng)論 1 52
  • vue是什么台猴? vue是構(gòu)建數(shù)據(jù)驅(qū)動(dòng)的web界面的漸進(jìn)式框架朽合。Vue.js 的目標(biāo)是通過(guò)盡可能簡(jiǎn)單的 API 實(shí)現(xiàn)...
    九四年的風(fēng)閱讀 8,713評(píng)論 2 131
  • Vue 3.0 性能提升主要是通過(guò)哪幾方面體現(xiàn)的? vue2在初始化的時(shí)候饱狂,對(duì)data中的每個(gè)屬性使用define...
    Smallbore閱讀 1,161評(píng)論 0 8
  • Vue八個(gè)生命周期 beforeCreate【創(chuàng)建前】created【創(chuàng)建后】 beforeMount【載入前】 ...
    艾薩克菊花閱讀 1,319評(píng)論 0 12
  • 昨天是晴曹步,今天來(lái)了雨。心情隨著陰也成了陰休讳。我坐在離門(mén)口最近的位置讲婚,不經(jīng)意看到行人被來(lái)往的車(chē)濺一身泥水的皺眉和隨意的...
    jeongtony閱讀 302評(píng)論 0 0