js 整理 前端知識點 前端面試題 (2020)(vue)


數據類型

字符串(String)、數字(Number)、布爾(Boolean)、對空(Null)、未定義(Undefined)、Symbol。

引用數據類型:對象(Object)、數組(Array)、函數(Function)。

注:Symbol 是 ES6 引入了一種新的原始數據類型,表示獨一無二的值。

undefined和null 區別

undefined是未定義 不存在的

null 是空值 已定義   typeof得到的是object

javaScript權威指南: null 和 undefined 都表示“值的空缺”,你可以認為undefined是表示系統級的、出乎意料的或類似錯誤的值的空缺,而null是表示程序級的、正常的或在意料之中的值的空缺。

http 和 https 有何區別

http是HTTP協議運行在TCP之上。所有傳輸的內容都是明文,客戶端和服務器端都無法驗證對方的身份。

https是HTTP運行在SSL/TLS之上,SSL/TLS運行在TCP之上。所有傳輸的內容都經過加密,加密采用對稱加密,但對稱加密的密鑰用服務器方的證書進行了非對稱加密。此外客戶端可以驗證服務器端的身份,如果配置了客戶端驗證,服務器方也可以驗證客戶端的身份。

常見的HTTP狀態碼

2開頭 (請求成功)表示成功處理了請求的狀態代碼。

200   (成功)  服務器已成功處理了請求。 通常,這表示服務器提供了請求的網頁。 
201   (已創建)  請求成功並且服務器創建了新的資源。 
202   (已接受)  服務器已接受請求,但尚未處理。 
203   (非授權信息)  服務器已成功處理了請求,但返回的信息可能來自另一來源。 
204   (無內容)  服務器成功處理了請求,但沒有返回任何內容。 

3開頭 (請求被重定向)表示要完成請求,需要進一步操作。 通常,這些狀態代碼用來重定向。

300   (多種選擇)  針對請求,服務器可執行多種操作。 服務器可根據請求者 (user agent) 選擇一項操作,或提供操作列表供請求者選擇。 
301   (永久移動)  請求的網頁已永久移動到新位置。 服務器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉到新位置。
302   (臨時移動)  服務器目前從不同位置的網頁響應請求,但請求者應繼續使用原有位置來進行以后的請求。

4開頭 (請求錯誤)這些狀態代碼表示請求可能出錯,妨礙了服務器的處理。

400   (錯誤請求) 服務器不理解請求的語法。 
401   (未授權) 請求要求身份驗證。 對於需要登錄的網頁,服務器可能返回此響應。 
403   (禁止) 服務器拒絕請求。
404   (未找到) 服務器找不到請求的網頁。
405   (方法禁用) 禁用請求中指定的方法。 
406   (不接受) 無法使用請求的內容特性響應請求的網頁。 
407   (需要代理授權) 此狀態代碼與 401(未授權)類似,但指定請求者應當授權使用代理。
408   (請求超時)  服務器等候請求時發生超時。 
409   (沖突)  服務器在完成請求時發生沖突。 服務器必須在響應中包含有關沖突的信息。 
410   (已刪除)  如果請求的資源已永久刪除,服務器就會返回此響應。 
411   (需要有效長度) 服務器不接受不含有效內容長度標頭字段的請求。 
412   (未滿足前提條件) 服務器未滿足請求者在請求中設置的其中一個前提條件。 
413   (請求實體過大) 服務器無法處理請求,因為請求實體過大,超出服務器的處理能力。 
414   (請求的 URI 過長) 請求的 URI(通常為網址)過長,服務器無法處理。 
415   (不支持的媒體類型) 請求的格式不受請求頁面的支持。 
416   (請求范圍不符合要求) 如果頁面無法提供請求的范圍,則服務器會返回此狀態代碼。 

5開頭(服務器錯誤)這些狀態代碼表示服務器在嘗試處理請求時發生內部錯誤。 這些錯誤可能是服務器本身的錯誤,而不是請求出錯。

