1. 程式人生 > 其它 >前端面試總結

前端面試總結

總結

一. html/css

1.BFC

定義
BFC(Block formatting context)直譯為"塊級格式化上下文"。它是一個獨立的渲染區域,只有 塊級盒子參與,它規定了內部的 塊級盒子 如何佈局,並且與這個區域外部毫不相干
佈局規則
1、內部的 Box 會在垂直方向,一個接一個地放置
2、Box 垂直方向的距離由 margin 決定。屬於同一個 BFC 的兩個相鄰 Box 的 margin會發生重疊
3、每個元素的 margin box 的左邊, 與包含塊 border box 的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此
4、BFC 的區域不會與 浮動元素 重疊

5、BFC 就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素。反之也如此
6、計算 BFC 的高度時,浮動元素也參與計算
哪些元素會生成 BFC:
1、根元素
2、float 屬性不為 none
3、position 為 absolute 或 fixed
4、display 為 inline-block, table-cell, table-caption, flex, inline-flex
5、overflow 不為 visible

2.H5,cs3新特性

H5 新特性
1、拖拽釋放(Drap and drop) API ondrop
拖放是一種常見的特性,即抓取物件以後拖到另一個位置,在 HTML5 中,拖放是標準的一部分,任何元素都能夠拖放

2、自定義屬性 data-id
3、語義化更好的內容標籤(header,nav,footer ,aside, article, section)
4、音訊 ,視訊(audio, video) 如果瀏覽器不支援自動播放怎麼辦?在屬性中新增 autoplay
5、畫布 Canvas
5.1 getContext() 方法返回一個用於在畫布上繪圖的環境
Canvas.getContext(contextID) 引數 contextID 指定了您想要在畫布上繪製的型別。當前唯一的合法值是 “2d”,它指定了二維繪圖,並且導致這個方法返回 一個環境物件,該物件匯出一個二維繪圖 API
5.2 cxt.stroke() 如果沒有這一步 線條是不會顯示在畫布上的
5.3 canvas 和 image 在處理圖片的時候有什麼區別?
image 是通過物件的形式描述圖片的,canvas 通過專門的 API 將圖片繪製在畫布上.
6、 地理(Geolocation) API
7、 本地離線儲存 localStorage 長期儲存資料 瀏覽器關閉後資料不丟失
8、 sessionStorage 的資料在瀏覽器關閉後自動刪除
9、 表單控制元件 calendar , date , time , email , url , search , tel , file , number
10、新的技術 webworker, websocket , Geolocation

CSS3 新特性
1、顏色: 新增 RGBA , HSLA 模式
2、文字陰影(text-shadow)
3、邊框: 圓角(border-radius) 邊框陰影 : box-shadow
4、盒子模型: box-sizing
5、背景:background-size background-origin background-clip
6、漸變: linear-gradient , radial-gradient
7、過渡 : transition 可實現動畫
8、自定義動畫 animate @keyfrom
9、媒體查詢 多欄佈局 @media screen and (width:800px) {…}
10、border-image
11、2D 轉換;transform: translate(x,y) rotate(x,y) skew(x,y) scale(x,y)
12、3D 轉換
13、字型圖示 font-face
14、彈性佈局 flex

3.margin塌陷問題

外邊距塌陷共有兩種情況:
第一種情況:兩個同級元素,垂直排列,上面的盒子給 margin-bottom 下面的盒子給margin-top,那麼他們兩個的間距會重疊,以大的那個計算。解決這種情況
的方法為:兩個外邊距不同時出現
第二種情況:兩個父子元素,內部的盒子給 margin-top,其父級也會受到影響,同時產生上邊距,父子元素會進行粘連,解決這種情況的方法為:父級新增一個 css 屬性,overflow: hidden,禁止超出
外邊距重疊就是 margin-collapse
解決方案:
1、為父盒子設定 border,為外層新增 border 後父子盒子就不是真正意義上的貼合 (可
以設定成透明:border:1px solid transparent)。
2、為父盒子新增 overflow:hidden;
3、為父盒子設定 padding 值;
4、為父盒子新增 position:fixed;
5、為父盒子新增 display:table;
6、利用偽元素給子元素的前面新增一個空元素
.son:before{ content:"";
overflow:hidden; }

4.flex佈局

父容器上的屬性

  .father {
      display: flex;   
      flex-flow: row wrap;      flex-direction和flex-wrap的合寫,設定主軸方向(row橫向,column縱向),和是否換行wrap、nowrap
      justify-content: space-between;   主軸對齊方式 
      /* align-items: center; */      一行時,側軸對齊方式
      align-content: space-around;   多行時,側軸對齊方式
    }

子容器上的屬性

order:0;     子項的前後順序,越小越靠前,預設是0
flex-grow: 0;   子項的放大比例。預設是0,不放大
flex-shrink:1;  子項的縮小比例,預設是1,不縮小
flex-basis:auto;  子項佔據的主軸空間
align-self:auto;  單個子項的對齊方式

合寫屬性

flex:flex-grow   flex-shrink flex-basis;
flex:1;是   1          1        0%                  專案自動填充
flex:auto;  1          1        auto
flex:20px/20%; 1      1        20px/ 20%      長度單位或者百分比

flex佈局的相容性 ,,,,,,,,,

5.grid佈局
  .father {
      width: 100%;
      height: 500px;
      display: grid;
      grid-template-columns: 100px 100px 100px 200px;
      grid-template-rows: 100px 100px;
      grid-gap: 10px 30px;
      place-content: start center;
    }
6.三角形

寬高都為0的盒子,通過border設定邊框寬度和顏色,把其他三邊顏色設為透明,就可以出一個三角形

