你或許不知道Vue的這些小技巧
來自專欄猿論
前言
用Vue開發一個網頁並不難,但是也經常會遇到一些問題,其實大部分的問題都在文檔中有所提及,再不然我們通過谷歌也能成功搜索到問題的答案,為了幫助小夥伴們提前踩坑,在遇到問題的時候,心裡大概有個譜知道該如何去解決問題。這篇文章是將自己知道的一些小技巧,結合查閱資料整理成的一篇文章,如果喜歡的話可以點波贊/關注,支持一下,希望大家看完本文可以有所收穫。
個人博客了解一下:obkoro1.com
文章內容總結:
- 組件style的scoped
- Vue 數組/對象更新 視圖不更新
- vue filters 過濾器的使用
- 列表渲染相關
- 深度watch與watch立即觸發回調
- 這些情況下不要使用箭頭函數
- 路由懶載入寫法
- 路由的項目啟動頁和404頁面
- Vue調試神器:vue-devtools
組件style的scoped:
問題:在組件中用js動態創建的dom,添加樣式不生效。
場景:
<template> <div class="test"></div> </template> <script> let a=document.querySelector(.test); let newDom=document.createElement("div"); // 創建dom newDom.setAttribute("class","testAdd" ); // 添加樣式 a.appendChild(newDom); // 插入dom </script> <style scoped> .test{ background:blue; height:100px; width:100px; } .testAdd{ background:red; height:100px; width:100px; } </style>
結果:
// test生效 testAdd 不生效<div data-v-1b971ada class="test"><div class="testAdd"></div></div>.test[data-v-1b971ada]{ // 注意data-v-1b971ada background:blue; height:100px; width:100px;}
原因:
當 <style>
標籤有 scoped 屬性時,它的 CSS 只作用於當前組件中的元素。
它會為組件中所有的標籤和class樣式添加一個scoped
標識,就像上面結果中的data-v-1b971ada
。
所以原因就很清楚了:因為動態添加的dom沒有scoped
添加的標識,沒有跟testAdd
的樣式匹配起來,導致樣式失效。
解決方式
- 推薦:去掉該組件的scoped
每個組件的css並不會很多,當設計到動態添加dom,並為dom添加樣式的時候,就可以去掉scoped,會比下面的方法方便很多。
- 可以動態添加style// 上面的栗子可以這樣添加樣式newDom.style.height=100px;
newDom.style.width_=100px;
newDom.style.background=red;
Vue 數組/對象更新 視圖不更新
很多時候,我們習慣於這樣操作數組和對象:
data() { // data數據 return { arr: [1,2,3], obj:{ a: 1, b: 2 } }; }, // 數據更新 數組視圖不更新 this.arr[0] = OBKoro1; this.arr.length = 1; console.log(arr);// [OBKoro1]; // 數據更新 對象視圖不更新 this.obj.c = OBKoro1; delete this.obj.a; console.log(obj); // {b:2,c:OBKoro1}
由於js的限制,Vue 不能檢測以上數組的變動,以及對象的添加/刪除,很多人會因為像上面這樣操作,出現視圖沒有更新的問題。
解決方式:
- this.$set(你要改變的數組/對象,你要改變的位置/key,你要改成什麼value)this.$set(this.arr, 0, "OBKoro1"); // 改變數組this.$set(this.obj, "c", "OBKoro1"); // 改變對象
如果還是不懂的話,可以看看這個codependemo。
- 數組原生方法觸發視圖更新:
Vue可以監測到數組變化的,數組原生方法:
splice()、 push()、pop()、shift()、unshift()、sort()、reverse()
意思是使用這些方法不用我們再進行額外的操作,視圖自動進行更新。
推薦使用splice
方法會比較好自定義,因為slice可以在數組的任何位置進行刪除/添加操作,這部分可以看看我前幾天寫的一篇文章:【乾貨】js 數組詳細操作方法及解析合集
- 替換數組/對象
比方說:你想遍歷這個數組/對象,對每個元素進行處理,然後觸發視圖更新。
// 文檔中的栗子: filter遍曆數組,返回一個新數組,用新數組替換舊數組 example1.items = example1.items.filter(function (item) { return item.message.match(/Foo/) })
舉一反三:可以先把這個數組/對象保存在一個變數中,然後對這個變數進行遍歷,等遍歷結束後再用變數替換對象/數組。
並不會重新渲染整個列表:
Vue 為了使得 DOM 元素得到最大範圍的重用而實現了一些智能的、啟發式的方法,所以用一個含有相同元素的數組去替換原來的數組是非常高效的操作。
如果你還是很困惑,可以看看Vue文檔中關於這部分的解釋。
vue filters 過濾器的使用:
過濾器,通常用於後台管理系統,或者一些約定類型,過濾。Vue過濾器用法是很簡單,但是很多朋友可能都沒有用過,這裡稍微講解一下。
在html模板中的兩種用法:
<!-- 在雙花括弧中 --> {{ message | filterTest }} <!-- 在 `v-bind` 中 --> <div :id="message | filterTest"></div>
在組件script
中的用法:
export default { data() { return { message:1 } }, filters: { filterTest(value) { // value在這裡是message的值 if(value===1){ return 最後輸出這個值; } } }}
用法就是上面講的這樣,可以自己在組件中試一試就知道了,很簡單很好用的。
如果不想自己試,可以點這個demo裡面修改代碼就可以了,demo中包括過濾器串聯、過濾器傳參。
推薦看Vue過濾器文檔,你會更了解它的。
列表渲染相關
v-for循環綁定model:
input在v-for中可以像如下這麼進行綁定,我敢打賭很多人不知道。
// 數據 data() { return{ obj: { ob: "OB", koro1: "Koro1" }, model: { ob: "默認ob", koro1: "默認koro1" } } }, // html模板 <div v-for="(value,key) in obj"> <input type="text" v-model="model[key]"> </div> // input就跟數據綁定在一起了,那兩個默認數據也會在input中顯示
為此,我做了個demo,你可以點進去試試。
一段取值的v-for
如果我們有一段重複的html模板要渲染,又沒有數據關聯,我們可以:
<div v-for="n in 5"> <span>這裡會被渲染5次,渲染模板{{n}}</span> </div>
v-if盡量不要與v-for在同一節點使用:
v-for 的優先順序比 v-if 更高,如果它們處於同一節點的話,那麼每一個循環都會運行一遍v-if。
如果你想根據循環中的每一項的數據來判斷是否渲染,那麼你這樣做是對的:
<li v-for="todo in todos" v-if="todo.type===1"> {{ todo }} </li>
如果你想要根據某些條件跳過循環,而又跟將要渲染的每一項數據沒有關係的話,你可以將v-if放在v-for的父節點:
// 根據elseData是否為true 來判斷是否渲染,跟每個元素沒有關係 <ul v-if="elseData"> <li v-for="todo in todos"> {{ todo }} </li> </ul> // 數組是否有數據 跟每個元素沒有關係 <ul v-if="todos.length"> <li v-for="todo in todos"> {{ todo }} </li> </ul> <p v-else>No todos left!</p>
如上,正確使用v-for與v-if優先順序的關係,可以為你節省大量的性能。
深度watch與watch立即觸發回調
watch很多人都在用,但是這watch中的這兩個選項deep
、immediate
,或許不是很多人都知道,我猜。
選項:deep
在選項參數中指定 deep: true
,可以監聽對象中屬性的變化。
選項:immediate
在選項參數中指定 immediate: true, 將立即以表達式的當前值觸發回調,也就是默認觸發一次。
watch: { obj: { handler(val, oldVal) { console.log(屬性發生變化觸發這個回調,val, oldVal); }, deep: true // 監聽這個對象中的每一個屬性變化 }, step: { // 屬性 //watch handler(val, oldVal) { console.log("默認觸發一次", val, oldVal); }, immediate: true // 默認觸發一次 }, },
這兩個選項可以同時使用,另外:是的,又有一個demo。
還有下面這一點需要注意。
這些情況下不要使用箭頭函數:
- 不應該使用箭頭函數來定義一個生命周期方法
- 不應該使用箭頭函數來定義 method 函數
- 不應該使用箭頭函數來定義計算屬性函數
- 不應該對 data 屬性使用箭頭函數
- 不應該使用箭頭函數來定義 watcher 函數
示例:
// 上面watch的栗子: handler:(val, oldVal)=> { // 可以執行 console.log("默認觸發一次", val, oldVal); }, // method: methods: { plus: () => { // 可以執行 // do something } } // 生命周期: created:()=>{ // 可以執行 console.log(lala,this.obj) },
是的,沒錯,這些都能執行。
but:
箭頭函數綁定了父級作用域的上下文,this 將不會按照期望指向 Vue 實例。
也就是說,你不能使用this來訪問你組件中的data數據以及method方法了。
this將會指向undefined。
路由懶載入寫法:
// 我所採用的方法,個人感覺比較簡潔一些,少了一步引入賦值。 const router = new VueRouter({ routes: [ path: /app, component: () => import(./app), // 引入組件 ] }) // Vue路由文檔的寫法: const app = () => import(./app.vue) // 引入組件 const router = new VueRouter({ routes: [ { path: /app, component: app } ] })
文檔的寫法在於問題在於:如果我們的路由比較多的話,是不是要在路由上方引入賦值十幾行組件?
第一種跟第二種方法相比就是把引入賦值的一步,直接寫在component
上面,本質上是一樣的。兩種方式都可以的,大家自由選擇哈。
路由的項目啟動頁和404頁面
實際上這也就是一個設置而已:
export default new Router({ routes: [ { path: /, // 項目啟動頁 redirect:/login // 重定向到下方聲明的路由 }, { path: *, // 404 頁面 component: () => import(./notFind) // 或者使用component也可以的 }, ] })
比如你的域名為:www.baidu.com
項目啟動頁指的是: 當你進入www.baidu.com
,會自動跳轉到login登錄頁。
404頁面指的是: 當進入一個沒有 聲明/沒有匹配 的路由頁面時就會跳轉到404頁面。
比如進入www.baidu.com/testRouter
,就會自動跳轉到notFind
頁面。
當你沒有聲明一個404頁面,進入www.baidu.com/testRouter
,顯示的頁面是一片空白。
Vue調試神器:vue-devtools
每次調試的時候,寫一堆console
是否很煩?想要更快知道組件/Vuex內數據的變化?
那麼這款尤大開發的調試神器:vue-devtools,你真的要了解一下了。
這波穩賺不賠,真的能提高開發效率。
安裝方法:
- 谷歌商店+科學上網,搜索vue-devtools即可安裝。
- 不會科學上網?手動安裝
安裝之後:
在chrome開發者工具中會看一個vue的一欄,如下對我們網頁應用內數據變化,組件層級等信息能夠有更準確快速的了解。
前幾個月也寫過一篇類似的:
Vue 實踐過程中的幾個問題
結語
本文的內容很多都在Vue文檔裡面有過說明,推薦大家可以多看看Vue文檔,不止看教程篇,還有文檔的Api什麼的,也都可以看。然後其實還有兩三點想寫的,因為預計篇幅都會比較長一點,所以準備留到以後的文章裡面吧~
文章如有不正確的地方歡迎各位路過的大佬鞭策!希望大家看完可以有所收穫,喜歡的話,趕緊點波訂閱關注/喜歡。
看完的朋友可以點個喜歡/關注,您的支持是對我最大的鼓勵。
個人blog and 掘金個人主頁,如需轉載,請放上原文鏈接並署名。碼字不易,感謝支持!
如果喜歡本文的話,歡迎關注我的訂閱號,漫漫技術路,期待未來共同學習成長。
以上2018.6.3
參考資料:
Vue文檔
Vue Api文檔
作者:OBKoro1
鏈接:https://www.imooc.com/article/32884
來源:慕課網
本文原創發佈於慕課網 ,轉載請註明出處,謝謝合作
推薦閱讀:
【重磅】認證作者招募 | 打造個人品牌 so easy !
有獎徵文004期|從小白到大牛,進階路上有話說?
Flex入坑指南
PHP中的10個實用函數
向Go轉型的點滴
推薦閱讀:
※請問vue組件如何reload或者說vue-router如何刷新當前的route??
※傳統項目使用Vue時,為了提高性能需要修改Vue源碼,可行嗎?
※前端來防止csrf,這個做法是否有漏洞?
※Vue2里對應Angular2的service的部分是什麼?是plugin嗎?