亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

一、錯誤類型

任何一個框架,對于錯誤的處理都是一種必備的能力

在Vue 中,則是定義了一套對應的錯誤處理規(guī)則給到使用者,且在源代碼級別,對部分必要的過程做了一定的錯誤處理。

主要的錯誤來源包括:

  • 后端接口錯誤
  • 代碼中本身邏輯錯誤

二、如何處理

后端接口錯誤

通過axIOS的interceptor實現(xiàn)網(wǎng)絡(luò)請求的response先進行一層攔截

apiClient.interceptors.response.use(
  response => {
    return response;
  },
  error => {
    if (error.response.status == 401) {
      router.push({ name: "Login" });
    } else {
      message.error("出錯了");
      return Promise.reject(error);
    }
  }
);

 

代碼邏輯問題

全局設(shè)置錯誤處理

設(shè)置全局錯誤處理函數(shù)

Vue.config.errorHandler = function (err, vm, info) {
  // handle error
  // `info` 是 Vue 特定的錯誤信息,比如錯誤所在的生命周期鉤子
  // 只在 2.2.0+ 可用
}

errorHandler指定組件的渲染和觀察期間未捕獲錯誤的處理函數(shù)。這個處理函數(shù)被調(diào)用時,可獲取錯誤信息和 Vue 實例

不過值得注意的是,在不同Vue 版本中,該全局 API 作用的范圍會有所不同:

從 2.2.0 起,這個鉤子也會捕獲組件生命周期鉤子里的錯誤。同樣的,當這個鉤子是 undefined 時,被捕獲的錯誤會通過 console.error 輸出而避免應用崩

從 2.4.0 起,這個鉤子也會捕獲 Vue 自定義事件處理函數(shù)內(nèi)部的錯誤了

從 2.6.0 起,這個鉤子也會捕獲 v-on DOM 監(jiān)聽器內(nèi)部拋出的錯誤。另外,如果任何被覆蓋的鉤子或處理函數(shù)返回一個 Promise 鏈 (例如 async 函數(shù)),則來自其 Promise 鏈的錯誤也會被處理

生命周期鉤子

errorCaptured是 2.5.0 新增的一個生命鉤子函數(shù),當捕獲到一個來自子孫組件的錯誤時被調(diào)用

基本類型

(err: Error, vm: Component, info: string) => ?boolean

 

此鉤子會收到三個參數(shù):錯誤對象、發(fā)生錯誤的組件實例以及一個包含錯誤來源信息的字符串。此鉤子可以返回 false 以阻止該錯誤繼續(xù)向上傳播

參考官網(wǎng),錯誤傳播規(guī)則如下:

  • 默認情況下,如果全局的 config.errorHandler 被定義,所有的錯誤仍會發(fā)送它,因此這些錯誤仍然會向單一的分析服務的地方進行匯報
  • 如果一個組件的繼承或父級從屬鏈路中存在多個 errorCaptured 鉤子,則它們將會被相同的錯誤逐個喚起。
  • 如果此 errorCaptured 鉤子自身拋出了一個錯誤,則這個新錯誤和原本被捕獲的錯誤都會發(fā)送給全局的 config.errorHandler
  • 一個 errorCaptured 鉤子能夠返回 false 以阻止錯誤繼續(xù)向上傳播。本質(zhì)上是說“這個錯誤已經(jīng)被搞定了且應該被忽略”。它會阻止其它任何會被這個錯誤喚起的 errorCaptured 鉤子和全局的 config.errorHandler

下面來看個例子

定義一個父組件cat

Vue.component('cat', {
    template:`
        <div>
			<h1>Cat: </h1>
        	<slot></slot>
        </div>`,
    props:{
        name:{
            required:true,
            type:String
        }
    },
    errorCaptured(err,vm,info) {
        console.log(`cat EC: ${err.toString()}ninfo: ${info}`); 
        return false;
    }

});

 