7.rgba和opacity

opacity屬性的值,可以被其子元素繼承,給父級div設定opacity屬性,那麼所有子元素都會繼承這個屬性,並且,該元素及其繼承該屬性的所有子元素的所有內容透明度都會改變。而RGBA設定的元素,只對該元素的背景色有改變,並且,該元素的後代不會繼承該屬性。

8.左邊100px,右邊自適應場景

給父元素設定display:flex; 然後右邊直接flex:1;

9.為什麼會有浮動,清除浮動的方法

浮動定位將元素排除在普通流之外,即元素講脫離文件流,不佔據空間。浮動元素碰到包含它的邊框或者浮動元素的邊框停留
為什麼需要清除浮動
1、父元素的高度無法被撐開,影響與父元素同級的元素;
2、與浮動元素同級的非浮動元素(內聯元素)會跟隨其後;
3、若非第一個元素浮動,則該元素之前的元素也需要浮動,否則會影響頁面顯示的結構
清除浮動的方式
1、父級盒子定義高度,height 簡單粗暴,但是隻適合高度固定的佈局

​ 2、結尾處加空div,並給這個空div上加上clear:both; 能讓父級div自動獲取高度,但是這種做法會增加很多空div,讓人感覺不好

​ 3、父級盒子上加上overflow:hidden; 缺點是溢位部分會被隱藏

​ 4、父級盒子定義 偽元素after,考慮相容ie,需要zoom(設定zoom:1可以在IE6下清除浮動、解決margin導致的重疊等問題)

 .parents::after {
      content: '';
      display: block;
      clear: both;
    }
  .parents {
      zoom: 1;
    }

​ 5、雙偽元素法(4方法 的升級) 四五方法一樣,就是在父元素的頭和尾加偽元素撐起父元素

 .parents::before,
    .parents::after {
      content: '';
      display: block;
      clear: both;
    }

  .parents {
      zoom: 1;
    }
10.less和sass

sass 與 less 都是預編譯(預處理)的css語言

LESS和Sass的他們的實現方式:Less是基於JavaScript,是在客戶端處理的。
Sass是基於Ruby,是在伺服器端處理的

11.響應式佈局及實現
  1. 百分比佈局
  2. bootstrap柵格系統(antdesign 裡面的珊格佈局)
  3. Flex 伸縮盒佈局
  4. 媒體查詢
12.css哪些屬性可以繼承,哪些不行

​ 能繼承的屬性

  1. 字體系列屬性:font、font-family、font-weight、font-size、font-style;

  2. 文本系列屬性:
    2.1內聯元素:color、line-height、word-spacing、letter-spacing、
    text-transform;
    2.2塊級元素:text-indent、text-align;

  3. 元素可見性:visibility

  4. 表格佈局屬性:caption-side、border-collapse、border-spacing、empty-cells、
    table-layout;

  5. 列表佈局屬性:list-style

不能繼承的屬性

  1. display:規定元素應該生成的框的型別;

  2. 文字屬性:vertical-align、text-decoration;

  3. 盒子模型的屬性:width、height、margin 、border、padding;

  4. 背景屬性:background、background-color、background-image;

  5. 定位屬性:float、clear、position、top、right、bottom、left、min-width、
    min-height、max-width、max-height、overflow、clip;

12.盒模型(標準盒模型和ie盒模型)

盒子模型(Box Modle)可以用來對元素進行佈局,包括內邊距,邊框,外邊距,和實際內容這幾個部分

標準盒模型下盒子的大小 = content + border + padding + margin

ie盒模型下盒子的大小 = width(content + border + padding) + margin

二.js