500   (服務器內部錯誤)  服務器遇到錯誤,無法完成請求。 
501   (尚未實施) 服務器不具備完成請求的功能。 例如,服務器無法識別請求方法時可能會返回此代碼。 
502   (錯誤網關) 服務器作為網關或代理,從上游服務器收到無效響應。 
503   (服務不可用) 服務器目前無法使用(由於超載或停機維護)。 通常,這只是暫時狀態。 
504   (網關超時)  服務器作為網關或代理,但是沒有及時從上游服務器收到請求。 
505   (HTTP 版本不受支持) 服務器不支持請求中所用的 HTTP 協議版本。

mvvm mvc

MVC(Model-View-Controller)

MVC是比較直觀的架構模式,用戶操作->View(負責接收用戶的輸入操作)->Controller(業務邏輯處理)->Model(數據持久化)->View(將結果反饋給View)。

MVVM(Model-View-ViewModel)

將“數據模型數據雙向綁定”的思想作為核心  View和Model之間沒有聯系,通過ViewModel進行交互,而且Model和ViewModel之間的交互是雙向的,因此視圖的數據的變化會同時修改數據源,而數據源數據的變化也會立即反應view

px  em   rem的區別  chrome最小字體為12px 

px 像素 絕對單位 不會其他元素的尺寸變化而變化

em 根據父元素的字體大小的變化而變化 相對單位   

rem 根據根元素的字體大小的變化而變化 相對單位

上下左右居中顯示 css

div{

    position:absolute;

   top:50%;

   left:50%

   height: 200px;

   width:200px;

   margin-top:-100px;

   margin-left:-100px;

}

margin 實現 必須設置width height

div2{

  position:absolute;

  top:0;

  left:0;right:0;

  bottom:0;

  margin:auto;

  width:200px;

  height:200px;

}

清楚浮動

.clear{ clear:both}

父級設置height

父級 overflow:hidden  zoom:1

數組去重  遍歷數組 indexOf判斷是否存在

let arr = [1, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 1, 2, 3, 4], activeArr = []

arr.map((res, index)=> {

  if (activeArr.indexOf(res) === -1) {

    activeArr.push(res)

  }

})

三個盒子,左右定寬,中間自適應 使用flex布局 

<style>

.son{
     width: 100%;
     position:relative;
     display: flex;
     justify-content: space-between;
     height: 50px;
}
.son>div{
    margin:0 10px;
    background: red;
    width: 200px;
}
.dd2{
    flex:1
}

</style>

<div class="son">
     <div class="dd1"></div>
      <div class="dd2"></div>
      <div class="dd3"></div>

</div>

eval() 字符串計算函數

console.log(eval('2+2'))  4

console.log(eval('x=2;y=3;x+y'))  5

let num = 9

console.log(eval('num+1'))  10

JS事件冒泡與JS事件代理

事件冒泡 點擊子元素觸發父元素事件 逐級往上 

阻止事件冒泡 :

w3c的方法是e.stopPropagation(),IE則是使用e.cancelBubble = true

vue 使用 @click.stop   小程序 bindtap 改成 catchtap  

事件委托 將子元素的事件通過冒泡交給父元素執行

CSS樣式覆蓋規則 !important優先級最高

內聯樣式 style 權級最大  1000

id  100

class 10

標簽 1

繼承樣式和自身樣式 會顯示自身樣式

!important的樣式屬性不被覆蓋 為特殊 比style還高

box-sizing -moz-box-sizing

盒子組成: 內容 內邊距 外邊距 邊框

box-sizing:border-box 設置盒子固定width   height  不受padding影響width     

閉包 作用域

閉包 

白話文 函數內包有函數 內部函數使用外部函數變量

閉包就是一個函數,捕獲作用域內的外部綁定。這些綁定是為之后使用而被綁定,即使作用域已經銷毀