定義一個子組件kitten,其中dontexist()并沒有定義,存在錯誤

Vue.component('kitten', {
    template:'<div><h1>Kitten: {{ dontexist() }}</h1></div>',
    props:{
        name:{
            required:true,
            type:String
        }
    }
});

 

頁面中使用組件

<div id="App" v-cloak>
    <cat name="my cat">
        <kitten></kitten>
    </cat>
</div>

在父組件的errorCaptured則能夠捕獲到信息

cat EC: TypeError: dontexist is not a function
info: render

三、源碼分析

異常處理源碼

源碼位置:/src/core/util/error.js

// Vue 全局配置,也就是上面的Vue.config
import config from '../config'
import { warn } from './debug'
// 判斷環(huán)境
import { inBrowser, inWeex } from './env'
// 判斷是否是Promise,通過val.then === 'function' && val.catch === 'function', val !=== null && val !== undefined
import { isPromise } from 'shared/util'
// 當錯誤函數(shù)處理錯誤時,停用deps跟蹤以避免可能出現(xiàn)的infinite rendering
// 解決以下出現(xiàn)的問題https://github.com/vuejs/vuex/issues/1505的問題
import { pushTarget, popTarget } from '../observer/dep'

export function handleError (err: Error, vm: any, info: string) {
    // Deactivate deps tracking while processing error handler to avoid possible infinite rendering.
    pushTarget()
    try {
        // vm指當前報錯的組件實例
        if (vm) {
            let cur = vm
            // 首先獲取到報錯的組件,之后遞歸查找當前組件的父組件,依次調(diào)用errorCaptured 方法。
            // 在遍歷調(diào)用完所有 errorCaptured 方法、或 errorCaptured 方法有報錯時,調(diào)用 globalHandleError 方法
            while ((cur = cur.$parent)) {
                const hooks = cur.$options.errorCaptured
                // 判斷是否存在errorCaptured鉤子函數(shù)
                if (hooks) {
                    // 選項合并的策略,鉤子函數(shù)會被保存在一個數(shù)組中
                    for (let i = 0; i < hooks.length; i++) {
                        // 如果errorCaptured 鉤子執(zhí)行自身拋出了錯誤,
                        // 則用try{}catch{}捕獲錯誤,將這個新錯誤和原本被捕獲的錯誤都會發(fā)送給全局的config.errorHandler
                        // 調(diào)用globalHandleError方法
                        try {
                            // 當前errorCaptured執(zhí)行,根據(jù)返回是否是false值
                            // 是false,capture = true,阻止其它任何會被這個錯誤喚起的 errorCaptured 鉤子和全局的 config.errorHandler
                            // 是true capture = fale,組件的繼承或父級從屬鏈路中存在的多個 errorCaptured 鉤子,會被相同的錯誤逐個喚起
                            // 調(diào)用對應的鉤子函數(shù),處理錯誤
                            const capture = hooks[i].call(cur, err, vm, info) === false
                            if (capture) return
                        } catch (e) {
                            globalHandleError(e, cur, 'errorCaptured hook')
                        }
                    }
                }
            }
        }
        // 除非禁止錯誤向上傳播,否則都會調(diào)用全局的錯誤處理函數(shù)
        globalHandleError(err, vm, info)
    } finally {
        popTarget()
    }
}
// 異步錯誤處理函數(shù)
export function invokeWithErrorHandling (
handler: Function,
 context: any,
 args: null | any[],
    vm: any,
        info: string
        ) {
            let res
            try {
                // 根據(jù)參數(shù)選擇不同的handle執(zhí)行方式
                res = args ? handler.apply(context, args) : handler.call(context)
                // handle返回結(jié)果存在
                // res._isVue an flag to avoid this being observed,如果傳入值的_isVue為ture時(即傳入的值是Vue實例本身)不會新建observer實例
                // isPromise(res) 判斷val.then === 'function' && val.catch === 'function', val !=== null && val !== undefined
                // !res._handled  _handle是Promise 實例的內(nèi)部變量之一,默認是false,代表onFulfilled,onRejected是否被處理
                if (res && !res._isVue && isPromise(res) && !res._handled) {
                    res.catch(e => handleError(e, vm, info + ` (Promise/async)`))
                    // avoid catch triggering multiple times when nested calls
                    // 避免嵌套調(diào)用時catch多次的觸發(fā)
                    res._handled = true
                }
            } catch (e) {
                // 處理執(zhí)行錯誤
                handleError(e, vm, info)
            }
            return res
        }

