您好,登錄后才能下訂單哦!
本文主要內容:
來源于Vue文檔
你可能看過
但是你可能沒用過
vue的數據響應失效了
你知道什么情況下,vue的數據響應會是失效嗎??官方舉了個例子:
var?vm?=?new?Vue({ ?data:?{ ?items:?['a',?'b',?'c'] ?} }) vm.items[1]?=?'x'?//?不是響應性的vm.items.length?=?2?//?不是響應性的復制代碼
在日常的業務的處理中,尤其是數組的for循環渲染,當你使用完v-for之后,動態的通過操作index指定數組的值,不是響應的。?我們使用實際業務代碼舉個例子:
<template> ?<div> ?<div?v-for="(item,key)?in?list"?:key="key"> ?{{item}} ?</div> ?<button?@click="changeList">失效</button> ?<button?@click="respondList">響應</button> ?{{list}} ?</div></template><script>export?default?{?name:?'ex', ?data?()?{?return?{?list:?[11,?12,?{?money:?17?}] ?} ?},?methods:?{ ?changeList?()?{?//?失效代碼 ?this.list[0]?=?16 ?this.list.length?=?0 ?}, ?respondList?()?{?//?生效代碼 ?this.list[2].money?=?0 ?this.list[0]?=?16 ?} ?} }</script>復制代碼
然后我們來看一下會發生什么:
這就很有意思了,我們可以看到這個過程中,執行changeList()方法,頁面上的11并沒有變成16且數組也沒有變為空數組,但是執行第二個方法時,this.list已經為空數組,導致報錯。也就驗證了官網所說沒錯,我們不可以直接操作數組的item值,你想要的響應并不會發生。但是!大家可能會發現,好像自己項目里經常有這種操作,但是沒有發生這種問題,那么我們來看一下是什么導致我們在項目中忽略了這個問題。 請看:
我直接執行了respondList (),但是可以看到this.list[0] = 16這句也跟著一起響應了,這就是為什么我們日常項目中沒有出現這個問題的原因。因為在日常項目中很少會有單獨寫一個方法去改list[index],通常會伴隨著其他的對數組或者數組中對象的一些操作,而這些操作會觸發Vue的響應,Vue響應不是響應我們的代碼過程,他響應的是結果,而我們的代碼過程只是意味著是否會觸發Vue對代碼結果的響應。
簡單說,執行第一個方法,里面的2行代碼將list變為了空數組,但是這2行代碼都不會觸發Vue去響應,顧,頁面不變。
執行第二個方法,this.list[2].money = 0除了將money變為了0還觸發了Vue的響應機制,也就是方法執行完之后Vue會對list進行更新,所以第2行this.list[0] = 16將整個list修改完之后,方法結束,Vue更新list
所以我們要規避在Vue直接去單獨對數組的[index]和length去賦值,注意!是單獨。
vue的數據響應又又失效了?
你沒看錯,vue的數據響應又要上演失效了,這次的失效可能你平常項目中寫過很多,但是?你還是沒注意過!?該知識點來源于vue文檔的列表渲染里面的一小段提示代碼:
var?vm?=?new?Vue({ ?data:?{?a:?1 ?} })//?`vm.a`?現在是響應式的vm.b?=?2//?`vm.b`?不是響應式的復制代碼
闊怕,你從來沒想過你在項目中obj.a=1會不生效,這其中文檔中有2句話很重要:
還是由于 JavaScript 的限制,Vue?不能檢測對象屬性的添加或刪除。 對于已經創建的實例,Vue 不能動態添加根級別的響應式屬性。
相信我的加粗已經讓你意識到了問題所在,至于日常中為什么沒有感覺到失效是和上個例子一樣的,當然官方為這種單獨操作對象屬性方法
Vue.set(object, key, value)
具體使用方法可以回看文檔。
不止在{{}}中可以使用函數
我要表達的意思是不止在雙括號中可以使用函數,v-for也可以。 當然如果有人不知道雙括號可以使用函數,我們先來演示一遍:
<template> ?<div> ?<div?v-for="(item,key)?in?list"?:key="key"> ?{{filterList(item)}} ?</div> ?</div></template><script>export?default?{?name:?'ex', ?data?()?{?return?{?list:?[0,?1,?2] ?} ?},?methods:?{ ?filterList?(item)?{?if?(item?>?0)?{?return?'大于0' ?}?else?{?return?item ?} ?} ?} }</script>復制代碼
好的,接下來,文檔告訴我們一個技巧,直接看官網示例:<li?v-for="n?in?evenNumbers">{{?n?}}</li> 復制代碼 data:?{?numbers:?[?1,?2,?3,?4,?5?] }, computed:?{ ?evenNumbers:?function?()?{ ?return?this.numbers.filter(function?(number)?{ ?return?number?%?2?===?0 ?}) ?} } 復制代碼
可以直接用一個函數來代替v-for中的list,這樣可以結合計算屬性避免我們在每次獲取數據等業務場景下重新單獨處理list。
函數中直接調用當前元素的原生事件
首先說一下這個技巧適用于:
你要為某個元素綁定一個事件
你的事件里可能需要操作業務的同時,根據業務操作瀏覽器原生事件
綁定事件時可以用特殊變量 $event 把它傳入方法:
<button?v-on:click="warn('Form?cannot?be?submitted?yet.',?$event)"> ?Submit </button> 復制代碼//?...methods:?{ ?warn:?function?(message,?event)?{?//?現在我們可以訪問原生事件對象 ?if?(event)?event.preventDefault() ?alert(message) ?} } 復制代碼
該技巧適應場景有限,但是至少你要記住,vue可以直接在實踐中綁定event,去操作原生事件,因為總有一天你會發現有些p需求需要你去實現……
Vue的修飾符很多你知道嗎
有v-once也有.once
大家知道vue推薦對低開銷的靜態內容使用v-once渲染,但是如果你仔細看過文檔你應該知道v-once,首先v-once的原理其實是keep-alive,它會緩存v-once的組件,但是希望你再閱讀一次官方這句提示:
再說一次,試著不要過度使用這個模式。當你需要渲染大量靜態內容時,極少數的情況下它會給你帶來便利,除非你非常留意渲染變慢了,不然它完全是沒有必要的——再加上它在后期會帶來很多困惑。例如,設想另一個開發者并不熟悉v-once 或漏看了它在模板中,他們可能會花很多個小時去找出模板為什么無法正確更新。
是的,除非你這個組件渲染的開銷已經嚴重到你覺得他明顯的慢,否則不要使用。
然后我們來說事件的.once
<!--?點擊事件只會執行一次?--><form?@click.once="submit"></form>復制代碼
要注意不能將其應用于按鈕的點擊之后,它不同于按鈕的loading,點擊按鈕打開loading如果執行錯誤可以關閉loading,按鈕可以再次執行。
而使用.once事件觸發過一次之后,不會再次執行,當然你可以將它應用于其他事件,但是你要記住存在一個可以只讓你的事件只觸發一次的修飾符,總會用到的。
你認為的type="number"
大家在表單中如果要是用數字類型的input的時候通常我們會使用type=number,但是也許沒有人注意到input真正返回是什么,比如:
<template> ?<div> ?{{age}} ?<input?v-model.number="age"?type="number"?@change="lookAge"> ?{{year}} ?<input?v-model="year"?type="number"?@change="lookYear"> ?</div></template><script>export?default?{ ?data?()?{?return?{?age:?null,?year:?null ?} ?},?methods:?{ ?lookAge?()?{?console.log(this.age) ?}, ?lookYear?()?{?console.log(this.year) ?} ?} }</script>復制代碼
這一小段那代碼有什么區別呢?
首先,在渲染上,至少結果都是正確的,console的結果也是沒問題的,但是console調試的時候,藍色數字和白色數字有什么區別,也許很多人都沒注意過這個問題,回看看文檔就可以讓你理解我剛才提出的問題,文檔原文:如果想自動將用戶的輸入值轉為數值類型,可以給 v-model 添加 number 修飾符:
<input v-model.number="age" type="number">
這通常很有用,因為即使在 type="number" 時,HTML 輸入元素的值也總會返回字符串。如果這個值無法被 parseFloat() 解析,則會返回原始的值。 是滴,我覺得這對于用ts的人極其和諧。
如果你看到了上面的.number修飾符,那你一定可以在文檔中接著看到.trim修飾符:
如果要自動過濾用戶輸入的首尾空白字符,可以給 v-model 添加 trim 修飾符:
<input v-model.trim="msg">
這個問題我之前還真是碰見過,可惜我使用的方法是用js的trim去單獨處理了一遍,殊不知文檔如此簡單,我竟然不好好閱讀!
最后一個小技巧了
首先講一講我的菜鳥路程,在使用prop的時候剛開始我都是這樣寫:
props:?{?title, ?author } 復制代碼
后來我這樣寫:
props:?{?title:?String, ?author:?Object } 復制代碼
再后來我這樣寫:
props:?{?title:{?type:?String,?required:?true ?},?author:{?type:?Object,?required:?true ?}}復制代碼
然后我讀文檔發現還可以這樣寫:
props:?{?//?帶有默認值的對象 ?title:{?type:?String,?//?對象或數組默認值必須從一個工廠函數獲取 ?default:?function?()?{?return?{?message:?'hello'?} ?} ?},?//?自定義驗證函數 ?author:{?validator:?function?(value)?{?//?這個值必須匹配下列字符串中的一個 ?return?['au',?'th',?'or'].indexOf(value)?!==?-1 ?} ?} } 復制代碼
是的,prop也帶有驗證功能,且可以使用自定義驗證函數! 發現這算是個小技巧,但是最重要的在這段文檔后面:
當 prop 驗證失敗的時候,(開發環境構建版本的) Vue 將會產生一個控制臺的警告。
注意那些 prop 會在一個組件實例創建之前進行驗證,所以實例的屬性 (如?data、computed?等) 在 default 或validator 函數中是不可用的。
最關鍵一句在驗證函數中:data和計算屬性中的變量和方法都不可用。
到這就結束了,這是我最近利用上下班時間我vue文檔過了一遍,愿意主動將里面的一些遺漏或平常項目中很少用到,一直與忘記的小內容分享給各位。
如果有用給個評論,如果沒用不要吐槽我好不好,求你們了,哈哈。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。