前端常見面試題(六)@郝晨光


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

路由這個概念最初是由后端提出來的,在我們沒有SPA單頁面應(yīng)用之前杨伙,使用的一直都是后端路由淘衙,根據(jù)不同的路由返回不同的頁面,后來隨著單頁面應(yīng)用的誕生剔桨,開始有了前端路由屉更,實現(xiàn)不刷新但是更新頁面的效果

vue-router是專為Vue打造的路由管理工具

vue-router提供三種路由模式
  1. hash模式
    • 默認(rèn)模式,通過路徑中的hash值來控制路由跳轉(zhuǎn)洒缀,不存在兼容問題
  2. history模式
    • H5新增的 history API瑰谜,相對hash而言,不會顯示#號树绩,但是需要服務(wù)器端配置
  3. abstract模式
    • 支持javascript的所有運行環(huán)境萨脑,常指Node.js服務(wù)器環(huán)境
hash模式實現(xiàn)原理

示例:http://www.haochenguang.cn/#/home
在正常路徑后跟一個 # 號,匹配 # 后邊的路徑為前端路由饺饭,通過window.onhashchange方法來操控路由改變的時候切換內(nèi)容

  1. onhashchange 方法的觸發(fā)時機
    1. 直接更改瀏覽器地址渤早,在最后面增加或改變#hash;
    2. 通過改變location.href或location.hash的值瘫俊;
    3. 通過觸發(fā)點擊帶錨點的鏈接蛛芥;
    4. 瀏覽器前進后退可能導(dǎo)致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標(biāo)簽仅淑,傳遞一個hash值,然后通過window.onhashchange方法來監(jiān)聽hash的變化胸哥,然后在這個事件觸發(fā)的時候涯竟,根據(jù)location.hash來動態(tài)的修改單頁面應(yīng)用的內(nèi)容即可
history模式實現(xiàn)原理

示例:http://www.haochenguang.cn/home
看起來與后端路由沒有任何區(qū)別,在window.history這個對象中,包含瀏覽器的歷史庐船,而在HTML5中银酬,新增了pushStatereplaceState,通過這兩個API可以改變url地址且不會發(fā)送請求筐钟,同時還有popstate事件揩瞪,實現(xiàn)原理與hash相似,只不過因為沒有了 # 號篓冲,所以刷新頁面還是會向服務(wù)器發(fā)送請求李破,而后端沒有對應(yīng)的處理措施的話,會返回404壹将,所以需要后端配合

  1. popstate方法的觸發(fā)時機

    1. 僅僅調(diào)用pushState方法或replaceState方法 嗤攻,并不會觸發(fā)該事件;
    2. 只有用戶點擊瀏覽器倒退按鈕和前進按鈕诽俯,或者使用JavaScript調(diào)用back妇菱、forward、go方法時才會觸發(fā)暴区。
    3. 另外闯团,該事件只針對同一個文檔,如果瀏覽歷史的切換仙粱,導(dǎo)致加載不同的文檔偷俭,該事件也不會觸發(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>
      
      • 當(dāng)點擊瀏覽器的后退或前進按鈕缰盏,或者調(diào)用history上的go、back方法時淹遵,就會觸發(fā)事件口猜,打印出對應(yīng)的數(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)境下,都會默認(rèn)使用abstract模式侍咱,VueRouter內(nèi)部會根據(jù)所處的環(huán)境自行判斷耐床,默認(rèn)使用hash模式,如果檢測到?jīng)]有瀏覽器API的時候楔脯,就會使用abstract模式撩轰。



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

  1. 出現(xiàn)問題:在使用history模式的時候,由于瀏覽器路徑與后端路徑類似,所以當(dāng)刷新頁面的時候堪嫂,瀏覽器還是會向服務(wù)器發(fā)送請求偎箫,但是由于服務(wù)器并沒有對應(yīng)的路由頁面,所以會導(dǎo)致404空白
  2. 解決方案:在服務(wù)端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源皆串,則應(yīng)該返回同一個 index.html 頁面淹办,這個頁面就是你 app 依賴的頁面。同時這么做以后恶复,服務(wù)器就不再返回 404 錯誤頁面怜森,因為對于所有路徑都會返回 index.html 文件。為了避免這種情況寂玲,在 Vue 應(yīng)用里面覆蓋所有的路由情況塔插,然后在給出一個 404 頁面⊥赜矗或者想许,如果是用 Node.js 作后臺,可以使用服務(wù)端的路由來匹配 URL断序,當(dāng)沒有匹配到路由的時候返回 404流纹,從而實現(xiàn)后退。
    1. node服務(wù)器
      • 簡單粗暴的一種方法违诗,如果沒有讀取到靜態(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)服務(wù)器
      • 常用方式,直接使用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端口的下方新加入上述代碼,接著重復(fù)nginx -tnginx -s reload再次打開瀏覽器搪花,輸入localhost:8000就可以看到項目部署完成


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

  1. $route是路由信息對象痢畜,包括path垛膝、params、hash丁稀、query吼拥、fullPath、meta线衫、name等路由信息參數(shù)凿可,可以通過$route來獲取當(dāng)前路由的各種參數(shù)
    1. path String 保存當(dāng)前絕對路徑信息
    2. params Object 保存當(dāng)前的params參數(shù)對象
    3. hash String 保存當(dāng)前的hash信息,不帶#號授账,如果沒有hash為空字符串
    4. query Object 保存當(dāng)前的query參數(shù)對象
    5. meta Object 保存當(dāng)前路由的源信息
    6. fullPath String 保存完成解析后的路徑信息枯跑,包含hash、query等參數(shù)
    7. name String 保存路由name值
  2. $router是路由實例對象白热,包含的是VueRouter實例上的方法以及配置屬性敛助,常用于編程式導(dǎo)航;
    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進行前進
    4. ······