閉包的官方定義為:一個擁有許多變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分

自由變量與閉包的關系是,自由變量閉合於閉包的創建

閉包有三個特性:

函數嵌套函數 

函數內部可以引用外部的參數和變量 

參數和變量不會被垃圾回收機制回收

作用域 

白話文 函數調用外部變量

在內部函數可以訪問外部函數變量的這種機制,用鏈式查找決定哪些數據能被內部函數訪問

函數的執行依賴於變量作用域,這個作用域是在函數定義時決定的,而不是函數調用時決定的。

瀏覽器的內核分別是什么?

IE: trident內核

Firefox:gecko內核

Safari:webkit內核

Opera:以前是presto內核,Opera現已改用Google Chrome的Blink內核

Chrome:Blink(基於webkit,Google與Opera Software共同開發)


sessionStorage 、localStorage 和 cookie 之間的區別

sessionStorage 本地存儲 頁面關閉數據及清除  數據可存5M  不同窗口不可共享

localStorage 本地存儲 如不主動清除 則一直存在  數據可存5M  窗口可共享

Cookie 數據會發送到服務器端 可設置過期時間 數據不能超過4K, 窗口可共享 

函數防抖和函數節流?

函數防抖是指頻繁觸發的情況下,只有足夠的空閑時間,才執行代碼一次

函數防抖的要點,也是要一個setTImeout來輔助實現。延遲執行需要跑的代碼

如果方法多次觸發,則要把上次記錄的延遲執行代碼用clearTimeout清掉,重新開始

如果計時完畢,沒有方法進來訪問觸發,則執行代碼

    clearTimeout(timer);
    let timer = setTimeout(function(){
        console.log('0')
    }, 400);

javascript中的this 指向

全局代碼中的this是指向全局對象

作為對象的方法調用時指向調用這個函數的對象

作為構造函數指向創建的對象

require.context()

如頁面需要導入多個組件,原始寫法:

import titleCom from '@/components/home/titleCom'
import bannerCom from '@/components/home/bannerCom'
import cellCom from '@/components/home/cellCom'
components:{titleCom,bannerCom,cellCom}

大量重復的代碼,利用 require.context   (需要組件提前預設,在統一的一個文件夾下面)

const path = require('path')
const files = require.context('@/components/home', false, /\.vue$/)
const modules = {}
files.keys().forEach(key => {
  const name = path.basename(key, '.vue')
  modules[name] = files(key).default || files(key)
})
components:modules

VUEX

state:定義存貯數據的倉庫 ,可通過this.$store.state 或mapState訪問
getter:獲取 store 值,可認為是 store 的計算屬性,可通過this.$store.getter 或
       mapGetters訪問
mutation:同步改變 store 值,為什么會設計成同步,因為mutation是直接改變 store 值,
         vue 對操作進行了記錄,如果是異步無法追蹤改變.可通過mapMutations調用
action:異步調用函數執行mutation,進而改變 store 值,可通過 this.$dispatch或mapActions
       訪問
modules:模塊,如果狀態過多,可以拆分成模塊,最后在入口通過...解構引入

VUE  props 和 $attrs(vue2.4)  父組件傳子組件  $listeners

主要用於父組件傳子組件

props  子組件提前定義獲取的父組件傳遞的參數

$attrs  子組件獲取props未定義的父組件傳遞的參數

$listeners 子組件調用父組件的方法

// 對象
props:{
 inpVal:{
  type:Boolean, //傳入值限定類型
  // type 值可為String,Number,Boolean,Array,Object,Date,Function,Symbol
  // type 還可以是一個自定義的構造函數,並且通過 instanceof 來進行檢查確認
  required: true, //是否必傳
  default:200,  //默認值,對象或數組默認值必須從一個工廠函數獲取如 default:()=>[]
  validator:(value) {
    // 這個值必須匹配下列字符串中的一個
    return ['success', 'warning', 'danger'].indexOf(value) !== -1
  }
 }
}

 