1.es6
  • let和const關鍵字

    • let 定義變數,變數不可以再次定義,但可以改變其值
    • 具有塊級作用域
    • 沒有變數提升,必須先定義再使用
    • let宣告的變數不會壓到window物件中,是獨立的

    • 使用const關鍵字定義常量
    • 常量是不可變的,一旦定義,則不能修改其值
    • 初始化常量時,必須給初始值
    • 具有塊級作用域
    • 沒有變數提升,必須先定義再使用
    • 常量也是獨立的,定義後不會壓入到window物件中
  • 解構賦值

    ES 6 允許按照一定**模式**,從陣列和物件中提取值,對變數進行賦值,這被稱為解構(Destructuring)

    物件、陣列的解構賦值。直接用=號

    // 假設從伺服器上獲取的資料如下
    let response = {
        data: ['a', 'b', 'c'],
        meta: {
            code: 200,
            msg: '獲取資料成功'
        }
    }
    // 如何獲取到 code 和 msg
    let { meta: { code, msg } } = response;
    console.log(code, msg); // 200, 獲取資料成功
    
  • 箭頭函式

    ES6 中允許使用箭頭定義函式 (=> goes to),目的是簡化函式的定義,並且裡面的this也比較特殊(箭頭函式內部的 this 指向外部作用域中的 this ,或者可以認為箭頭函式沒有自己的 this

    MDN解釋:箭頭函式不會建立自己的this,它只會從自己的作用域鏈的上一層繼承this

  • 函式引數預設值

    es6可以給函式的引數設定一個預設值,我們實際傳遞給函式的實參,優先順序大於預設值

  • 函式剩餘引數

  • Array物件擴充套件

    1. 擴充套件運算子(。。。)可以在函式呼叫/陣列構造時, 將陣列表示式或者string在語法層面展開,還可以在構造字面量物件時, 將物件表示式按key-value的方式展開
    2. Array.from() 把偽陣列轉換成陣列
    3. forEach遍歷陣列
    4. 陣列例項的 find() 和 findIndex()
    5. 陣列例項的 includes()
  • String物件擴充套件

    1. 模板字串
    2. includes(), startsWith(), endsWith()
    3. repeat() repeat方法返回一個新字串,表示將原字串重複n
    4. trim() trim() 方法可以去掉字串兩邊的空白
  • Number

    ES6 將全域性方法parseInt()parseFloat(),移植到Number物件上面,功能完全保持不變。 Number.parseInt() Number.parseFloat()

    parseInt() 會去掉小數,parseFloat() 不會

  • 新增物件Set

    ES6 提供了新的資料結構 Set。它類似於陣列,但是成員的值都是唯一的,沒有重複的值。Set的特點就是該物件裡面的成員不會有重複。

    Set本身是一個建構函式,用來生成 Set 資料結構。

    // 1. 基本使用
    let s = new Set();
    // 得到一個空的Set物件
    // 呼叫add方法,向s中新增幾個值
    s.add(3);
    s.add(7);
    s.add(9);
    s.add(7); // Set物件中的成員都是唯一的,前面新增過7了,所以這裡新增無效
    ​
    console.log(s.size);
    console.log(s); // {3, 7, 9}
    
    • size:屬性,獲取 set 中成員的個數,相當於陣列中的 length
    • add(value):新增某個值,返回 Set 結構本身。
    • delete(value):刪除某個值,返回一個布林值,表示刪除是否成功。
    • has(value):返回一個布林值,表示該值是否為Set的成員。
    • clear():清除所有成員,沒有返回值。
  • 定義物件的簡潔方式

    let id = 1;
    let name = 'zs';
    let age = 20;
    ​
    // 之前定義物件的方案
    // let obj = {
    //     // 屬性: 值
    //     id: id,
    //     name: name,
    //     age: age,
    //     fn: function () {
    //         console.log(this.age);
    //     }
    // };
    ​
    // obj.fn();
    ​
    ​
    // ES6的新方案
    let obj = {
        id,  // 屬性名id和前面的變數id名字相同,則可以省略 :id
        name,
        nianling: age,
        // 下面的函式是上面函式的簡化寫法,可以省略 :function  。但是注意這裡僅僅是上面函式的簡化,不是箭頭函式
        fn () {
            console.log(this.name);
        }
    };
    obj.fn();
    
  • Promise

    1. 概述:Promise是非同步程式設計的一種解決方案,從語法上講,Promise是一個物件,可以獲取非同步操作的訊息

    2. 目的: (1)、避免回撥地獄的問題(2)、Promise物件提供了簡潔的API,使得控制非同步操作更加容易

    3. Promise有三種狀態:pendding //正在請求,rejected //失敗,resolved //成功

    4. 基礎用法:new Promise(function(resolve,reject){ })

    5. resolved,rejected函式:在非同步事件狀態pendding->resolved回撥成功時,通過呼叫resolved函式返回結果;當非同步操作失敗時,回撥用rejected函式顯示錯誤資訊

    6. then的用法:then中傳了兩個引數,第一個對應resolve的回撥,第二個對應reject的回撥

    7. catch方法:捕捉promise錯誤函式,和then函式引數中rejected作用一樣,處理錯誤,由於Promise丟擲錯誤具有冒泡性質,能夠不斷傳遞,會傳到catch中,所以一般來說所有錯誤處理放在catch中,then中只處理成功的,同時catch還會捕捉resolved中丟擲的異常

    8. all方法:Promise.all([promise1,promise2])——引數是物件陣列。以慢為準,等陣列中所有的promise物件狀態為resolved時,該物件就為resolved;只要陣列中有任意一個promise物件狀態為rejected,該物件就為rejected

      let p = Promise.all([Promise1, Promise2])
      
      p.then((data) => {
          //都成功才表示成功
      })
      .catch((err) => {
          //有一個失敗,則都失敗
      });
      
    9. race方法:Promise.race([promise1,promise2])——引數是物件陣列。以快為準,陣列中所有的promise物件,有一個先執行了何種狀態,該物件就為何種狀態,並執行相應函式

2.原型鏈

在這裡插入圖片描述

3.this的理解

​ this是一個關鍵字,代表函式執行時,自動生成的一個內部物件,只能在函式內部使用

​ 在普通函式中,this指向window

​ 在定時器中,this也是指向window

​ 在建構函式中,this指向當前例項化 物件

​ 在事件處理函式中,this指向事件觸發物件

​ 總的來說,誰呼叫指向誰

4.foreach和map區別

​ 1、forEach()返回值是undefined,不可以鏈式呼叫,對資料的操作會改變原陣列。

​ 2、map()返回一個新陣列,原陣列不會改變。

​ 3、沒有辦法終止或者跳出forEach()迴圈,除非丟擲異常,所以想執行一個數組是否滿足什麼條件,返回布林值,可以用一般的for迴圈實現,用Array.every()或者Array.some();

5.some和every

​ every()和 some()目的:確定陣列的所有成員是否滿足指定的測試

​ some方法遍歷 只要其中一個為true 就會返回true的,every()方法必須所有都返回true才會返回true,哪怕有一個false,就會返回false;

6.find和 filter

​ 陣列操作方法find(), 查詢,找到陣列中第一個滿足條件的成員並返回該成員,如果找不到返回undefined。

​ 同樣findindex(), 查詢,,找到陣列中第一個滿足條件的成員並返回該成員的索引,如果找不到返回 -1。

​ indexOf,遍歷一直,如果陣列中存在,則返回對應的索引值,不存在的話返回-1

​ filter () 過濾 filter方法用於過濾陣列成員,滿足條件的成員組成一個新陣列返回

7.reduce方法

reduce()方法裡邊,有兩部分,第一是個回撥函式,第二個引數是設定的初始值。回撥函式中可以有四個引數,第一個引數是上一次回撥返回的值,或者設定的初始值,第二個引數是當前被處理的項,第三個引數是當前被處理項的索引值,第四項是原陣列

1.求和

var total = [ 0, 1, 2, 3 ].reduce(
  ( acc, cur ) => acc + cur,
  0
)

// 累加物件裡面的值
let sum = [{x: 1}, {x:2}, {x:3}].reduce(
    (accumulator, currentValue) => accumulator + currentValue.x
    ,0
);
 
console.log(sum) // logs 6

2.二維陣列變一維

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
 ( acc, cur ) => acc.concat(cur),
 []
)