//全局錯誤處理
function globalHandleError (err, vm, info) {
    // 獲取全局配置,判斷是否設(shè)置處理函數(shù),默認undefined
    // 已配置
    if (config.errorHandler) {
        // try{}catch{} 住全局錯誤處理函數(shù)
        try {
            // 執(zhí)行設(shè)置的全局錯誤處理函數(shù),handle error 想干啥就干啥
            return config.errorHandler.call(null, err, vm, info)
        } catch (e) {
            // 如果開發(fā)者在errorHandler函數(shù)中手動拋出同樣錯誤信息throw err
            // 判斷err信息是否相等,避免log兩次
            // 如果拋出新的錯誤信息throw err Error('你好毒'),將會一起log輸出
            if (e !== err) {
                logError(e, null, 'config.errorHandler')
            }
        }
    }
    // 未配置常規(guī)log輸出
    logError(err, vm, info)
}

// 錯誤輸出函數(shù)
function logError (err, vm, info) {
    if (process.env.NODE_ENV !== 'production') {
        warn(`Error in ${info}: "${err.toString()}"`, vm)
    }
    /* istanbul ignore else */
    if ((inBrowser || inWeex) && typeof console !== 'undefined') {
        console.error(err)
    } else {
        throw err
    }
}

 

小結(jié)

  • handleError在需要捕獲異常的地方調(diào)用,首先獲取到報錯的組件,之后遞歸查找當前組件的父組件,依次調(diào)用errorCaptured 方法,在遍歷調(diào)用完所有 errorCaptured 方法或 errorCaptured 方法有報錯時,調(diào)用 globalHandleError 方法
  • globalHandleError調(diào)用全局的 errorHandler 方法,再通過logError判斷環(huán)境輸出錯誤信息
  • invokeWithErrorHandling更好的處理異步錯誤信息
  • logError判斷環(huán)境,選擇不同的拋錯方式。非生產(chǎn)環(huán)境下,調(diào)用warn方法處理錯誤

其它錯誤

1、在配置路由并引入組件后,報錯:

    Unknown custom element: <router-link> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

  錯誤原因:vue-router沒有注冊

  解決辦法:

    //注冊插件 *****************非常重要,不能忘記

    Vue.use(VueRouter)

2、在組件中的標簽和樣式中圖片路徑出錯時:報錯:

    Errors while compiling. Reload prevented.

    Module not found: Error: Can't resolve '
./src/assets/img/btn_bg.png' in 'E:myStudyvue案例chexian-spasrccomponents'

  解決辦法:將圖片的路徑重新書寫

3、在組件中標簽沒有閉合,報錯:

     Errors while compiling. Reload prevented.

    
./node_modules/[email protected]@vue-loader/lib/template-compiler?{"id":"data-v-00822b28","hasScoped":false,"buble":{"transforms":{}}}!./node_modules/[email protected]@vue-loader/lib/selector.js?type=template&index=0&bustCache!./src/components/BaseProject.vue

(Emitted value instead of an instance of Error)

  解決辦法:檢查html代碼

4、在使用less定義變量是報錯:

前端開發(fā)中 vue項目中常見的錯誤處理

 

  錯誤原因:必須用分號結(jié)尾:@imgUrl:'../../assets/img/';

前端開發(fā)中 vue項目中常見的錯誤處理

 

Compiled with problems:

編譯問題