mounted(){console.log(this.$attrs)}.

 

// 父組件
<parent @change="change"/>

// 子組件
mounted() {
  console.log(this.$listeners) //即可拿到 change 事件
}

 

Vue $emit 子傳父 

// 父組件
<parent @change="sonChange">
// 子組件
this.$emit('change','我是子組件的事件')

 Vue $children  一級子組件的屬性和方法

//父組件
mounted(){
  console.log(this.$children) 
  //可以拿到 一級子組件的屬性和方法
  //所以就可以直接改變 data,或者調用 methods 方法
}

//子組件
mounted(){
  console.log(this.$parent) //可以拿到 parent 的屬性和方法
}

 vue $refs(父調用子數據)    .sync(子動態修改父數據)

// 父組件
<parent ref="parent"/>

mounted(){
  console.log(this.$refs.parent) //即可拿到子組件的實例,就可以直接操作 data 和 methods
}

// 父組件
<parent :title.sync="title" />
//編譯時會被擴展為
<parent :title="title"  @update:title="val => title = val"/>

// 子組件
// 所以子組件可以通過$emit 觸發 update 方法改變
mounted(){
  this.$emit("update:title", '這是新的title')

vue proxy (vue-cli@2.X)  設置代理 允許跨域請求 

// config/index.js 約定 /api  進入代理 

module.exports = {
  dev: {

    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    // 原本proxyTable屬性中對象為空,在此進行proxy代理配置(可以跨域)
    proxyTable: {
      '/api': {
        target: 'http://192.168.1.117:8083/',   // 后端接口地址 target表示代理的服務器url
        changeOrigin: true, // 是否允許跨越
        pathRewrite: {     // pathRewrite表示路徑重寫,key表示一個正則,value表示別名 
          '^/api': ''   // // 重寫,
        }
      }
    },
    // ---------------------------------------------------------

    host: 'localhost', // 
    port: 8080,   // 開啟服務器的端口
    autoOpenBrowser: false,   // 是否開啟在瀏覽器中打開
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false, 
    devtool: 'cheap-module-eval-source-map',
    cacheBusting: true,
    cssSourceMap: true
  },

  build: {
  
    // build時輸出的index.html文件,可以自定義路徑
    index: path.resolve(__dirname, '../dist/index.html'),

    // build時輸出的靜態(除了index.html)資源路徑
    assetsRoot: path.resolve(__dirname, '../dist'),

    // build時輸出靜態資源的二級目錄
    assetsSubDirectory: 'static',

    // 代表打包后,index.html里面引用資源的的相對地址
    assetsPublicPath: './',

 
    // 是否開啟cssSourceMap
    productionSourceMap: true,
    devtool: '#source-map',

    // 是否開啟gzip
    productionGzip: false,

    // 需要用gzip壓縮的文件擴展名
    productionGzipExtensions: ['js', 'css'],

    bundleAnalyzerReport: process.env.npm_config_report
  }
}

// 接口調用  

export const netPictureUpload = (params) =>{

    return httpService(`/api/crm/appendix/netPictureUpload`,params,'get'); // 實際路徑 crm/appendix/netPictureUpload

}

 Vue EventBus 

1.就是聲明一個全局Vue實例變量 EventBus , 把所有的通信數據,事件監聽都存儲到這個變量上;
2.類似於 Vuex。但這種方式只適用於極小的項目
3.原理就是利用和emit 並實例化一個全局 vue 實現數據共享

4.可以實現平級,嵌套組件傳值,但是對應的事件名eventTarget必須是全局唯一的

// 在 main.js
Vue.prototype.$eventBus=new Vue()

// 傳值組件
this.$eventBus.$emit('eventTarget','這是eventTarget傳過來的值')

// 接收組件
this.$eventBus.$on("eventTarget",v=>{
  console.log('eventTarget',v);//這是eventTarget傳過來的值
})

render 函數  slot標簽 插槽

1.場景:有些代碼在 template 里面寫會重復很多,所以這個時候 render 函數就有作用啦

2.render 和 template 的對比
前者適合復雜邏輯,后者適合邏輯簡單;
后者屬於聲明是渲染,前者屬於自定Render函數;
前者的性能較高,后者性能較低。

// 根據 props 生成標簽
// 初級
<template>
  <div>
    <div v-if="level === 1"> <slot></slot> </div>
    <p v-else-if="level === 2"> <slot></slot> </p>
    <h1 v-else-if="level === 3"> <slot></slot> </h1>
    <h2 v-else-if="level === 4"> <slot></slot> </h2>
    <strong v-else-if="level === 5"> <slot></slot> </stong>
    <textarea v-else-if="level === 6"> <slot></slot> </textarea>
  </div>
</template>

// 優化版,利用 render 函數減小了代碼重復率
<template>
  <div>
    <child :level="level">Hello world!</child>
  </div>
</template>

<script type='text/javascript'>
  import Vue from 'vue'
  Vue.component('child', {
    render(h) {
      const tag = ['div', 'p', 'strong', 'h1', 'h2', 'textarea'][this.level-1]
      return h(tag, this.$slots.default)
    },
    props: {
      level: {  type: Number,  required: true  } 
    }
  })   
  export default {
    name: 'hehe',
    data() { return { level: 3 } } 
  }
</script>

<slot></slot> 為插槽 Vue.component 內使用    例子中slot 代替 Your Profile

<navigation-link url="/channel" loo="asdasd">

  Your Profile

</navigation-link>

Vue.component('navigation-link', {

    template: `

    <div>

      Clicking here will send you to

      <slot></slot>

    </div>

    `

})

 

異步組件  官方文檔

項目過大就會導致加載緩慢,所以異步組件實現按需加載就是必須要做的事啦

// 工廠函數執行 resolve 回調
Vue.component('async-webpack-example', function (resolve) {
  // 這個特殊的 `require` 語法將會告訴 webpack
  // 自動將你的構建代碼切割成多個包, 這些包
  // 會通過 Ajax 請求加載
  require(['./my-async-component'], resolve)
})

// 工廠函數返回 Promise
Vue.component(
  'async-webpack-example',
  // 這個 `import` 函數會返回一個 `Promise` 對象。
  () => import('./my-async-component')
)

// 工廠函數返回一個配置化組件對象
const AsyncComponent = () => ({
  // 需要加載的組件 (應該是一個 `Promise` 對象)
  component: import('./MyComponent.vue'),
  // 異步組件加載時使用的組件
  loading: LoadingComponent,
  // 加載失敗時使用的組件
  error: ErrorComponent,
  // 展示加載時組件的延時時間。默認值是 200 (毫秒)
  delay: 200,
  // 如果提供了超時時間且組件加載也超時了,
  // 則使用加載失敗時使用的組件。默認值是:`Infinity`
  timeout: 3000
})

路由的按需加載 


{
  path:'/',
  name:'home',
  components:resolve=>require(['@/components/home'],resolve)
}

{
  path:'/',
  name:'home',
  components:()=>import('@/components/home')
}

import()方法由es6提出,import()方法是動態加載,返回一個Promise對象,then方法的參數是加載到的模塊。import()方法是異步加載的。 

vue context 屬性有:
1.props:提供所有 prop 的對象
2.children: VNode 子節點的數組
3.slots: 一個函數,返回了包含所有插槽的對象
4.scopedSlots: (2.6.0+) 一個暴露傳入的作用域插槽的對象。也以函數形式暴露普通插槽。
5.data:傳遞給組件的整個數據對象,作為 createElement 的第二個參數傳入組件
6.parent:對父組件的引用
7.listeners: (2.3.0+) 一個包含了所有父組件為當前組件注冊的事件監聽器的對象。這是 data.on 的一個別名。
8.injections: (2.3.0+) 如果使用了 inject 選項,則該對象包含了應當被注入的屬性

Vue.nextTick

頁面加載時需要讓文本框獲取焦點

在下次 DOM 更新循環結束之后執行延遲回調。在修改數據之后立即使用這個方法,獲取更新后的 DOM

mounted(){ //因為 mounted 階段 dom 並未渲染完畢,所以需要$nextTick
  this.$nextTick(() => {
    this.$refs.inputs.focus() //通過 $refs 獲取dom 並綁定 focus 方法
  })
}

Vue.filter 

// 使用
// 在雙花括號中
{{ message | capitalize }}

// 在 `v-bind` 中
<div v-bind:id="rawId | formatId"></div>

// 全局注冊
Vue.filter('stampToYYMMDD', (value) =>{
  // 處理邏輯
})

// 局部注冊
filters: {
  stampToYYMMDD: (value)=> {
    // 處理邏輯
  }
}

// 多個過濾器全局注冊
// /src/common/filters.js
let dateServer = value => value.replace(/(\d{4})(\d{2})(\d{2})/g, '$1-$2-$3') 
export { dateServer }
// /src/main.js
import * as custom from './common/filters/custom'
Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))