自定義過濾器詳解

  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> // 2019/7/10 下午12:00:17
      
    2. 有參數(shù)過濾器
      Vue.filter('formatPrice', function(value, num) {
            if(!value) return;
            return value.toFixed(num);
      }) 
      // html
      <div>{{ 15.6264 | formatPrice(2)}}</div> // 15.63
      
    3. 多個參數(shù)的過濾器
      Vue.filter('formatText', function(value, start, end) {
            if(!value) return;
            return start + '-' + value + '-' + end;
      }) 
      // html
      <div>{{ '中間' | formatText('開始','結(jié)束')}}</div> // 開始-中間-結(jié)束
      
    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 會被當(dāng)成模塊請求, 例如:<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 地址: 前端常見面試題(六)@郝晨光

結(jié)言
感謝您的查閱二汛,本文由郝晨光整理并總結(jié)婿崭,代碼冗余或者有錯誤的地方望不吝賜教;菜鳥一枚肴颊,請多關(guān)照
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末氓栈,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子婿着,更是在濱河造成了極大的恐慌授瘦,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祟身,死亡現(xiàn)場離奇詭異奥务,居然都是意外死亡,警方通過查閱死者的電腦和手機袜硫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門氯葬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人婉陷,你說我怎么就攤上這事帚称。” “怎么了秽澳?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵闯睹,是天一觀的道長。 經(jīng)常有香客問我担神,道長楼吃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任妄讯,我火速辦了婚禮孩锡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘亥贸。我一直安慰自己躬窜,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布炕置。 她就那樣靜靜地躺著荣挨,像睡著了一般男韧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上默垄,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天此虑,我揣著相機與錄音,去河邊找鬼厕倍。 笑死寡壮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的讹弯。 我是一名探鬼主播况既,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼组民!你這毒婦竟也來了棒仍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤臭胜,失蹤者是張志新(化名)和其女友劉穎莫其,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耸三,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡乱陡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了仪壮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片憨颠。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖积锅,靈堂內(nèi)的尸體忽然破棺而出爽彤,到底是詐尸還是另有隱情,我是刑警寧澤缚陷,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布适篙,位于F島的核電站,受9級特大地震影響箫爷,放射性物質(zhì)發(fā)生泄漏嚷节。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一虎锚、第九天 我趴在偏房一處隱蔽的房頂上張望硫痰。 院中可真熱鬧,春花似錦翁都、人聲如沸碍论。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鳍悠。三九已至,卻和暖如春坐搔,著一層夾襖步出監(jiān)牢的瞬間藏研,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工概行, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蠢挡,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓凳忙,卻偏偏與公主長得像业踏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子涧卵,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348