昨天是最后一次給同事進行Vue的培訓,這次培訓主要是以基礎入門為主。
整篇講義參考了一些文章:https://gitbook.cn/gitchat/column/5a4af1c5658b7c0d9ebe1131/topic/5a4dfdddbb7105032b4fa06b
https://blog.csdn.net/insistlzh/article/details/79381796
在學習任何一種語言或者框架的時候,學到的知識,要會把它用出來才能變成自己的經驗。大家自己平時學習的時候也要學會總結。這次,從整體說一下Vue常見的坑。
一、Vue.js
我認為Vue.js是一個數據驅動的漸進式的框架,雙向數據綁定,通過指令的方式實現很多功能,組件式開發。
一般的項目中,只要不涉及到特殊的頁面效果,都可以采用數據驅動頁面的方法,包括頁面間各種展示效果,通過CSS屬性和Vue.js的指令配合就可以解決大部分的問題了。所以,大家在用這個框架的時候,要記住:數據驅動頁面,用數據控制你的頁面。
二、Vue常見的坑
1、this
在開發中,我們使用data中定義的變量或者methods定義的方法時,都是通過this.xxx或者this.xxx()的方式去調用。但是有的時候會出現報錯,說this.xxx為undefined;我們明明已經定義了這些變量或方法,但它仍會報錯
出現這種問題的原因:
①箭頭函數
new Vue({ data: { item: { title: '', description: '', } }, methods: { saveItem: function() { let vm = this; this.$http.post('item', this.item) .then( function (response) { vm.item.title = ''; vm.item.description = ''; }, function (response) { console.log('error', response); } ); } } });
我們現在看一下上述代碼,通過變量vm將tihs保存,這樣的目的就是為了我們能夠不受函數執行上下文影響獲取Vue的實例對象;這種方式寫起來很麻煩,我們可以使用箭頭函數的方式,去精簡我們的代碼,如下:這樣我們就可以不用總是保存一下this變量就可以獲取到Vue實例了
saveItem: function() { this.$http.post('item', this.item) .then( (response)=> { vm.item.title = ''; vm.item.description = ''; },(response) =>{ console.log('error', response); } ); }
箭頭函數雖然很好用,但並不是所有的函數定義都要用到它。
saveItem:()=>{ this.$http.post('item',this.item).then( //callbacks in here ) }
如果寫成這樣的話,代碼看起來更精簡,但是會遇到一個坑,就是this的指向問題,此時的this並沒有指向Vue實例,它獲取的是window.item
ES6約定了一種新的函數定義方式,可以直接把函數名當作函數來聲明。如下:
var obj = { foo:function(){}, bar:function(){} } //ES6 methods definitions it becomes var obj ={ foo(){}, bar(){} }
我們用這種方式簡寫我們的saveItem方法,也不會出現this的繼承問題
這也就是為什么在Vue中盡量用ES6的語法去寫js
data相關
在Vue中的組件開發中,我們定義的data這個對象可以當作一個閉包return回來,官方文檔的解釋是:為了保證組件內部的狀態獨立,避免多個組件共用一個data
之前也說過,在data中也可以寫成函數的形式
var sum = (a,b)=>{return a+b}//傳統的塊級結構,需要有return var sum = (a,b)=>a+b;//簡單結構 ---(為了代碼規范,不建議用這種方式) //如果返回一個值得時候,可以直接把值寫上,但是如果返回得是一個對象字面量,就必須把你返回得對象用括號包起來返回。
②交互
在使用axios進行交互的時候,你返回函數中想用this.xxx進行賦值或調用方法,this.xxx或this.xxx() 有時也會報undedined的錯誤
解決方法:
var that=this; axios.get('/list?now_page=4') .then(function (res) { that.listData=res.data }) .catch(function (err) { console.log(err); });
2、父子組件傳參
父組件給子組件的數據是異步獲取的,子組件獲取到數據后再渲染,在父組件傳遞數據之前,子組件先進行渲染時,子組件此時在 mounted 中打印數據是 undefined。
解決方法一:
給子組件加v-if,先不讓它顯示,等到數據獲取后再顯示。
解決方法二:
可以用vuex狀態管理
3、圖片路徑
在開發中涉及到圖片路徑的切換,你會發現在一開始設置的時候,路徑是可用的,但是在打包的時候,會報錯,變成‘../../../a/b/c/image/bg.png’。出現這種問題的原因是在開發時和打包后的路徑是不一樣的,這時我們可以用require('相對路徑')的方式解決
<img :src="imgUrl"> data(){ return { imgUrl:require('../asserts/images/bg.png'); } }
4、請求問題
XMLHttpRequest cannot load XXX. Response for preflight has invalid HTTP status code 405
出現這種問題是因為在post請求中,post的默認格式是request payload,而不是 form data。解決這個問題,我們只需要添加一個 headers 進行設置,如下。
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
5、template的問題
<template> <div class="box1"></div> <div class="box2"></div> </template>
以上代碼會報錯如下:
template syntax error Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
解決方法:
在 template 下面只能有一個元素,你的其他元素都應該在這個元素中,如下面的代碼。
<template> <div class="container"> <div class="box1"></div> <div class="box2"></div> </div> </template>
6、開發中的指令使用(不做講解,遇到自己查文檔)
7、自定義指令
最容易被忽視的環節,大家把其他的掌握好后再去了解學習
8、組件開發(重點,需要不斷實踐,在實踐中處理)
9、axios請求
請求的一般坑我就不說了,這些都是個人原因,這里講解一種情況,如果你的后台進行了請求限制,也就是說限定了你只能用 post 或者 get 請求,這個時候你是用 axios.js 進行交互,你用的也是 post 或者 get,但是后台也出現了錯誤請求。
我在工作中發現的一種情況是,在頁面交互過程中,axios 一定幾率會發送兩次請求,一次是自己設置的請求方式,還有一次是 options。
經過查找資料,得出以下結論。
跨域資源共享標准新增了一組 HTTP 首部字段,允許服務器聲明哪些源站有權限訪問哪些資源。另外,規范要求,對那些可能對服務器數據產生副作用的 HTTP 請求方法(特別是 GET 以外的 HTTP 請求,或者搭配某些 MIME 類型的 POST 請求),瀏覽器必須首先使用 OPTIONS 方法發起一個預檢請求(Preflight Request),從而獲知服務端是否允許該跨域請求。服務器確認允許之后,才發起實際的 HTTP 請求。在預檢請求的返回中,服務器端也可以通知客戶端,是否需要攜帶身份憑證(包括 Cookies 和 HTTP 認證相關數據)。
也就是說,它會先使用 options 去測試,你這個接口是否能夠正常通訊,如果不能就不會發送真正的請求過來,如果測試通訊正常,則開始正常請求。
關於這個問題,需要在后台進行設置,允許 options 請求,不然你的請求就會受到影響。后台作出判斷,如果請求方式為 options,告訴它可以通訊,其它什么都不用做。