這些vue技巧,你值得擁有
分享我在vue開發中積累的開發技巧總結,有些會結合使用環境或者是我的個人網站(www.cooldream.fun/home)中的使用例項來說明,畢竟光有技巧也要考慮結合使用環境,這才能做到對於學習狀態的加深印象以及實際使用的事半功倍,話不多說,我是想到啥寫到啥,不要因為有些可能有點low或者用的不多就看一半就關了,希望你能夠耐心看完,多多少少肯定對你還是有點幫助的,最後,也希望閱讀我的這篇部落格能給我一個點贊,你們的贊是我更新的最大動力!
1.動態元件 <component :is='元件名'></component>
結合v-for迴圈使用
-
使用環境
如圖,這是一個v-for渲染的列表(只是目前這個版塊才剛開始做,目前只有一個),圓圈內的就是一個元件,也就是要v-for動態元件
-
實際使用
一開始就是基本的元件引入了
import ColorIn from '@/components/Magic/ColorIn.vue'
import LineIn from "@/components/Magic/LineIn.vue";
import LineIn from "@/components/Magic/Header.vue";
import LineIn from "@/components/Magic/Footer.vue";
export default{
components:{
ColorIn,LineIn,Header,Footer
}
}
複製程式碼
接下來就是動態v-for動態元件的使用,componentList:['ColorIn','LineIn','Header','Footer']
使用下面的程式碼即可將程式碼依次迴圈
<component v-for="(item,index) in componentList" :key="index" :is="item"></component>
複製程式碼
編譯以後的效果就是
<ColorIn></ColorIn>
<LineIn></LineIn>
<Header></Header>
<Footer ></Footer>
複製程式碼
2.watch進階使用
立即執行
- 使用環境
例如場景為頁面一進來就呼叫拉取列表資料getList()
,然後監聽路由的$route.query.id
然後觸發列表資料的更新
- 實際使用
為了讓它一開始就執行,我們需要在created()
生命週期中執行一次拉取資料的方法
watch:{
'$route.query.id':{
handle(){
this.getList();
},}
},created(){
this.getList();
},複製程式碼
但是使用immediate
即可立即執行,改寫以後的程式碼如下
watch:{
'$route.query.id':{
handle(){
this.getList();
},immediate:true
}
},複製程式碼
深度監聽
- 使用環境
在監聽物件的時候,物件的內部屬性發生變化watch無法監聽到,這種時候就需要使用深度監聽,詳情請看我的這一篇部落格Vue由淺入深系列(二)詳解Watch偵聽器
- 實際使用
只需要設定deep:true
即可開啟深度監聽
data(){
return{
queryList:{
count:0,name:'',}
}
},watch:{
queryList(newValue,oldValue){
//do something
}
},複製程式碼
計算屬性之setter
- 實際使用
我們一般平常使用的都是
getter
,但其實它還有個setter
,當計算屬性的fullName
觸發更新的時候,就會觸發setter
回撥,計算屬性詳情請看我的這一篇部落格Vue由淺入深系列(三)詳解Computed計算屬性
data(){
return{
firstName:'',lastName:'',computed:{
fullName:{
get(){
return `${this.firstName} ${this.lastName}`;
},set(newValue){
let names=newValue.split(' ');
this.firstName=names[0];
this.lastName=names[1];
}
}
},複製程式碼
$on('hook:生命週期')來簡化window監聽
- 實際使用
先來看一下平常的使用方法
mounted () {
window.addEventListener('resize',this.resizeHandler);
},beforeDestroy () {
window.removeEventListener('resize',this.resizeHandler);
}
複製程式碼
改寫以後的程式碼為,相比於上面的寫法,這個寫法的好處在於可以開啟一個事件監聽器的同時,就在beforeDestroy
生命週期中掛載一個刪除事件監聽器的事件。比上面的寫法會更加安全,更加有助於避免記憶體洩露並防止事件衝突
mounted () {
window.addEventListener('resize',this.resizeHandler);
this.$on("hook:beforeDestroy",() => {
window.removeEventListener('resize',this.resizeHandler);
})
}
複製程式碼
子元件@hook:生命週期
監聽子元件的生命週期回撥
- 實際使用
<child @hook:mounted="listenChildMounted" />
複製程式碼
v-pre
- 使用環境
不需要編譯的html程式碼可以使用v-pre,可以提高效能
- 實際使用
<span v-pre>{{message}}</span> //就算data裡面定義了message,渲染完也是{{message}}
複製程式碼
v-once
- 使用環境
只需要渲染一次,適用於渲染完以後就不會更新的內容,降低效能開銷
- 實際使用
<span v-once>{{message}}</span> //message的值會編譯後渲染,但是編譯以後再次修改message的值不會觸發更新
複製程式碼
- v-pre與v-once的區別
v-pre相當於不編譯,直接顯示,v-once相當於只編譯一次,後面的更新不編譯了
Vue.set()
- 使用環境
當你利用索引直接設定一個數組項時或你修改陣列的長度時,由於Object.defineprototype()
方法限制,資料不響應式更新
- 實際使用
this.$set(arr,index,item);
複製程式碼
keep-alive
- 使用環境
當這個頁面沒有資料更新,或者是想儲存狀態,下次進來還是這樣子的時候,例如淘寶檢視列表頁,點進去檢視詳情之後,返回列表頁依舊到上次瀏覽到的地方,都可以使用keep-alive
- 實際使用
分為配合路由使用,使用
max,include,exclude
,以及特殊的生命週期activated
和deactivated
,詳情請看我的這一篇部落格 Vue由淺入深系列(一)詳解keep-alive
$route路由資訊
- $route.query.id
用來拿取路由傳值的資訊,比如路由的字尾?id=1,$route.query.id拿到的值為1
- $route.meta.flag
用來拿取路由meta中的資訊,路由資訊裡的meta是可以自定義屬性的,我一般導航欄當前選中的nav用來和$route.meta.flag進行匹配,來拿到當前頁面應該啟用哪一個選項卡
- base路由
比方說百度的所有路由字首要加/baidu
,那麼可以設定路由的base為/baidu
export const router = new Router({
base:'/baidu/',}
複製程式碼
此外,打包的時候,請修改config/index.js
的build
塊中的assetsPublicPath
為 '/baidu/',不然打包以後是找不到資原始檔路徑的
module.exports = {
build:{
assetsPublicPath: '/baidu/',}
}
複製程式碼
- 全域性路由鉤子
使用場景一般為使用者的登入鑑權
router.beforeEach((to,from,next) => {
//一定要呼叫next()才能到下一個頁面
if (path === '/login') {
next()
}else{
if(token){
next();
}else{
next('/login');
}
}
})
複製程式碼
- 元件路由鉤子中訪問this
元件路由的鉤子一開始還未初始化,不能訪問到vue例項
beforeRouteEnter (to,from,next) {
// 這裡還無法訪問到元件例項,this === undefined
next( vm => {
// 通過 vm
訪問元件例項
})
}
樣式穿透
- 使用環境
一般在修改外掛樣式的時候使用的比較多
- 實際使用
分為兩種,一般stylus
中使用>>>
,less
中使用/deep/
,sass
沒有使用經驗,不予說明
>>>.el-dialog .el-dialog__body{
padding 0
text-align center
border-radius 0 0 4px 4px
}
/deep/.el-dialog .el-dialog__body{
padding 0
text-align center
border-radius 0 0 4px 4px
}
複製程式碼
Object.freeze()
- 使用環境
我們都知道vue
是使用Object.defineProperty
對資料進行雙向繫結,而對於只做展示使用的長列表,可以使用Object.freeze()進行凍結,使它無法被修改,從而提高效能
- 實際使用
getList().then(res=>{
this.list=Object.freeze(res.data.result);
})
複製程式碼
值得注意的是,改變list的值不會更新,但改變引用會觸發更新
元件通訊技巧
props
$emit
-
$attrs
&$listeners
-
provide
&inject
vuex
Observable
eventBus
$refs
-
slot-scope
&v-slot
scopedSlots
-
$parent
&$children
&$root
詳細使用可以檢視我的這一篇部落格一篇文章看懂Vue.js的11種傳值通訊方式
mixins混入的使用
- 使用環境
一般獲取驗證碼,收藏,點贊等公用且邏輯一樣(有些邏輯是根據頁面的不同而不同的不建議使用混入)等場景都可以使用混入
- 實際使用
這裡我直接封裝了一個vue新開視窗的混入方法,引入了以後,混入中的所有data,methods
,以及生命週期都會共享
//openWindow.js
export default {
methods:{
openUrl(url){
const link= this.$router.resolve({path: url});
window.open(link.href,'_blank');
},}
}
//其他頁面使用
import openWindow from "../../mixins/openWindow";
export default{
mixins:[openWindow],}
複製程式碼
- 注意點(使用的頁面統稱為元件)
① 混入比元件優先執行
② 當混入中的屬性或者方法與元件中的屬性或者方法名稱相同時,以元件中的值為準(結合上一條規則,因為混入先執行,所以元件會將混入覆蓋)
③ 比方說A頁面和B頁面都使用了同一個混入,A頁面與B頁面的狀態同樣是獨立的
qs
-
使用場景,
get
傳輸的時候都是路由拼接方式(?a=1&b=2),而不是json
方式 -
實際使用
//安裝依賴
npm install qs --save
//頁面中或者直接api.js中直接序列化使用
import qs from 'qs'
qs.stringify(params)
//axios攔截器中直接使用
import qs from 'qs'
axios.interceptors.request.use(
config => {
if (config.method === 'get') {
config.data = qs.stringify(config.data)
}
)
複製程式碼
v-for繫結key不建議使用index,建議使用另外的並且值唯一的變數,例如後臺給你的id
- 主要原因
有的時候v-for列表可能存有刪除,交換位置等操作,這種時候index的順序變換會導致同一條資料,在此刻的index置換,所以,不建議v-for的key繫結index
v-for不建議配合v-if
- 主要原因
v-for的優先順序比v-if高,也就是說,假設總計50條資料,即使經過v-if以後,只剩下25條顯示,但是v-for早就迴圈了一遍50條資料,解決辦法就是用一個計算屬性先將資料過濾了以後,v-for迴圈過濾了之後的資料
document.body.contentEditable
- 操作方法
開啟控制檯,輸入document.body.contentEditable=true
,然後敲回車,網頁可以像word一樣編輯,很方便對於頁面的佈局抗壓能力做測試