C:myelsrcviewsHomeView.vue

錯誤出現(xiàn)文件

3:1 error Mixed spaces and tabs no-mixed-spaces-and-tabs

4:1 error Mixed spaces and tabs no-mixed-spaces-and-tabs

第3行的第一個字符

第4函的第一個字符

Mixed spaces and tabs

錯誤原因:混合的空格與tab

no-mixed-spaces-and-tabs

錯誤規(guī)則: no-mixed-spaces-and-tabs 不準混空格與tab

2 problems (2 errors, 0 warnings)

2個問題(2個錯誤,0個警告)

前端開發(fā)中 vue項目中常見的錯誤處理

 

Compiled with problems:

編譯錯誤

ERROR in ./src/views/HomeView.vue?

錯誤出現(xiàn)的位置

Unexpected keyword 'const'. (6:0)

第6行第0個字符有個不應該出現(xiàn)的關(guān)鍵字 const

63 | const user = reactive({ userid: "", pwd: "", code: "" }), | ^ 64 | const rules = reactive({ | ^ 65 | userid: [

第63到64行兩個^之間有錯誤

前端開發(fā)中 vue項目中常見的錯誤處理

 

ERROR in ./src/router/index.ts 10:19-57

錯誤發(fā)生在 ./src/router/index.ts 第10行第19個字符到57字符

Module not found: Error: Can't resolve '../views/admin/AdminVeiw.vue' in 'C:myelsrcrouter'

,模塊找不的 不能resolve(兌現(xiàn),發(fā)現(xiàn),解決)
../views/admin/AdminVeiw.vue

在C:myelsrcrouter

總結(jié):文件
../views/admin/AdminVeiw.vue(文件名/路徑發(fā)生錯誤)

本地開發(fā)環(huán)境請求服務器接口跨域的問題

前端開發(fā)中 vue項目中常見的錯誤處理

 

上面的這個報錯大家都不會陌生,報錯是說沒有訪問權(quán)限(跨域問題)。本地開發(fā)項目請求服務器接口的時候,因為客戶端的同源策略,導致了跨域的問題。

下面先演示一個沒有配置允許本地跨域的的情況:

前端開發(fā)中 vue項目中常見的錯誤處理

 


前端開發(fā)中 vue項目中常見的錯誤處理

 


前端開發(fā)中 vue項目中常見的錯誤處理

 

可以看到,此時我們點擊獲取數(shù)據(jù),瀏覽器提示我們跨域了。所以我們訪問不到數(shù)據(jù)。

那么接下來我們演示設(shè)置允許跨域后的數(shù)據(jù)獲取情況:

前端開發(fā)中 vue項目中常見的錯誤處理

 

注意:配置好后一定要關(guān)閉原來的server,重新npm run dev啟動項目。不然無效。

前端開發(fā)中 vue項目中常見的錯誤處理

 


前端開發(fā)中 vue項目中常見的錯誤處理

 

注意:配置好后一定要關(guān)閉原來的server,重新npm run dev啟動項目。不然無效。

我們在1出設(shè)置了允許本地跨域,在2處,要注意我們訪問接口時,寫的是/api,此處的/api指代的就是我們要請求的接口域名。如果我們不想每次接口都帶上/api,可以更改axios的默認配置axios.defaults.baseURL = '/api';這樣,我們請求接口就可以直接this.$axios.get('app.php?m=App&c=Index&a=index'),很簡單有木有。此時如果你在network中查看xhr請求,你會發(fā)現(xiàn)顯示的是localhost:8080/api的請求地址。這樣沒什么大驚小怪的,代理而已:

前端開發(fā)中 vue項目中常見的錯誤處理

 

給大家分享我收集整理的各種學習資料,前端小白交流、學習交流,也可以直接問我,我會組織大家一起做項目練習,幫助大家匹配一位學習伙伴互相監(jiān)督學習-下面是學習資料參考。

分享到:
標簽:vue
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定