3.計算每個元素出現的次數

const names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
 
let countedNames = names.reduce(function (allNames, name) { 
  if (name in allNames) {
    allNames[name]++;
  }
  else {
    allNames[name] = 1;
  }
  return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
  1. 陣列去重

    let arr = [1,2,3,4,4,1]
    let newArr = arr.reduce((pre,cur)=>{
        if(!pre.includes(cur)){
          return pre.concat(cur)
        }else{
          return pre
        }
    },[])
    console.log(newArr);// [1, 2, 3, 4]
    
8.陣列去重
  1. 將陣列的每一個元素通過兩次for迴圈依次與其他元素做比較,發現重複元素,利用陣列方法splice()刪除重複元素

    function noRepeat1(arr){
            // 第一層for用來控制迴圈的次數
            for(var i=0; i<arr.length; i++){
                //第二層for 用於控制與第一層比較的元素
                for(var j=i+1; j<arr.length; j++){
                    //如果相等
                    if(arr[i] == arr[j]){
                        //刪除後面的 即第 j個位置上的元素  刪除個數 1 個
                        arr.splice(j,1);
                        // j--很關鍵的一步  如果刪除 程式就會出錯 
                        //j--的原因是 每次使用splice刪除元素時 返回的是一個新的陣列 
                        // 這意味這陣列下次遍歷是 比較市跳過了一個元素
                        /*
                            例如: 第一次刪除後 返回的是 1 1 3 2 1 2 4
                         *  但是第二次遍歷是 j的值為2  arr[2] = 3
                         *  相當於跳過一個元素 因此要 j--
                         * */
                        j--;
     
                    }
     
                }
            }
     
            return arr;
        }
    
    1. 通過foreach遍歷陣列,新建一個空陣列,然後用includes()或者indexof ()判斷新數組裡邊有沒有遍歷出來的每一項,沒有的話,加到新數組裡邊去

    2. 通過filter過濾,返回 self.indexOf(value) === index 值的情況

         var newarr = arr.filter(function (value, index, self) {
            return self.indexOf(value) === index;
          });
      

      4.通過reduce()方法,先設定一個空陣列,然後拿includes判斷每一項是否在新的陣列中,不再 的話,加里邊

      let arr = [1,2,3,4,4,1]
      let newArr = arr.reduce((pre,cur)=>{
          if(!pre.includes(cur)){
            return pre.concat(cur)
          }else{
            return pre
          }
      },[])
      console.log(newArr);// [1, 2, 3, 4]
      
  2. slice()和splice()區別

    slice擷取陣列的一段 返回一個新的陣列 不改變原陣列,兩個引數,一是,開始刪除的位置,二是結束的位置(不包括),

    splice可以刪除或者新增 會改變原陣列,三個引數可以有,一是開始位置,二是改變多少項,三個替換的內容

  3. js繼承

    繼承有以下六種方法
    1、原型鏈繼承 JavaScript 實現繼承的基本思想:通過原型將一個引用型別繼承另一個引
    用 型別的屬性和方法
    2、借用建構函式繼承(偽造物件或經典繼承) JavaScript 實現繼承的基本思想:在子類構造
    函式內部呼叫超型別建構函式。 通過使用 apply()和 call()方法可以在新建立的子類物件上
    執 行建構函式
    3、組合繼承(原型+借用構造)(偽經典繼承) JavaScript 實現繼承的基本思想:將原型鏈和借
    用建構函式的技術組合在一塊,從而發揮兩者之長的一種繼承模式
    將原型鏈和借用建構函式的技術組合到一起,從而取長補短髮揮兩者長處的一種繼承模式
    4、型式繼承 JavaScript 實現繼承的基本思想:藉助原型可以基於已有的物件建立新對
    象, 同時還不必須因此建立自定義的型別
    5、寄生式繼承 JavaScript 實現繼承的基本思想:建立一個僅用於封裝繼承過程的函式,
    該 函式在內部以某種方式來增強物件,最後再像真正是它做了所有工作一樣返回物件。
    寄生式繼承是原型式繼承的加強版
    6、寄生組合式繼承 JavaScript 實現繼承的基本思想:通過借用函式來繼承屬性,通過原
    型 鏈的混成形式來繼承方法

11.new

1、建立一個空物件: 並且 this 變數引入該物件,同時還繼承了函式的原型
2、設定原型鏈 空物件指向建構函式的原型物件
3、執行函式體 修改建構函式 this 指標指向空物件,並執行函式體
4、判斷返回值 返回物件就用該物件,沒有的話就建立一個物件

三.vue

1.介紹一下vue

vue是一款漸進式 的輕量級框架,他的核心庫只關注檢視層,

Vue作為一款輕量級框架、簡單易學、雙向資料繫結、元件化、資料和結構的分離、虛擬DOM、執行速度快,並且作者是中國人尤雨溪,對應的API文件對國內開發者優化,作為前端開發人員的首選入門框架,Vue 有很多優勢:

1、 Vue.js 可以進行元件化開發,使程式碼編寫量大大減少,讀者更加易於理解。

2、 Vue.js 最突出的優勢在於可以對資料進行雙向繫結。

3、使用 Vue.js 編寫出來的介面效果本身就是響應式的,這使網頁在各種裝置上都能顯示出非常好看的效果。

4、相比傳統的頁面通過超連結實現頁面的切換和跳轉,Vue 使用路由不會重新整理頁面。

5、vue是單頁面應用,使頁面區域性重新整理,不用每次跳轉頁面都要請求所有資料和dom,這樣大大加快了訪問速度和提升使用者體驗。

6、而且他的第三方UI元件庫使用起來節省很多開發時間,從而提升開發效率。

2.vue生命週期

​ Vue 例項從建立到銷燬的過程,就是生命週期。也就是從開始建立、初始化資料、編譯模板、掛載Dom→渲染、更新→渲染、解除安裝等一系列過程,我們稱這是 Vue 的生命週期。

1)beforeCreate

​ 在例項初始化之後,資料觀測 (data observer) 和 event/watcher 事件配置之前被呼叫。

2)created

