整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          新來的前端小姐姐問:Vue路由history模式刷新頁面出現404問題

          ??此賬號為華為云開發者社區官方運營賬號,提供全面深入的云計算前景分析、豐富的技術干貨、程序樣例,分享華為云前沿資訊動態


          本文分享自華為云社區《學習VueRouter,HTML5 History 模式,因為history模式刷新頁面會出現404》,作者: DevFeng 。


          vue-router 默認 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,于是當 URL 改變時,頁面不會重新加載。

          如果不想要很丑的 hash,我們可以用路由的 history 模式,這種模式充分利用 history.pushState API 來完成 URL 跳轉而無須重新加載頁面。

          const router = new VueRouter({
            mode: 'history',
            routes: [...]
          })

          當你使用 history 模式時,URL 就像正常的 url,例如 http://yoursite.com/user/id,也好看!

          不過這種模式要玩好,還需要后臺配置支持。因為我們的應用是個單頁客戶端應用,如果后臺沒有正確的配置,當用戶在瀏覽器直接訪問 http://oursite.com/user/id 就會返回 404,這就不好看了。

          所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。

          #后端配置例子

          注意:下列示例假設你在根目錄服務這個應用。如果想部署到一個子目錄,你需要使用 VueCLI 的

          publicPath 選項 (opens new window)和相關的 router base property (opens new window)。你還需要把下列示例中的根目錄調整成為子目錄 (例如用 RewriteBase /name-of-your-subfolder/ 替換掉 RewriteBase/)。

          #Apache

          <IfModule mod_rewrite.c>
            RewriteEngine On
            RewriteBase /
            RewriteRule ^index\.html$ - [L]
            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteCond %{REQUEST_FILENAME} !-d
            RewriteRule . /index.html [L]
          </IfModule>

          除了 mod_rewrite,你也可以使用 FallbackResource (opens new window)。

          #nginx

          location / {
            try_files $uri $uri/ /index.html;
          }

          #原生 Node.js

          const http = require('http')
          const fs = require('fs')
          const httpPort = 80
          
          http.createServer((req, res) => {
            fs.readFile('index.html', 'utf-8', (err, content) => {
              if (err) {
                console.log('We cannot open "index.html" file.')
              }
          
              res.writeHead(200, {
                'Content-Type': 'text/html; charset=utf-8'
              })
          
              res.end(content)
            })
          }).listen(httpPort, () => {
            console.log('Server listening on: http://localhost:%s', httpPort)
          })

          #基于 Node.js 的 Express

          對于Node.js/Express,請考慮使用 connect-history-api-fallback 中間件 (opens new window)。

          #Internet InformationServices (IIS)

          1. 安裝 IIS UrlRewrite(opens new window)

          2. 在你的網站根目錄中創建一個 web.config 文件,內容如下:

          <?xml version="1.0" encoding="UTF-8"?>
          <configuration>
            <system.webServer>
              <rewrite>
                <rules>
                  <rule name="Handle History Mode and custom 404/500" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions logicalGrouping="MatchAll">
                      <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                      <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/" />
                  </rule>
                </rules>
              </rewrite>
            </system.webServer>
          </configuration>

          #Caddy

          rewrite {
              regexp .*
              to {path} /
          }

          #Firebase 主機

          在你的 firebase.json 中加入:

          {
            "hosting": {
              "public": "dist",
              "rewrites": [
                {
                  "source": "**",
                  "destination": "/index.html"
                }
              ]
            }
          }

          #警告

          給個警告,因為這么做以后,你的服務器就不再返回 404 錯誤頁面,因為對于所有路徑都會返回

          index.html 文件。為了避免這種情況,你應該在 Vue 應用里面覆蓋所有的路由情況,然后再給出一個 404 頁面。

          const router = new VueRouter({
            mode: 'history',
            routes: [
              { path: '*', component: NotFoundComponent }
            ]
          })

          或者,如果你使用 Node.js 服務器,你可以用服務端路由匹配到來的 URL,并在沒有匹配到路由的時候返回 404,以實現回退。


          點擊關注,第一時間了解華為云新鮮技術~華為云博客_大數據博客_AI博客_云計算博客_開發者中心-華為云

          、良生- input type=file與文件上傳

          本文所說的input type=file指的是type類型是file的input元素,最簡HTML代碼如下:

          <input type=file>

          但是,為了習慣,我們多寫成:

          <input type="file">

          在HTML5出現之前(XHTML),我們的閉合規則則有些出入:

          <input type="file" />

          顧名思義,選擇文件,并上傳文件。

          在萬惡的舊時代,HTML5還沒有出現之前,原生的file input表單元素只能讓我們一次上傳一張圖片。無法滿足一次上傳多圖的交互需求,所以,很多場景,就被swfupload.js給取代了,有點逐漸淡出人們視野的感覺。

          然,技術發展,日新月異,三十年河東,三十年河西。隨著原生HTML5表單對多圖(multiple屬性)、上傳前預覽,二進制上傳等支持越來越廣泛,原生的file input表單元素又迎來了新的升級,flash為背景的swfupload.js注定要落寞。

          但是,對于PC項目,IE8-IE9瀏覽器還是不能忽略的。所以,現在,很流行的一種處理方式,就是HTML5 file上傳和flash swfupload上傳一起整合的模式,優先使用原生HTML5上傳,不支持的,使用flash上傳。我之前有篇關于HTML5上傳的文章,每天訪問量很高的:“基于HTML5的可預覽多圖片Ajax上傳”,大家有興趣可以看看。

          如果想使用瀏覽器原生特性實現文件上傳(如圖片)效果,父級的form元素有個東西不能丟,就是:

          enctype="multipart/form-data"

          enctype屬性規定在發送到服務器之前應該如何對表單數據進行編碼,默認的編碼是:”application/x-www-form-urlencoded“。對于普通數據是挺適用的,但是,對于文件,科科,就不能亂編碼了,該什么就是什么,只能使用multipart/form-data作為enctype屬性值。

          無論是舊時代的單圖上傳,還是HTML5中的多圖上傳,均是如此。

          文件,尤其圖片,上場前能夠預覽,是很棒的交互體驗。不走服務器,不耗費流量,多棒!

          理想雖好,實現起來……

          在HTML5還沒出現的舊時代,只有低版本的IE瀏覽器貌似有方法,使用私有的濾鏡,超越安全的限制(其實是利用了不好的東西),實現圖片直接預覽;但是呢,那個時候,Chrome, FireFox沒有這一出,于是,想要使用原生file input實現圖片的上傳前預覽,兼容性坎很難跨過去。

          但是,后來,HTML5來了,我們出現了轉機,IE10+以及其他現代瀏覽器,可以讓我們直接讀取圖片的數據,然后在頁面上呈現,實現了上傳前預覽;加上之前老IE的濾鏡策略,貌似,可行。但是呢但是,老的IE瀏覽器只能最多一次選擇一個文件,因此,只有單圖上傳的時候,大家可以考慮考慮。

          傳統的form提交,是要改變頁面流的,也就是刷新后跳轉。好的體驗應該是走Ajax交互的。HTML5里面支持二進制formData數據提交,因此,可以從容Ajax提交上傳的文件數據;那老舊的IE瀏覽器怎么辦?

          一般方法如下:

          <form action="" method="post" enctype="multipart/form-data" target="uploadIframe">< <iframe id="uploadIframe"></iframe>

          var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document; var response = doc.body && doc.body.innerHTML;

          OK, 當然,你也可以不用像上面這么麻煩,直接使用jquery.form.js. 原理呢,就是上面這樣,但是,不需要這么麻煩。

          原生的file input不收待見的另外一個原因是:長的丑還不好控制。

          舉個例子,下圖這個“選擇文件”這幾個文字,我們就不好對file控件動刀子實現自定義:

          file input框

          怎么辦呢?

          有一種方法是這樣的: 讓file類型的元素透明度0,覆蓋在我們好看的按鈕上。然后我們去點擊好看的按鈕,實際上點擊是是file元素。

          然而,此方法有一些不足:

          更好的方法是,使用label元素與file控件關聯,好處在于:

          <label class="ui_button ui_button_primary" for="xFile">上傳文件</label> <form><input type="file" id="xFile" style="position:absolute;clip:rect(0 0 0 0);"></form>

          效果如下(真實實時效果):

          input file類型控件有一個屬性,名為

          accept

          , 可能有些小伙伴不太了解。可以用來指定瀏覽器接受的文件類型,也就是的那個我們打開系統的選擇文件彈框的時候,默認界面中呈現的文件類型。例如:

          accept="image/jpeg"

          ,則界面中只有jpg圖片,如下截圖,同時,窗體右下方是“自定義文件”按鈕:

          自定義文件

          實際開發的時候,很少只允許傳jpg圖片,應該都是只能傳圖片類型,此時,可以使用:

          accept="image/*"

          于是乎,“自定義文件”按鈕變成了語義更明確的“圖片文件”:

          圖片文件

          accept屬性值其實是MIME類型, 例如下面幾個可能常用的:

          accept="application/pdf" accept="audio/x-mpeg" accept="text/html" .accept="video/x-mpeg2"

          然后,多個屬性值使用逗號分隔,例如:

          <input accept="audio/*,video/*,image/*">

          現代瀏覽器直接value = "", 有些IE瀏覽器貌似不行,好像使用file.outerHTML = file.outerHTML,我自己沒測試。

          不過我覺得比較麻煩,還要判斷瀏覽器什么的。像本文的Ajax單圖上傳,直接form.reset()就可以了。

          以上~

          本文為原創文章,會經常更新知識點以及修正一些錯誤,因此轉載請保留原出處,方便溯源,避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。

          下面試題不分先后順序

          1、vue實現雙向數據綁定原理是什么?

          八股文不想寫了自己百度吧...

          2、v-model語法糖是怎么實現的

          3、Hash和history有什么區別

          Hash模式

          1、定義

          hash 模式是一種把前端路由的路徑用井號 # 拼接在真實 url 后面的模式。當井號 # 后面的路徑發生變化時,瀏覽器并不會重新發起請求,而是會觸發 onhashchange 事件。

          2、網頁url組成部分

          (1)了解幾個url的屬性

          屬性

          含義

          location.protocal

          協議

          location.hostname

          主機名

          location.host

          主機

          location.port

          端口號

          location.patchname

          訪問頁面

          location.search

          搜索內容

          location.hash

          哈希值

          (2)演示

          下面用一個網址來演示以上屬性:

          History模式

          hash的特點

          • hash變化會觸發網頁跳轉,即瀏覽器的前進和后退。
          • hash 可以改變 url ,但是不會觸發頁面重新加載(hash的改變是記錄在 window.history 中),即不會刷新頁面。也就是說,所有頁面的跳轉都是在客戶端進行操作。因此,這并不算是一次 http 請求,所以這種模式不利于 SEO 優化。hash 只能修改 # 后面的部分,所以只能跳轉到與當前 url 同文檔的 url
          • hash 通過 window.onhashchange 的方式,來監聽 hash 的改變,借此實現無刷新跳轉的功能。
          • hash 永遠不會提交到 server 端(可以理解為只在前端自生自滅)。三、History模式

          1、定義

          history APIH5 提供的新特性,允許開發者直接更改前端路由,即更新瀏覽器 URL 地址而不重新發起請求。

          2、與hash的區別

          我們用一個例子來演示, hashhistory 在瀏覽器下刷新時的區別。具體如下:

          正常頁面瀏覽

          改造H5 history模式

          3、history的API

          下面闡述幾種 HTML5 新增的 history API 。具體如下表:

          API

          定義

          history.pushState(data, title [, url])

          pushState主要用于往歷史記錄堆棧頂部添加一條記錄。各參數解析如下:①data會在onpopstate事件觸發時作為參數傳遞過去;②title為頁面標題,當前所有瀏覽器都會忽略此參數;③url為頁面地址,可選,缺少時表示為當前頁地址

          history.replaceState(data, title [, url])

          更改當前的歷史記錄,參數同上; 上面的pushState是添加,這個更改

          history.state

          用于存儲以上方法的data數據,不同瀏覽器的讀寫權限不一樣

          window.onpopstate

          響應pushState或者replaceState的調用

          4、history的特點

          對于 history 來說,主要有以下特點:

          • 新的 url 可以是與當前 url 同源的任意 url ,也可以是與當前 url 一樣的地址,但是這樣會導致的一個問題是,會把重復的這一次操作記錄到棧當中。
          • 通過 history.state ,添加任意類型的數據到記錄中。
          • 可以額外設置 title 屬性,以便后續使用。
          • 通過 pushState 、 replaceState 來實現無刷新跳轉的功能。

          5、存在問題

          對于 history 來說,確實解決了不少 hash 存在的問題,但是也帶來了新的問題。

          具體如下:

          • 使用 history 模式時,在對當前的頁面進行刷新時,此時瀏覽器會重新發起請求。如果 nginx 沒有匹配得到當前的 url ,就會出現 404 的頁面。
          • 而對于 hash 模式來說, 它雖然看著是改變了 url ,但不會被包括在 http 請求中。所以,它算是被用來指導瀏覽器的動作,并不影響服務器端。因此,改變 hash 并沒有真正地改變 url ,所以頁面路徑還是之前的路徑, nginx 也就不會攔截。
          • 因此,在使用 history 模式時,需要通過服務端來允許地址可訪問,如果沒有設置,就很容易導致出現 404 的局面。

          6、兩者選擇

          下面我們再來介紹下在實際的項目中,如何對這兩者進行選擇。具體如下:

          • to B 的系統推薦用 hash ,相對簡單且容易使用,且因為 hashurl 規范不敏感;
          • to C 的系統,可以考慮選擇 H5 history ,但是需要服務端支持;
          • 能先用簡單的,就別用復雜的,要考慮成本和收益。

          4、什么是深拷貝和淺拷貝?以及怎么實現深拷貝和淺拷貝?

          淺拷貝與深拷貝

          • 淺拷貝是創建一個新對象,這個對象有著原始對象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果屬性是引用類型,拷貝的就是內存地址 ,所以如果其中一個對象改變了這個地址,就會影響到另一個對象。
          • 深拷貝是將一個對象從內存中完整的拷貝一份出來,從堆內存中開辟一個新的區域存放新對象,且修改新對象不會影響原對象

          借助ConardLi大佬以下兩張圖片,幫我們更好的理解兩者的含義:

          總而言之,淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。但深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。

          5、什么是原型什么是原型鏈?

          var person = new Person()

          console.log(person.constructor === Person) // true

          當獲取person.constructor時,其實person中并沒有constructor屬性,當不能讀取到constructor屬性時,會從person的原型,也就是Person.prototype中讀取時,正好原型中有該屬性,所以 person.constructor === Person.prototype.constructor

          其次是__proto__,絕大部分瀏覽器都支持這個非標準的方法訪問原型,然而它并不存在于Person.prototype中。

          實際上,它是來自與Object.prototype,與其說是一個屬性,不如說是一個getter/setter,當使用obj.__proto__時,可以理解成返回了Object.getPrototypeOf(obj) 。

          總結:

          1. 當一個對象查找屬性和方法時會從自身查找,如果查找不到則會通過__proto__指向被實例化的構造函數的prototype
          2. 隱式原型也是一個對象,是指向我們構造函數的原型
          3. 除了最頂層的Object對象沒有__proto_,其他所有的對象都有__proto__,這是隱式原型
          4. 隱式原型__proto__的作用是讓對象通過它來一直往上查找屬性或方法,直到找到最頂層的Object的__proto__屬性,它的值是null,這個查找的過程就是原型鏈

          6、箭頭函數和普通函數有什么區別?

          1. 箭頭函數比普通函數更加簡潔。

          如果沒有參數,就直接寫一個空括號即可

          如果只有一個參數,可以省去參數括號

          如果有多個參數,用逗號分割

          如果函數體的返回值只有一句,可以省略大括號

          如果函數體不需要返回值,且只有一句話,可以給這個語句前面加一個void關鍵字。

          最常用的就是調用一個函數:

          let fn = () => void doesNotReturn()

          1. 箭頭函數沒有自己的this

          箭頭函數不會創建自己的this,所以它沒有自己的this,它只會在自己作用域的上一層繼承this。所以箭頭函數中的this的指向在它在定義時一家確定了,之后不會改變。


          1. 箭頭函數繼承來的this指向永遠不會改變
          2. call()、apply()、bind()等方法不能改變箭頭函數中的this指向
          3. 箭頭函數不能作為構造函數使用
          4. 箭頭函數沒有自己的arguments
          5. 箭頭函數沒有prototype
          6. 箭頭函數不能用作Generator函數,不能使用yeild關鍵字

          7、New操作符做了什么事情?

          8、說一下eventloop

          戳右邊鏈接https://segmentfault.com/a/1190000016278115

          9、什么是閉包,閉包的作用是什么

          當一個內部函數被調用,就會形成閉包,閉包就是能夠讀取其他函數內部變量的函數。

          閉包作用:

          局部變量無法共享和長久的保存,而全局變量可能造成變量污染,所以我們希望有一種機制既可以長久的保存變量又不會造成全局污染。

          10、Promise是什么?

          Promise 是異步編程的一種解決方案:從語法上講,promise是一個對象,從它可以獲取異步操作的消息;從本意上講,它是承諾,承諾它過一段時間會給你一個結果。promise有三種狀態: pending(等待態),fulfiled(成功態),rejected(失敗態) ;狀態一旦改變,就不會再變。創造promise實例后,它會立即執行。


          11、Set 和 Map有什么區別?

          12、map和foreach有什么區別

          foreach()方法會針對每一個元素執行提供得函數,該方法沒有返回值,是否會改變原數組取決與數組元素的類型是基本類型還是引用類型

          map()方法不會改變原數組的值,返回一個新數組,新數組中的值為原數組調用函數處理之后的值

          13、localStorage sessionStorage cookies 有什么區別?

          localStorage:以鍵值對的方式存儲 儲存時間沒有限制 永久生效 除非自己刪除記錄

          sessionStorage:當頁面關閉后被清理與其他相比不能同源窗口共享 是會話級別的存儲方式

          cookies數據不能超過4k 同時因為每次http請求都會攜帶cookie 所有cookie只適合保存很小的數據 如會話標識

          14、Vuex有哪些基本屬性?為什么 Vuex 的 mutation 中不能做異步操作?

          有五種,分別是 State、 Getter、Mutation 、Action、 Module

          1. state => 基本數據(數據源存放地)
          2. getters => 從基本數據派生出來的數據
          3. mutations => 提交更改數據的方法,同步
          4. actions => 像一個裝飾器,包裹mutations,使之可以異步。
          5. modules => 模塊化Vuex
          • Vuex中所有的狀態更新的唯一途徑都是mutation,異步操作通過 Action 來提交 mutation實現,這樣可以方便地跟蹤每一個狀態的變化,從而能夠實現一些工具幫助更好地了解我們的應用。
          • 每個mutation執行完成后都會對應到一個新的狀態變更,這樣devtools就可以打個快照存下來,然后就可以實現 time-travel 了。如果mutation支持異步操作,就沒有辦法知道狀態是何時更新的,無法很好的進行狀態的追蹤,給調試帶來困難。

          15、Loader和Plugin 有什么區別

          Loader:直譯為"加載器"。Webpack將一切文件視為模塊,但是webpack原生是只能解析js文件,如果想將其他文件也打包的話,就會用到`loader`。 所以Loader的作用是讓webpack擁有了加載和解析非JavaScript文件的能力。

          Plugin:直譯為"插件"。Plugin可以擴展webpack的功能,讓webpack具有更多的靈活性。 在 Webpack 運行的生命周期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機通過 Webpack 提供的 API 改變輸出結果。

          16、在地址欄里輸入一個地址回車會發生哪些事情

          1. 解析URL:首先會對 URL 進行解析,分析所需要使用的傳輸協議和請求的資源的路徑。如果輸入的 URL 中的協議或者主機名不合法,將會把地址欄中輸入的內容傳遞給搜索引擎。如果沒有問題,瀏覽器會檢查 URL 中是否出現了非法字符,如果存在非法字符,則對非法字符進行轉義后再進行下一過程。
          2. 緩存判斷:瀏覽器會判斷所請求的資源是否在緩存里,如果請求的資源在緩存里并且沒有失效,那么就直接使用,否則向服務器發起新的請求。
          3. DNS解析: 下一步首先需要獲取的是輸入的 URL 中的域名的 IP 地址,首先會判斷本地是否有該域名的 IP 地址的緩存,如果有則使用,如果沒有則向本地 DNS 服務器發起請求。本地 DNS 服務器也會先檢查是否存在緩存,如果沒有就會先向根域名服務器發起請求,獲得負責的頂級域名服務器的地址后,再向頂級域名服務器請求,然后獲得負責的權威域名服務器的地址后,再向權威域名服務器發起請求,最終獲得域名的 IP 地址后,本地 DNS 服務器再將這個 IP 地址返回給請求的用戶。用戶向本地 DNS 服務器發起請求屬于遞歸請求,本地 DNS 服務器向各級域名服務器發起請求屬于迭代請求。
          4. 獲取MAC地址: 當瀏覽器得到 IP 地址后,數據傳輸還需要知道目的主機 MAC 地址,因為應用層下發數據給傳輸層,TCP 協議會指定源端口號和目的端口號,然后下發給網絡層。網絡層會將本機地址作為源地址,獲取的 IP 地址作為目的地址。然后將下發給數據鏈路層,數據鏈路層的發送需要加入通信雙方的 MAC 地址,本機的 MAC 地址作為源 MAC 地址,目的 MAC 地址需要分情況處理。通過將 IP 地址與本機的子網掩碼相與,可以判斷是否與請求主機在同一個子網里,如果在同一個子網里,可以使用 APR 協議獲取到目的主機的 MAC 地址,如果不在一個子網里,那么請求應該轉發給網關,由它代為轉發,此時同樣可以通過 ARP 協議來獲取網關的 MAC 地址,此時目的主機的 MAC 地址應該為網關的地址。
          5. TCP三次握手: 下面是 TCP 建立連接的三次握手的過程,首先客戶端向服務器發送一個 SYN 連接請求報文段和一個隨機序號,服務端接收到請求后向客戶端發送一個 SYN ACK報文段,確認連接請求,并且也向客戶端發送一個隨機序號。客戶端接收服務器的確認應答后,進入連接建立的狀態,同時向服務器也發送一個ACK 確認報文段,服務器端接收到確認后,也進入連接建立狀態,此時雙方的連接就建立起來了。
          6. HTTPS握手: 如果使用的是 HTTPS 協議,在通信前還存在 TLS 的一個四次握手的過程。首先由客戶端向服務器端發送使用的協議的版本號、一個隨機數和可以使用的加密方法。服務器端收到后,確認加密的方法,也向客戶端發送一個隨機數和自己的數字證書??蛻舳耸盏胶螅紫葯z查數字證書是否有效,如果有效,則再生成一個隨機數,并使用證書中的公鑰對隨機數加密,然后發送給服務器端,并且還會提供一個前面所有內容的 hash 值供服務器端檢驗。服務器端接收后,使用自己的私鑰對數據解密,同時向客戶端發送一個前面所有內容的 hash 值供客戶端檢驗。這個時候雙方都有了三個隨機數,按照之前所約定的加密方法,使用這三個隨機數生成一把秘鑰,以后雙方通信前,就使用這個秘鑰對數據進行加密后再傳輸。
          7. 返回數據: 當頁面請求發送到服務器端后,服務器端會返回一個 html 文件作為響應,瀏覽器接收到響應后,開始對 html 文件進行解析,開始頁面的渲染過程。
          8. 頁面渲染: 瀏覽器首先會根據 html 文件構建 DOM 樹,根據解析到的 css 文件構建 CSSOM 樹,如果遇到 script 標簽,則判端是否含有 defer 或者 async 屬性,要不然 script 的加載和執行會造成頁面的渲染的阻塞。當 DOM 樹和 CSSOM 樹建立好后,根據它們來構建渲染樹。渲染樹構建好后,會根據渲染樹來進行布局。布局完成后,最后使用瀏覽器的 UI 接口對頁面進行繪制。這個時候整個頁面就顯示出來了。
          9. TCP四次揮手: 最后一步是 TCP 斷開連接的四次揮手過程。若客戶端認為數據發送完成,則它需要向服務端發送連接釋放請求。服務端收到連接釋放請求后,會告訴應用層要釋放 TCP 鏈接。然后會發送 ACK 包,并進入 CLOSE_WAIT 狀態,此時表明客戶端到服務端的連接已經釋放,不再接收客戶端發的數據了。但是因為 TCP 連接是雙向的,所以服務端仍舊可以發送數據給客戶端。服務端如果此時還有沒發完的數據會繼續發送,完畢后會向客戶端發送連接釋放請求,然后服務端便進入 LAST-ACK 狀態。客戶端收到釋放請求后,向服務端發送確認應答,此時客戶端進入 TIME-WAIT 狀態。該狀態會持續 2MSL(最大段生存期,指報文段在網絡中生存的時間,超時會被拋棄) 時間,若該時間段內沒有服務端的重發請求的話,就進入 CLOSED 狀態。當服務端收到確認應答后,也便進入 CLOSED 狀態。

          17、UDP和TCP有什么區別

          18、項目中常用的性能優化方式有哪些?

          太多了,自己整理吧-.-

          19、怎么解決跨域問題的,你是怎么配置的

          20、計算屬性和watch有什么區別?以及它們的運用場景?

          區別:

          computed 計算屬性:依賴其它屬性值,并且computed的值有緩存,只有它依賴的屬性值發生改變,下一次獲取computed的值時才會重新計算computed的值。

          watch 偵聽器:更多的是觀察的作用,無緩存性,類似與某些數據的監聽回調,每當監聽的數據變化時都會執行回調進行后續操作

          運用場景:

          當需要進行數值計算,并且依賴與其它數據時,應該使用computed,因為可以利用computed的緩存屬性,避免每次獲取值時都要重新計算。

          當需要在數據變化時執行異步或開銷較大的操作時,應該使用watch,使用watch選項允許執行異步操作(訪問一個API),限制執行該操作的頻率,并在得到最終結果前,設置中間狀態。這些都是計算屬性無法做到的。

          21、Vue的生命周期是什么 每個鉤子里面具體做了什么事情

          Vue 實例有?個完整的?命周期,也就是從開始創建、初始化數據、編譯模版、掛載Dom -> 渲染、更新 -> 渲染、卸載等?系列過程,稱這是Vue的?命周期。

          1. beforeCreate(創建前) :數據觀測和初始化事件還未開始,此時 data 的響應式追蹤、event/watcher 都還沒有被設置,也就是說不能訪問到data、computed、watch、methods上的方法和數據。
          2. created(創建后) :實例創建完成,實例上配置的 options 包括 data、computed、watch、methods 等都配置完成,但是此時渲染得節點還未掛載到 DOM,所以不能訪問到 `$el` 屬性。
          3. beforeMount(掛載前) :在掛載開始之前被調用,相關的render函數首次被調用。實例已完成以下的配置:編譯模板,把data里面的數據和模板生成html。此時還沒有掛載html到頁面上。
          4. mounted(掛載后) :在el被新創建的 vm.$el 替換,并掛載到實例上去之后調用。實例已完成以下的配置:用上面編譯好的html內容替換el屬性指向的DOM對象。完成模板中的html渲染到html 頁面中。此過程中進行ajax交互。
          5. beforeUpdate(更新前) :響應式數據更新時調用,此時雖然響應式數據更新了,但是對應的真實 DOM 還沒有被渲染。
          6. updated(更新后):在由于數據更改導致的虛擬DOM重新渲染和打補丁之后調用。此時 DOM 已經根據響應式數據的變化更新了。調用時,組件 DOM已經更新,所以可以執行依賴于DOM的操作。然而在大多數情況下,應該避免在此期間更改狀態,因為這可能會導致更新無限循環。該鉤子在服務器端渲染期間不被調用。
          7. beforeDestroy(銷毀前) :實例銷毀之前調用。這一步,實例仍然完全可用,`this` 仍能獲取到實例。
          8. destroyed(銷毀后) :實例銷毀后調用,調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。該鉤子在服務端渲染期間不被調用。 另外還有 `keep-alive` 獨有的生命周期,分別為 `activated` 和 `deactivated` 。用 `keep-alive` 包裹的組件在切換時不會進行銷毀,而是緩存到內存中并執行 `deactivated` 鉤子函數,命中緩存渲染后會執行 `activated` 鉤子函數。

          22、組件之間的傳值有幾種方式

          23、Eventbus具體是怎么實現的

          24、父組件到子組件更新的方式是什么樣的

          25、$nexttick 是干嘛的,你一般拿它做什么

          26、Keepalive 是什么,里面有哪些鉤子

          27、插槽是什么 怎么使用的

          28、Es6常見的語法你知道哪一些

          29、自定義指令你是怎么用的

          30、重繪和重排

          31、常見的水平垂直方式有幾種?

          //利用絕對定位,先將元素的左上角通過 top:50%和 left:50%定位到頁面的中心,然后再通過 translate 來調整元素的中心點到頁面的中心。該方法需要考慮瀏覽器兼容問題。


          //利用絕對定位,設置四個方向的值都為 0,并將 margin 設置為 auto,由于寬高固定,因此對應方向實現平分,可以實現水平和垂直方向上的居中。該方法適用于盒子有寬高的情況:

          //利用絕對定位,先將元素的左上角通過 top:50%和 left:50%定位到頁面的中心,然后再通過 margin 負值來調整元素的中心點到頁面的中心。該方法適用于盒子寬高已知的情況


          //使用 flex 布局,通過 align-items:center 和 justify-content:center 設置容器的垂直和水平方向上為居中對齊,然后它的子元素也可以實現垂直和水平的居中。該方法要**考慮兼容的問題**,該方法在移動端用的較多:


          //另外,如果父元素設置了flex布局,只需要給子元素加上`margin:auto;`就可以實現垂直居中布局

          32、標準盒模型和怪異盒模型

          33、Flex常見的屬性 flex:1代表什么

          34、Rem你是怎么做適配的

          35、媒體查詢是什么

          36、首屏性能優化你是怎么做的

          37、怎么解決白屏問題

          38、瀏覽器的性能監控你是怎么做的

          戳右邊鏈接https://blog.csdn.net/qq_29438877/article/details/103998284

          39、Diff算法是什么 :key = index 為什么不常用數組的下標作為index 加了它有什么好處

          40、虛擬列表你是怎么實現的

          41、說一下防抖和節流

          42、哪些情況會導致內存泄漏

          1. 意外的全局變量:由于使用未聲明的變量,而意外的創建了一個全局變量,而使這個變量一直留在內存中無法被回收
          2. 被遺忘的計時器或回調函數:設置了 setInterval 定時器,而忘記取消它,如果循環函數有對外部變量的引用的話,那么這個變量會被一直留在內存中,而無法被回收。
          3. 脫離 DOM 的引用:獲取一個 DOM 元素的引用,而后面這個元素被刪除,由于一直保留了對這個元素的引用,所以它也無法被回收。
          4. 閉包:不合理的使用閉包,從而導致某些變量一直被留在內存當中。

          43、Vue的父子組件生命周期鉤子函數執行順序?

          44、說一下常見的檢測數據類型的幾種方式?

          • typeof 其中數組、對象、null都會被判斷為Object,其他判斷都正確
          • instanceof 只能判斷引用數據類型,不能判斷基本數據類型 constructor 它有2個作用 一是判斷數據的類型,二是對象實例通過
          • constructor對象訪問它的構造函數。需要注意的事情是如果創建一個對象來改變它的原型,constructor就不能來判斷數據類型了
          • Object.prototype.toString.call()

          45、說一下data為什么是一個函數而不是一個對象?

          JavaScript中的對象是引用類型的數據,當多個實例引用同一個對象時,只要一個實例對這個對象進行操作,其他實例中的數據也會發生變化。而在Vue中,我們更多的是想要復用組件,那就需要每個組件都有自己的數據,這樣組件之間才不會相互干擾。所以組件的數據不能寫成對象的形式,而是要寫成函數的形式。數據以函數返回值的形式定義,這樣當我們每次復用組件的時候,就會返回一個新的data,也就是說每個組件都有自己的私有數據空間,它們各自維護自己的數據,不會干擾其他組件的正常運行。

          46、說一下slice splice split 的區別?


          47、說一下怎么把類數組轉換為數組?

          48、說一下數組如何去重,你有幾種方法?

          49、說一下怎么取出數組最多的一項?

          50、說一下JSON.stringify有什么缺點?

          1.如果obj里面有時間對象,則JSON.stringify后再JSON.parse的結果,時間將只是字符串的形式,而不是對象的形式

          2.如果obj里有RegExp(正則表達式的縮寫)、Error對象,則序列化的結果將只得到空對象

          3、如果obj里有函數,undefined,則序列化的結果會把函數或 undefined丟失

          4、如果obj里有NaN、Infinity和-Infinity,則序列化的結果會變成null

          5、JSON.stringify()只能序列化對象的可枚舉的自有屬性,例如 如果obj中的對象是有構造函數生成的, 則使用JSON.parse(JSON.stringify(obj))深拷貝后,會丟棄對象的constructor

          6、如果對象中存在循環引用的情況也無法正確實現深拷貝

          51、說一下for...in 和 for...of的區別?

          • for...of遍歷獲取的是對象的鍵值, for...in獲取的是對象的鍵名;
          • for...in會遍歷對象的整個原型鏈, 性能非常差不推薦使用,而for...of只遍歷當前對象不會遍歷原型鏈;
          • 對于數組的遍歷,for...in會返回數組中所有可枚舉的屬性(包括原型鏈上可枚舉的屬性),for...of只返回數組的下標對應的屬性值;

          總結:for...in循環主要是為了遍歷對象而生,不適用遍歷數組; for....of循環可以用來遍歷數組、類數組對象、字符串、Set、Map以及Generator對象

          52、說一下類組件和函數組件的區別?

          1. 語法上的區別:

          函數式組件是一個純函數,它是需要接受props參數并且返回一個React元素就可以了。類組件是需要繼承React.Component的,而且class組件需要創建render并且返回React元素,語法上來講更復雜。

          2. 調用方式

          函數式組件可以直接調用,返回一個新的React元素;類組件在調用時是需要創建一個實例的,然后通過調用實例里的render方法來返回一個React元素。

          3. 狀態管理

          函數式組件沒有狀態管理,類組件有狀態管理。

          4. 使用場景

          類組件沒有具體的要求。函數式組件一般是用在大型項目中來分割大組件(函數式組件不用創建實例,所有更高效),一般情況下能用函數式組件就不用類組件,提升效率。

          53、說一下react的更新機制

          答案戳這里:zhuanlan.zhihu.com/p/35801438

          54、說一下redux 里面有什么

          55、說一下react和vue框架的區別

          56、說一下proxy 它有什么優點

          57、說一下vue3.0你了解多少?

          58、說一下bfc bfc有什么優缺點

          59、說一下你對盒模型的理解?

          60、說一下SPA單頁面有什么優缺點?

          61、說一下前端登錄的流程?

          初次登錄的時候,前端調后調的登錄接口,發送用戶名和密碼,后端收到請求,驗證用戶名和密碼,驗證成功,就給前端返回一個token,和一個用戶信息的值,前端拿到token,將token儲存到Vuex中,然后從Vuex中把token的值存入瀏覽器Cookies中。

          把用戶信息存到Vuex然后再存儲到LocalStroage中,然后跳轉到下一個頁面,根據后端接口的要求,只要不登錄就不能訪問的頁面需要在前端每次跳轉頁面師判斷Cookies中是否有token,沒有就跳轉到登錄頁,有就跳轉到相應的頁面,我們應該再每次發送post/get請求的時候應該加入token,常用方法再項目utils/service.js中添加全局攔截器,將token的值放入請求頭中 后端判斷請求頭中有無token,有token,就拿到token并驗證token是否過期,在這里過期會返回無效的token然后有個跳回登錄頁面重新登錄并且清除本地用戶的信息

          62、說一下前端權限管理怎么實現

          答案戳這里https://blog.csdn.net/weixin_40599109/article/details/113728974

          63、說一下購物車的邏輯?

          vue中購物車邏輯的實現

          • 購物車信息用一個數組來存儲,數組中保存對象,對象中有id和count屬性
          • 在vuex中state中添加一個數據 cartList 用來保存這個數組
          • 由于商品詳情頁需要用到加入購物車功能,所以我們需要提供一個mutation, 用來將購物車信息加入 cartList中
          • 加入購物車信息的時候,遵照如下規則: 如果購物車中已經有了該商品信息,則數量累加,如果沒有該商品信息,則新增一個對象
          • 在商品詳情頁,點擊加入購物車按鈕的時候,調用vuex提供的addToCart這個mutation將當前的商品信息 (id count)傳給addTocart this.$store.commit("addToCart", {id: , count:})

          js中購物車邏輯的實現

          • 商品頁點擊“加入購物車”按鈕,觸發事件
          • 事件調用購物車“增加商品”的Js程序(函數、對象方法)
          • 向Js程序傳遞傳遞“商品id”、“商品數量”等數據
          • 存儲“商品id”、“商品數量”到瀏覽器的localStorage中

          **展示購物車中的商品******

          • 打開購物車頁面
          • 從localStorage中取出“商品Id”、“商品數量”等信息。
          • 調用服務器端“獲得商品詳情”的接口得到購物車中的商品信息(參數為商品Id)
          • 將獲得的商品信息顯示在購物車頁面。

          **完成購物車中商品的購買******

          • 用戶對購物車中的商品完成購買流程,產生購物訂單
          • 清除localStorage中存儲的已經購買的商品信息

          備注1:購物車中商品存儲的數據除了“商品id”、“商品數量”之外,根據產品要求還可以有其他的信息,例如完整的商品詳情(這樣就不用掉服務器接口獲得詳情了)、購物車商品的過期時間,超過時間的購物車商品在下次打開網站或者購物車頁面時被清除。

          備注2:購物車商品除了存儲在localStorage中,根據產品的需求不同,也可以存儲在sessionStorage、cookie、session中,或者直接向服務器接口發起請求存儲在服務器上。何種情況使用哪種方式存儲、有啥區別請自己分析。

          64、說一下HTTP和HTTPS協議的區別?

          1. HTTPS協議需要CA證書,費用較高;而HTTP協議不需要
          2. HTTP協議是超文本傳輸協議,信息是明文傳輸的,HTTPS則是具有安全性的SSL加密傳輸協議
          3. 使用不同的連接方式,端口也不同,HTTP協議端口是80,HTTPS協議端口是443
          4. HTTP協議連接很簡單,是無狀態的;HTTPS協議是具有SSL和HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比HTTP更加安全

          65、說一下常見的HTTP狀態碼?說一下狀態碼是302和304是什么意思?你在項目中出現過么?你是怎么解決的?

          <!-- 狀態碼:由3位數字組成,第一個數字定義了響應的類別 -->

          <!-- 1xx:指示消息,表示請求已接收,繼續處理 -->

          <!-- 2xx:成功,表示請求已被成功接收,處理 -->

          <!-- 200 OK:客戶端請求成功

          204 No Content:無內容。服務器成功處理,但未返回內容。一般用在只是客戶端向服務器發送信息,而服務器不用向客戶端返回什么信息的情況。不會刷新頁面。

          206 Partial Content:服務器已經完成了部分GET請求(客戶端進行了范圍請求)。響應報文中包含Content-Range指定范圍的實體內容 -->

          <!-- 3xx 重定向 -->

          <!-- 301 Moved Permanently:永久重定向,表示請求的資源已經永久的搬到了其他位置。

          302 Found:臨時重定向,表示請求的資源臨時搬到了其他位置

          303 See Other:臨時重定向,應使用GET定向獲取請求資源。303功能與302一樣,區別只是303明確客戶端應該使用GET訪問

          307 Temporary Redirect:臨時重定向,和302有著相同含義。POST不會變成GET

          304 Not Modified:表示客戶端發送附帶條件的請求(GET方法請求報文中的IF…)時,條件不滿足。返回304時,不包含任何響應主體。雖然304被劃分在3XX,但和重定向一毛錢關系都沒有 -->

          <!-- 4xx:客戶端錯誤 -->

          <!-- 400 Bad Request:客戶端請求有語法錯誤,服務器無法理解。

          401 Unauthorized:請求未經授權,這個狀態代碼必須和WWW-Authenticate報頭域一起使用。

          403 Forbidden:服務器收到請求,但是拒絕提供服務

          404 Not Found:請求資源不存在。比如,輸入了錯誤的url

          415 Unsupported media type:不支持的媒體類型 -->

          <!-- 5xx:服務器端錯誤,服務器未能實現合法的請求。 -->

          <!-- 500 Internal Server Error:服務器發生不可預期的錯誤。

          503 Server Unavailable:服務器當前不能處理客戶端的請求,一段時間后可能恢復正常, -->

          66、說一下常見的git操作

          我是cv的各位自取吧-。-




          原文鏈接:https://juejin.cn/post/7073869980411887652


          主站蜘蛛池模板: 国产午夜精品一区二区三区小说 | 亚洲A∨无码一区二区三区| 视频在线一区二区| 一本一道波多野结衣AV一区| 久久一区二区免费播放| 视频一区二区三区免费观看| 亚欧在线精品免费观看一区 | 精品欧洲av无码一区二区| 熟女少妇精品一区二区| 午夜福利国产一区二区| 免费在线视频一区| 国产视频一区在线播放| 韩国福利一区二区美女视频| 亚洲AV本道一区二区三区四区 | 亚洲高清日韩精品第一区| 亚洲综合无码一区二区| 国产在线精品一区二区三区直播| 亚洲国产成人久久综合一区77| 国产一区二区在线视频播放| 国产成人午夜精品一区二区三区| 亚洲国产情侣一区二区三区| 麻豆高清免费国产一区| 性色A码一区二区三区天美传媒| 亚洲线精品一区二区三区| 亚洲综合国产一区二区三区| 国产精品区一区二区三在线播放| 国产午夜福利精品一区二区三区| 国产亚洲日韩一区二区三区| 久久精品岛国av一区二区无码| 无码人妻精品一区二区三区久久| 亚洲国产成人一区二区三区| 亚洲va乱码一区二区三区| 无码日本电影一区二区网站| 国产亚洲福利一区二区免费看 | 国产一区二区三区在线观看免费| 精品国产免费观看一区| 亚洲国产一区二区三区| 波多野结衣的AV一区二区三区| 国产免费一区二区三区在线观看| 末成年女AV片一区二区| 无码少妇一区二区三区芒果|