事件修飾符 

.stop:阻止冒泡
.prevent:阻止默認行為
.self:僅綁定元素自身觸發
.once: 2.1.4 新增,只觸發一次
.passive: 2.3.0 新增,滾動事件的默認行為 (即滾動行為) 將會立即觸發,不能和.prevent 一起使用

全局路由鈎子 路由守衛 攔截

1.router.beforeEach

router.beforeEach((to, from, next) => {
  console.log('全局前置守衛:beforeEach -- next需要調用') //一般登錄攔截用這個,也叫導航鈎子守衛
  if (path === '/login') {
    next()
    return
  }
  if (token) {
    next();
  } 
})

2.router.beforeResolve (v 2.5.0+)
和beforeEach類似,區別是在導航被確認之前,同時在所有組件內守衛和異步路由組件被解析之后,解析守衛就被調用
即在 beforeEach之后調用

3.router.afterEach
全局后置鈎子
在所有路由跳轉結束的時候調用
這些鈎子不會接受 next 函數也不會改變導航本身

路由模式  Vue.$router Vue.$route  

設置 mode 屬性:hash或 history

2.Vue.$router

this.$router.push() 跳轉到不同的url,但這個方法回向history棧添加一個記錄,點擊后退會返回到上一個頁面
this.$router.replace() 不會有記錄
this.$router.go(n) n可為正數可為負數。正數返回上一個頁面,類似 window.history.go(n)

3.Vue.$route

表示當前跳轉的路由對象,屬性有:
name:路由名稱
path:路徑
query:傳參接收值
params:傳參接收值
fullPath:完成解析后的 URL,包含查詢參數和 hash 的完整路徑
matched:路由記錄副本
redirectedFrom:如果存在重定向,即為重定向來源的路由的名字

this.$route.params.id:獲取通過 params 或/:id傳參的參數
this.$route.query.id:獲取通過 query 傳參的參數

 

img 加載失敗

// page 代碼
<img :src="imgUrl" @error="handleError" alt="">
<script>
export default{
  data(){
    return{
      imgUrl:''
    }
  },
  methods:{
    handleError(e){
      e.target.src=reqiure('圖片路徑') //當然如果項目配置了transformToRequire,參考上面 27.2
    }
  }
}
</script>

deep >>> 深選擇器

例如要修改框架內組件的樣式 

設置scoped的子組件里的元素  

<style lang="css" scoped>

.gHeader /deep/ .name{ //第一種寫法 color:red; }

.gHeader >>> .name{ //二種寫法 color:red; }

</style>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM