前端面試題(六)

Vue路由的實現(xiàn)原理

路由這個概念最初是由后端提出來的,在我們沒有SPA單頁面應用之前赦役,使用的一直都是后端路由麻敌,根據(jù)不同的路由返回不同的頁面,后來隨著單頁面應用的誕生掂摔,開始有了前端路由术羔,實現(xiàn)不刷新但是更新頁面的效果
vue-router是專為Vue打造的路由管理工具
vue-router提供三種路由模式
1.hash模式

  • 默認模式,通過路徑中的hash值來控制路由跳轉(zhuǎn)乙漓,不存在兼容問題
    2.history模式
  • H5新增的 history API级历,相對hash而言,不會顯示#號叭披,但是需要服務器端配置
    3.abstract模式
  • 支持javascript的所有運行環(huán)境寥殖,常指Node.js服務器環(huán)境
hash模式實現(xiàn)原理

在正常路徑后跟一個 # 號,匹配 # 后邊的路徑為前端路由涩蜘,通過window.onhashchange方法來操控路由改變的時候切換內(nèi)容
2.onhashchange 方法的觸發(fā)時機

  1. 直接更改瀏覽器地址嚼贡,在最后面增加或改變#hash;
  2. 通過改變location.href或location.hash的值同诫;
  3. 通過觸發(fā)點擊帶錨點的鏈接粤策;
  4. 瀏覽器前進后退可能導致hash的變化,前提是兩個網(wǎng)頁地址中的hash值不同误窖。
    2.示例代碼
<body>
  <ul>
    <li>
       <a href="#/home">home</a>
    </li>
    <li>
       <a href="#/list">list</a>
    </li>
    <li>
       <a href="#/detail">detail</a>
    </li>
 </ul>
</body>
<script>
window.onhashchange = function() {
    //  做頁面切換渲染等
    console.log(location.href);
    console.log(location.hash);
}
</script>
  • 通過點擊a標簽叮盘,傳遞一個hash值秩贰,然后通過window.onhashchange方法來監(jiān)聽hash的變化,然后在這個事件觸發(fā)的時候柔吼,根據(jù)location.hash來動態(tài)的修改單頁面應用的內(nèi)容即可
history模式實現(xiàn)原理

看起來與后端路由沒有任何區(qū)別萍膛,在window.history這個對象中,包含瀏覽器的歷史嚷堡,而在HTML5中蝗罗,新增了pushState和replaceState,通過這兩個API可以改變url地址且不會發(fā)送請求蝌戒,同時還有popstate事件串塑,實現(xiàn)原理與hash相似,只不過因為沒有了 # 號北苟,所以刷新頁面還是會向服務器發(fā)送請求桩匪,而后端沒有對應的處理措施的話,會返回404友鼻,所以需要后端配合

  1. popstate方法的觸發(fā)時機
  2. 僅僅調(diào)用pushState方法或replaceState方法 傻昙,并不會觸發(fā)該事件;
  3. 只有用戶點擊瀏覽器倒退按鈕和前進按鈕彩扔,或者使用JavaScript調(diào)用back妆档、forward、go方法時才會觸發(fā)虫碉。
  4. 另外贾惦,該事件只針對同一個文檔,如果瀏覽歷史的切換敦捧,導致加載不同的文檔须板,該事件也不會觸發(fā)。
    2.示例代碼
<body>
  <ul>
    <li>
      <a href="/home">home</a>
    </li>
    <li>
      <a href="/list">list</a>
    </li>
    <li>
      <a href="/detail">detail</a>
    </li>
  </ul>
</body>
<script>
document.querySelectorAll('a').forEach(item => {
  item.onclick = function (e) {
      e.preventDefault();
      let link = item.getAttribute('href');
      window.history.pushState({link}, link, link);
   };
});
window.addEventListener('popstate', function (e) {
   console.log(e.state);
   console.log(location.href);
})
</script>
  • 當點擊瀏覽器的后退或前進按鈕兢卵,或者調(diào)用history上的go习瑰、back方法時,就會觸發(fā)事件秽荤,打印出對應的數(shù)據(jù)甜奄,e.state 中就存放著pushState方法中的state對象
  • 通過在修改路由信息的同時執(zhí)行切換DOM的操作,來實現(xiàn)了路由切換
abstract模式實現(xiàn)原理
  • abstract模式是不依賴于瀏覽器環(huán)境王滤,所以沒有使用hash或者history等瀏覽器才會提供的API贺嫂,而是VueRouter內(nèi)部使用數(shù)組進行模擬了路由管理,在node環(huán)境雁乡,或者原生App環(huán)境下第喳,都會默認使用abstract模式,VueRouter內(nèi)部會根據(jù)所處的環(huán)境自行判斷踱稍,默認使用hash模式曲饱,如果檢測到?jīng)]有瀏覽器API的時候悠抹,就會使用abstract模式。

SPA 路由history模式上線后刷新404

1.出現(xiàn)問題:在使用history模式的時候扩淀,由于瀏覽器路徑與后端路徑類似楔敌,所以當刷新頁面的時候,瀏覽器還是會向服務器發(fā)送請求驻谆,但是由于服務器并沒有對應的路由頁面卵凑,所以會導致404空白
2.解決方案:在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源,則應該返回同一個 index.html 頁面胜臊,這個頁面就是你 app 依賴的頁面勺卢。同時這么做以后,服務器就不再返回 404 錯誤頁面象对,因為對于所有路徑都會返回 index.html 文件黑忱。為了避免這種情況,在 Vue 應用里面覆蓋所有的路由情況勒魔,然后在給出一個 404 頁面甫煞。或者冠绢,如果是用 Node.js 作后臺抚吠,可以使用服務端的路由來匹配 URL,當沒有匹配到路由的時候返回 404唐全,從而實現(xiàn)后退埃跷。
1.node服務器

  • 簡單粗暴的一種方法蕊玷,如果沒有讀取到靜態(tài)資源就直接返回html頁面邮利,可以用于前端調(diào)試
const http = require('http');
const fs = require('fs');

http.createServer((req,res) => {
    fs.readFile(__dirname + req.url, (err, data) => {
      if(!err) {
          res.end(data);
      }else {
          fs.readFile('index.html', (e, html) => {
              if(!e) {
                  res.end(html);
              }
          })
      }
  })
}).listen(8080, err => {
  !err&&(console.log('http://localhost:8080')
})

2.nginx靜態(tài)服務器

  • 常用方式,直接使用80端口
server {
      listen       80;
      server_name  localhost;

      location / {
          root   html;
          index  index.html;
          try_files $uri $uri/ /index.html;
      }
   }
  • 在nginx安裝目錄下垃帅,將打包后的文件放置在安裝目錄下的 html 目錄中延届,接著打開conf目錄中的nginx.conf文件,修改server部分如上贸诚,然后在nginx根目錄使用nginx -t測試配置文件修改后的語法是否正確(如果有問題會報錯)方庭,如果沒有錯誤的話,使用命令nginx -s reload命令重啟讓配置文件生效酱固,打開瀏覽器械念,輸入localhost即可看到項目部署完成
  • 常用方式,同時運行多個程序時运悲,80端口被占用時
server {
    listen       8000;
    server_name  localhost;

    location / {
        root   html/project;
        index  index.html;
        try_files $uri $uri/ /index.html;
    }
}
  • 在html目錄下新建文件夾龄减,例如project,將打包后的文件放置在project文件夾下班眯,在conf/nginx.conf文件中希停,原80端口的下方新加入上述代碼烁巫,接著重復nginx -t與nginx -s reload再次打開瀏覽器,輸入localhost:8000就可以看到項目部署完成

$$route和$router的區(qū)別

1.route是路由信息對象宠能,包括 path亚隙、params、hash违崇、query阿弃、fullPath、meta羞延、name 等路由信息參數(shù)恤浪,可以通過route來獲取當前路由的各種參數(shù)
1.path String 保存當前絕對路徑信息

2.params Object 保存當前的params參數(shù)對象

3.hash String 保存當前的hash信息,不帶#號肴楷,如果沒有hash為空字符串

4.query Object 保存當前的query參數(shù)對象

5.meta Object 保存當前路由的源信息

6.fullPath String 保存完成解析后的路徑信息水由,包含hash、query等參數(shù)

7.name String 保存路由name值

2.$router是路由實例對象赛蔫,包含的是VueRouter實例上的方法以及配置屬性砂客,常用于編程式導航;

1.push Function(Object|String)

  • this.$router.push('/home?tab=all')
  • this.$router.push({path: '/home', query:{tab:'all'}})

2.replace Function(Object|String)

  • this.$router.replace('/home?tab=all')
  • this.$router.replace({path: '/home', query:{tab:'all'}})

3.go Function(Number)

  • this.$router.go(-1) 操作history的API進行后退

  • this.$router.go(1) 操作history的API進行前進

自定義過濾器詳解

1.在Vue1.x的版本中呵恢,是有內(nèi)置過濾器的鞠值,而到了2.0以后,廢除了內(nèi)置過濾器渗钉,允許我們自定義過濾器
2.自定義過濾器的使用方法

  • 在插值表達式{{}}以及v-bind:指令綁定的屬性的冒號內(nèi)彤恶,可以使用自定義過濾器
  • 使用時,在js表達式的結(jié)尾使用管道符來指示過濾器
  • 示例: {{date| formatDate}} 或者 <input v-bind:value="date | formatDate" />
    3.自定義過濾器的使用場景
  • 在我們前端拿到后臺的數(shù)據(jù)時鳄橘,經(jīng)常有些數(shù)據(jù)是不能直接展示出來的声离,需要經(jīng)過處理之后再展示,在Vue中瘫怜,我們可以通過methods來做术徊,也可以通過computed計算屬性來做,但是最好還是通過過濾器filters來做鲸湃,因為它是在原數(shù)據(jù)基礎(chǔ)上進行過濾赠涮,不會修改原有數(shù)據(jù),使用computed以及methods屬于大材小用了
    4.過濾器的定義
  • 在Vue中分為全局過濾器局部過濾器
// 全局過濾器
  Vue.filter(過濾器名稱, function(value) {
      return value;  // 處理value暗挑,vlaue就是需要過濾的數(shù)據(jù)
  })
  // 局部過濾器
  new Vue({
      el: '#app',
      filters: {
            '過濾器名稱'(value) {
                 return value;  // 處理value笋除,vlaue就是需要過濾的數(shù)據(jù)
            }
      }
  })

5.實現(xiàn)自定義過濾器
1.無參數(shù)過濾器

Vue.filter('formatDate', function(value) {
      if(!value) return;
      return new Date(value).toLocaleString();
}) 
// html
<div>{{ 1562731217574 | formatDate }}</div>

2.有參數(shù)過濾器

Vue.filter('formatPrice', function(value, num) {
      if(!value) return;
      return value.toFixed(num);
}) 
// html
<div>{{ 15.6264 | formatPrice(2)}}</div>

3.多個參數(shù)的過濾器

Vue.filter('formatText', function(value, start, end) {
      if(!value) return;
      return start + '-' + value + '-' + end;
}) 
// html
<div>{{ '中間' | formatText('開始','結(jié)束')}}</div>

4.過濾器串聯(lián),可以多個串聯(lián)

 <div>{{ '中間' | formatText('開始','結(jié)束') | formatText('串聯(lián)start','串聯(lián)end') }}</div> 

assets和static/public的區(qū)別

在vue-cli工具中炸裆,有兩個存放靜態(tài)資源的目錄垃它,一個是src目錄下的assets,另一個在vue-cli2下是static目錄,在vue-cli3下是public目錄嗤瞎,那這兩個目錄的區(qū)別是什么呢墙歪?
首先需要知道:在.vue組件中,所有的templates和css都會被vue-html-loader 和 css-loader解析贝奇,尋找資源的URL虹菲。
例如: <img src="./assets/logo.png">或者 background: url('./assets/logo.png'),這兩個url路徑都會被webpack解析成資源模塊依賴掉瞳,而由于這些靜態(tài)文件大都不是js文件毕源,而vue-cli工具利用各種loader幫助我們解析了這些資源

資源處理規(guī)則
1.相對路徑, ./assets/logo.png 將會被解析成一個模塊依賴。
2.沒有前綴的路徑, assets/logo.png 將會被看成./assets/logo.png進行解析模塊依賴
3.前綴帶~的URL 會被當成模塊請求, 例如:<img src="~assets/logo.png">
4.相對根目錄的URL/assets/logo.png 是不會被處理的

javascript中使用靜態(tài)資源

  • 例如:imgUrl: require('./assets/logo.png')

assets和static/public的區(qū)別

  • 在assets目錄下的靜態(tài)資源會被webpack解析成資源模塊依賴陕习,在項目打包的時候會隨著項目一起打包
  • 而在static/public目錄下的靜態(tài)資源不會被解析霎褐,是真正的靜態(tài)資源

本文CSDN地址:前端面試題(六)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市该镣,隨后出現(xiàn)的幾起案子冻璃,更是在濱河造成了極大的恐慌,老刑警劉巖损合,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件省艳,死亡現(xiàn)場離奇詭異,居然都是意外死亡嫁审,警方通過查閱死者的電腦和手機跋炕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來律适,“玉大人辐烂,你說我怎么就攤上這事∥婊撸” “怎么了纠修?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長眷蜓。 經(jīng)常有香客問我分瘾,道長,這世上最難降的妖魔是什么吁系? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮白魂,結(jié)果婚禮上汽纤,老公的妹妹穿的比我還像新娘。我一直安慰自己福荸,他們只是感情好蕴坪,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般背传。 火紅的嫁衣襯著肌膚如雪呆瞻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天径玖,我揣著相機與錄音痴脾,去河邊找鬼。 笑死梳星,一個胖子當著我的面吹牛赞赖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播冤灾,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼前域,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了韵吨?” 一聲冷哼從身側(cè)響起匿垄,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎归粉,沒想到半個月后年堆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡盏浇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年变丧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绢掰。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡痒蓬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出滴劲,到底是詐尸還是另有隱情攻晒,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布班挖,位于F島的核電站鲁捏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏萧芙。R本人自食惡果不足惜给梅,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望双揪。 院中可真熱鬧动羽,春花似錦、人聲如沸渔期。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拘哨,卻和暖如春谋梭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背倦青。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工瓮床, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姨夹。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓纤垂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親磷账。 傳聞我的和親對象是個殘疾皇子峭沦,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355