​ 在例項建立完成後被立即呼叫。在這一步,例項已完成以下的配置:資料觀測 (data observer), 屬性和方法的運算,watch/event 事件回撥。然而,掛載階段還沒開始,$el 屬性目前不可見。

3)beforeMount

​ 在掛載開始之前被呼叫:相關的 render 函式首次被呼叫。

4)mounted

​ el 被新建立的 vm. e l 替 換 , 並 掛 載 到 實 例 上 去 之 後 調 用 該 鉤 子 。 如 果 r o o t 實 例 掛 載 了 一 個 文 檔 內 元 素 , 當 m o u n t e d 被 調 用 時 v m . el 替換,並掛載到例項上去之後呼叫該鉤子。如果 root 例項掛載了一個文件內元素,當 mounted 被呼叫時 vm. el調rootmounted調vm.el 也在文件內。

5)beforeUpdate

​ 資料更新時呼叫,發生在虛擬 DOM 打補丁之前。這裡適合在更新之前訪問現有的 DOM,比如手動移除已新增的事件監聽器。該鉤子在伺服器端渲染期間不被呼叫,因為只有初次渲染會在服務端進行。

6)updated

​ 由於資料更改導致的虛擬 DOM 重新渲染和打補丁,在這之後會呼叫該鉤子。

7)activated

​ keep-alive 元件啟用時呼叫。該鉤子在伺服器端渲染期間不被呼叫。

8)deactivated

​ keep-alive 元件停用時呼叫。該鉤子在伺服器端渲染期間不被呼叫。

9)beforeDestroy

​ 例項銷燬之前呼叫。在這一步,例項仍然完全可用。該鉤子在伺服器端渲染期間不被呼叫。

10)destroyed

​ Vue 例項銷燬後呼叫。呼叫後,Vue 例項指示的所有東西都會解繫結,所有的事件監聽器會被移除,所有的子例項也會被銷燬。該鉤子在伺服器端渲染期間不被呼叫。

11)errorCaptured(2.5.0+ 新增)

​ 當捕獲一個來自子孫元件的錯誤時被呼叫。此鉤子會收到三個引數:錯誤物件、發生錯誤的元件例項以及一個包含錯誤來源資訊的字串。此鉤子可以返回 false 以阻止該錯誤繼續向上傳播。

3.vue-cli腳手架建立專案,目錄結構
  • node_modules:第三方依賴

  • public:公共資源

  • src:原始碼

    • assets:靜態資源,css、img、js、font等
    • compoments:元件,一般自定義元件
    • router:路由配置
    • views:檢視元件
  • App.vue:首頁元件(預設元件)

  • main.js:入口檔案

  • .browserslistrc:配置使用CSS相容性外掛的使用範圍

  • .eslintrc.js:配置ESLint

  • .gitignore:配置git忽略的檔案或者資料夾

  • babel.config.js:使用一些預設

  • package.json:專案描述既依賴

  • package-lock.json:版本管理使用的檔案

  • README.md:專案描述

  • 或者這樣回答

    1、 assets 資料夾是放靜態資源

    2、 components 是放元件

    3、 router 是定義路由相關的配置

    4、 view 檢視

    5、 app.vue 是一個應用主元件

    6、 main.js 是入口檔案

4.介紹路由,路由模式,許可權控制

url地址和資源的對應關係,就是路由,

vue的路由有三種模式

  1. hash模式 使用URL的hash值來作為路由。通過onhashchange事件監聽hash值的改變實現,它的特點在於:hash 雖然出現URL中,但不會被包含在HTTP請求中,對後端完全沒有影響,因此改變hash不會重新載入頁面。
  2. history模式 利用了HTML5 中新增的pushState() 和replaceState() 方法。(需要特定瀏覽器支援) 這兩個方法應用於瀏覽器的歷史記錄站,在當前已有的back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改是,雖然改變了當前的URL,但你瀏覽器不會立即向後端傳送請求。 history模式,會出現404 的情況,需要後臺配置。
  3. abstract : 支援所有 JavaScript 執行環境,如 Node.js 伺服器端。如果發現沒有瀏覽器的 API,路由會自動強制進入這個模式

hash模式和history模式切換,在router.js檔案中,路由初始化上加 mode:history;

const router = new VueRouter({
    // mode: 'history',
    base: process.env.BASE_URL,
    routes
})
  1. 路由許可權

    1、建立vue例項的時將vue-router掛載,但vue-router初始時只掛載登入頁面(或是其他不需要許可權的頁面)。

    2、當用戶登入後,獲取後臺返回的該使用者能訪問的頁面陣列role,將role和路由表每個頁面的需要的許可權作比較,生成終端使用者可訪問的路由表。

    3、呼叫router.addRoutes(store.getters.addRouters)新增使用者可訪問的路由。

    4、使用vuex管理路由表,根據vuex中可訪問的路由渲染側邊欄元件。

5.data為什麼是個函式return,而不是物件形式

​ 1、 每個元件都是 Vue 的例項。

​ 2、 元件共享 data 屬性,當 data 的值是同一個引用型別的值時,改變其中一個會影響其他

​ 3、元件中的data寫成一個函式,資料以函式返回值形式定義,這樣每複用一次元件,就會返回一份新的data,類似於給每個元件例項建立一個私有的資料空 間,讓各個元件例項維護各自的資料。而單純的寫成物件形式,就使得所有元件例項共用了一份data,就會造成一個變了全都會變的結果。

6.元件之間通訊方式

​ 1)父元件向子元件傳遞資料

​ 父元件內設定要傳的資料,在父元件中引用的子元件上繫結一個自定義屬性並把資料繫結在自定義屬性上,在子元件新增引數props接收即可

​ 2)子元件向父元件傳遞/資料

	 子元件通過vue例項方法$emit進行觸發並且可以攜帶引數,父元件監聽使用@(v-on)進行監聽,然後進行方法處理

​ 3)非父子元件之間傳遞資料

	 1、引入第三方new vue定義為eventBus
		2、在元件中created中訂閱方法eventBus.$on("自定義事件名",methods中的方法名)
	 3、在另一個兄弟元件中的methods中寫函式,在函式中釋出eventBus訂閱的方法eventBus.$emit("自定義事件名”)
	 4、在元件的template中繫結事件(比如click)
7.axios,封裝axios,一些引數配置項舉例
/**
 * 封裝一下axios
 */
// import store from '@/store.js'
// import router from '@/router.js' // 用到的話引入
import axios from 'axios'
const instance = axios.create({
  baseURL: '..', // 配置請求的基地址
  timeout: 3000, // `timeout` 指定請求超時的毫秒數(0 表示無超時時間)
  withCredentials: true, // 表示跨域請求時是否需要使用憑證
  headers: { 'X-Requested-With': 'XMLHttpRequest' }, // `headers` 是即將被髮送的自定義請求頭
  transformRequest: [data => { // `transformRequest` 允許在向伺服器傳送前,修改請求資料
    // 它的意思,其實就是把這樣的資料(物件){ name:"yangxu",age:23 } 轉換成這樣的資料(字串) "name=yangxu&age=23"這樣的查詢字串
    return JSON.stringify(data)
  }]
})
// // 新增請求攔截器
// axios.interceptors.request.use(function (config) {
//   // 在傳送請求之前做些什麼
//   return config;
// }, function (error) {
//   // 對請求錯誤做些什麼
//   return Promise.reject(error);
// });

// // 新增響應攔截器
// axios.interceptors.response.use(function (response) {
//   // 對響應資料做點什麼
//   return response;
// }, function (error) {
//   // 對響應錯誤做點什麼
//   return Promise.reject(error);
// });
export default instance
8.v-if和v-show

v-if和v-show都能控制元素的顯示和隱藏,區別是v-show是通過css中的display:none;控制顯示隱藏 的,而v-if是動態的向DOM樹內新增或者刪除DOM元素來實現的顯示與隱藏

v-show只編譯一次,後面其實就是控制css,而v-if不停的銷燬和建立

總結(適用場景):如果要頻繁切換某節點時,使用v-show(無論true或者false初始都會進行渲染,此後通過css來控制顯示隱藏,因此切換開銷比較小,初始開銷較大),如果不需要頻繁切換某節點時,使用v-if(因為懶載入,初始為false時,不會渲染,但是因為它是通過新增和刪除dom元素來控制顯示和隱藏的,因此初始渲染開銷較小,切換開銷比較大)

9.watch和computed區別

computed是計算屬性,他主要是同步對資料進行一些處理,比如說進行一些計算或者對字串的處理(購物車合計),他的使用是在,一個數據,是依賴多個數據變化的而變化,只有依賴的資料有變化時,資料才會變化,所以,他具有快取的功能

而watch,他不僅可以做一些同步處理,而且做一些非同步的處理,比如一些事件的派發,一些請求,他做的是偵聽,一個數據發生改變,可能會觸發多個事物,比如說視訊禁止快進場景,快進了,提示不能快進,並且給他返回快進前位置

10.說一說watch,深度監聽和立即執行,場景和原理

watch深度監聽一個物件的變化

​ 1、有個原則監聽誰,寫誰的名字,然後是對應的執行函式, 第一個引數為最新的改變值,第二個值為上一次改變的值, 注意: 除了監聽 data,也可以監聽計算屬性 或者一個 函式的計算結果

​ 2、啟用深度監聽物件 deep:true

在選項引數中指定immediate: true將立即以表示式的當前值觸發回撥,watch監聽開始之後立即被呼叫

	watch:{
  	 a:{
      	   handler:function(val,oldval){  
       },
       deep:true;
       immediate: true;
  		}
	}

11.vuex

​ Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式,可以解決不同元件資料共享問題。

他有五個核心屬性

1.state 存放所有公共狀態的屬性,專案全域性通用的屬性放在state裡邊

​ 使用:1. this.$store.state.屬性

​ 2.通過mapState輔助函式 ,先import引入mapState函式,採用陣列形式引入state屬性( mapState([‘count’]) ),然後通過擴充套件運算子,把匯出的屬性對映到計算屬性中

 import { mapState } from 'vuex'
 computed: {
    ...mapState(['count'])
  }

2.mutations mutations是一個物件,物件中存放修改state的方法 , state資料的修改只能通過mutations,並且mutations他是同步更新的

​ 使用: 1. this.$store.commit(‘方法名’, 引數)

			2. 通過mapMutations輔助函式,首先引入,然後通過擴充套件運算子,把mutations     內的方法對映到methods裡

3.actions Vuex中mutations中要求不能寫非同步程式碼,如果有非同步的ajax請求,應該放置在actions中

 actions: {
  //  獲取非同步的資料 context表示當前的store的例項 可以通過 context.state 獲取狀態 也可以通過context.commit 來提交mutations, 也可以 context.diapatch呼叫其他的action
    getAsyncCount (context) {
      setTimeout(function(){
        // 一秒鐘之後 要給一個數 去修改state
        context.commit('addCount', 123)
      }, 1000)
    }
 } 

使用: 1. this.$store.dispatch(‘非同步的方法名’, 引數)

​ 2, 通過mapActions輔助函式,首先引入,然後通過擴充套件運算子,把actions 內的方法對映到methods裡

4.getters 除了state之外,有時我們還需要從state中派生出一些狀態,這些狀態是依賴state的, getters可以理解為類似於計算屬性

    getters: {
    // getters函式的第一個引數是 state
    // 必須要有返回值
     filterList:  state =>  state.list.filter(item => item > 5)
  }

​ 使用: 1. this.$store.getters.屬性

​ 2.mapGetters輔助函式,對映到計算屬性中,和state一樣的方式

5.modules 如果把所有的狀態都放在state中,當專案變得越來越大的時候,Vuex會變得越來越難以維護,所以給他分模組管理

const store  = new Vuex.Store({
  modules: {
    user: {
     namespaced: true,         // 保證內部模組的高封閉性
       state: {
         token: '12345'
       },
       mutations: {
        //  這裡的state表示的是user的state
         updateToken (state) {
            state.token = 678910
         }
       }
    },
    setting: {
      state: {
         name: 'Vuex例項'
      }
    }
  })

使用: 1. this.$store.state.模組名稱.屬性名

這樣取有些麻煩,可以通過getters改善一下

 getters: {
   token: state => state.user.token,
   name: state => state.setting.name
 } 
  1. this.$store.dispatch(‘user/updateToken’) // 直接呼叫方法
12.scoped

把scoped寫在style上,保證單頁面使用這些樣式,不會汙染其他

13.vue專案登入功能,及登入後儲存資訊

1、第一次登入的時候,前端調後端的登陸介面,傳送使用者名稱和密碼

2、後端收到請求,驗證使用者名稱和密碼,驗證成功,就給前端返回一個token和一些其他的使用者資訊

3、前端拿到資訊,將資訊儲存到vuex中並且要做持久化快取,快取到localstorage中,(如果僅僅儲存到vuex中,會存在一重新整理頁面,vuex中資料丟失的情況,

因為重新整理頁面會重新載入vue例項,store裡面的資料就會被重新賦值)。

4.再發請求的時候攜帶token或者相關引數

14.資料雙向繫結原理

vue雙向繫結他是通過資料劫持,結合釋出者-訂閱者模式實現的

通過Object.defineProperty來劫持物件屬性的getter和setter操作,並種下一個監聽器,當資料變化時發出通知,給訂閱者,然後觸發相應的監聽回撥

訂閱者模式中的釋出函式,是釋出時執行 的回撥

訂閱函式,是新增訂閱者,傳入釋出時要執行的函式,可能會攜帶額外引數

15.$set

vue在建立例項的時候把data深度遍歷所有屬性,並使用 Object.defineProperty 把這些屬性全部轉為 getter/setter。讓 Vue 追蹤依賴,在屬性被訪問和修改時通知變化。所以屬性必須在 data 物件上存在才能讓 Vue 轉換它,這樣才能讓它是響應的。
當你在物件上新加了一個屬性 newProperty,當前新加的這個屬性並沒有加入vue檢測資料更新的機制(因為是在初始化之後新增的),vue.$set是能讓vue知道你添加了屬性, 它會給你做處理

如果在例項建立之後新增新的屬性到例項上,不觸發updated函式,檢視不更新。

this.$set(this.data,”key”,value’)

  data() {
    return {
      test: [1, 2, 3, 4],
    }
  },
  methods: {
    btn() {
      // this.test[1] = 'hi'
      this.$set(this.test, 1, 'hi')
      console.log(this.test)
    },
  },
16.vue.config.js配置
module.exports = {
  outputDir: 'D:\\website', // 打包資料夾
  publicPath: process.env.NODE_ENV === 'production' ? 'website/' : '/', // 部署時所在相對路徑
  // lintOnSave: false, // eslint-loader 是否在儲存的時候檢查
  devServer: { // 對請求進行攔截和處理的一箇中間件
    proxy: 'http://localhost:90/freshproject/'
    // proxy: {
    //   '/api': {
    //     target: 'http://localhost:8080', //要訪問的跨域的域名
    //     ws: true, // 是否啟用websockets
    //     changeOrigin: true, // 開啟代理:在本地會建立一個虛擬服務端,然後傳送請求的資料,並同時接收請求的資料,這樣客戶端端和服務端進行資料的互動就不會有跨域問題
    //     pathRewrite: {  // 為是否將指定字串轉換一個再發過去
    //       '^/api': ''
    //     }

    //   },

    // },
    // before(app) { // before方法:能夠在其他所以的中介軟體之前執行自定義的中介軟體
    //   app.get('/test', (req, res) => {
    //     res.json(test)
    //   })
    // }

    // configureWebpack: (config) => {
    //   if (process.env.NODE_ENV === 'production') {
    //     // 為生產環境配置
    //     // 在打包之後的js中去掉console.log
    //     config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true
    //   } else {
    //     // 為開發環境配置
    //   }
    // },
    // productionSourceMap: false, // 生產環境是否生成 sourceMap 檔案


    // cdn 引入,減小打包後體積,優化 "表示要引入的資源的名字": “表示該模組提供給外部引用的名字”
    // 要注意名字的寫法,否則會報錯 xxx is not defined
    // configureWebpack: {
    //   externals: { // 配置不打包的js
    //     'vue': 'Vue',
    //     'element-ui': 'ELEMENT',
    //     //   'vue-router': 'VueRouter',
    //     //   'vuex': 'Vuex',
    //     //   'axios': 'axios'

    //   }
    // },
  }
}
17.封裝元件,上傳npm

1.寫好元件

通過vue-cli建立專案,新建自己的元件資料夾,裡邊放自己寫的元件,同時,在這個元件資料夾下建立index.js檔案,通過import匯入自己寫的元件,然後通過install函式,結合Vue.component()註冊元件,然後匯出,這樣,在main.js裡邊就可以import這個index.js檔案,並vue.use()使用,然後在這個vue專案中就可以全域性使用我們自己寫 的元件了

2.打包上傳

需要配置打包命令在package.json中,專門打包對應的檔案,然後npm上傳打包生成的包

3.使用

當你上傳成功後,別人就可以直接npm i 安裝你的包了

18.nextTick

​ 檢視更新之後,基新的檢視進行操作,this.$nextTick將回調延遲到下次dom更新迴圈之後執行

​ 在vue中,資料和dom渲染是非同步的,資料的變化不是立即就引起檢視的變化,而是在下一輪的渲染操作中去更新檢視

19.專案優化方案

1.打包的時候去掉map檔案 productionSourceMap: false

2.路由懶載入

3.使用gzip壓縮

4.cdn 載入 直接引入第三方資源,減小伺服器壓力

5.元件的按需引入

6.去掉打包後 的console

    configureWebpack: (config) => {
      if (process.env.NODE_ENV === 'production') {
        // 為生產環境配置
        // 在打包之後的js中去掉console.log
        config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true
      } else {
        // 為開發環境配置
      }
    },
20.為什麼v-if和v-for不能一起用,解決方案

v-for 比 v-if 具有更高的優先順序,每一次判斷v-if真假的時候,都會先v-for迴圈

解決: 一是可以把v-if和v-for分開,別寫在一個元素上邊;二是可以先通過計算屬性,把v-if為false 的情況給他過濾掉,直接顯示為真的情況

  1. <router-view :key="$route.fullPath" / >

    通過繫結一個fullPath,可以識別當前頁面路由的完整地址,當地址發生改變(包括引數改變)則重新渲染頁面(例如動態路由引數的變化)

四.其他

1.localstorage、sessionstorage、cookie

共同點:都是儲存在瀏覽器端、且同源的
區別:
1、cookie 資料始終在同源的 http 請求中攜帶(即使不需要),即 cookie 在瀏覽器和伺服器間來回傳遞,而 sessionStorage 和 localStorage 不會自動把資料傳送給伺服器,僅在本地儲存。cookie 資料還有路徑(path)的概念,可以限制 cookie 只屬於某個路徑下
2、儲存大小限制也不同,cookie 資料不能超過 4K,同時因為每次 http 請求都會攜帶cookie、所以 cookie 只適合儲存很小的資料,如會話標識。sessionStorage 和 localStorage雖然也有儲存大小的限制,但比 cookie 大得多,可以達到 5M 或更大
3、資料有效期不同,sessionStorage:僅在當前瀏覽器視窗關閉之前有效; localStorage:始終有效,視窗或瀏覽器關閉也一直儲存,因此用作持久資料;cookie:只在設定的cookie 過期時間之前有效,即使視窗關閉或瀏覽器關閉
4、作用域不同,sessionStorage 不在不同的瀏覽器視窗中共享,即使是同一個頁面;
localstorage 在所有同源視窗中都是共享的;cookie 也是在所有同源視窗中都是共享的
5、web Storage 支援事件通知機制,可以將資料更新的通知傳送給監聽者
6、web Storage 的 api 介面使用更方便

2.瀏覽器相容問題

1.IE8下的png圖片無法顯示,因為會把png格式的圖片解析成span標籤

解決方案: 對span標籤設定寬高和display:inline-block

2.置較小高度的容器(小於10px),在IE6下不識別小於10px的高度

解決方案:給容器新增overflow:hidden

3.圖片預設有間隙

解決方案:

1)給img標籤新增左浮動float:left;

2)給img標籤新增display:block;

4.字型大小在不同瀏覽上不一致。例如font-size:14px,在 IE 中的實際行高是16px,下面有3px留白;在 Firefox 中的實際行高是17px,下面有3px留白,上邊1px留白;在 opera 中就更不一樣了。

解決方案: 統一指定行高 line-height 高度

5…當在a標籤中巢狀img標籤時,在某些瀏覽器中img會有藍色邊框

解決方案: 給img新增border:0;或者是border:none

6.百分比的bug 父元素寬度為100%,子元素寬度各為50%,在IE6下各個元素寬度之和超過100%

解決方案:給右邊浮動的子元素新增clear:right

3.購物車
4.換膚功能