Vue.js中讓人容易忽略的API詳解
nextTick
nextTick 是 Vue.js 提供的一個(gè)函數(shù),并非瀏覽器內(nèi)置。nextTick 函數(shù)接收一個(gè)回調(diào)函數(shù) cb,在下一個(gè) DOM 更新循環(huán)之后執(zhí)行。比如下面的示例:
<template> <div> <p v-if="show" ref="node">內(nèi)容</p> <button @click="handleShow">顯示</button> </div> </template> <script> export default { data () { return { show: false } }, methods: { handleShow () { this.show = true; console.log(this.$refs.node); // undefined this.$nextTick(() => { console.log(this.$refs.node); // <p>內(nèi)容</p> }); } } } </script>
當(dāng) show 被置為 true 時(shí),這時(shí) p 節(jié)點(diǎn)還未被渲染,因此打印出的是 undefined,而在 nextTick 的回調(diào)里,p 已經(jīng)渲染好了,這時(shí)能正確打印出節(jié)點(diǎn)。
nextTick 的源碼在github.com/vuejs/vue/b…,可以看到,Vue.js 使用了 Promise、setTimeout 和 setImmediate 三種方法來(lái)實(shí)現(xiàn) nextTick,在不同環(huán)境會(huì)使用不同的方法。
v-model 語(yǔ)法糖
v-model 常用于表單元素上進(jìn)行數(shù)據(jù)的雙向綁定,比如 <input>。除了原生的元素,它還能在自定義組件中使用。
v-model 是一個(gè)語(yǔ)法糖,可以拆解為 props: value 和 events: input。就是說(shuō)組件必須提供一個(gè)名為 value 的 prop,以及名為 input 的自定義事件,滿足這兩個(gè)條件,使用者就能在自定義組件上使用 v-model。比如下面的示例,實(shí)現(xiàn)了一個(gè)數(shù)字選擇器:
<template> <div> <button @click="increase(-1)">減 1</button> <span style="color: red;padding: 6px">{{ currentValue }}</span> <button @click="increase(1)">加 1</button> </div> </template> <script> export default { name: 'InputNumber', props: { value: { type: Number } }, data () { return { currentValue: this.value } }, watch: { value (val) { this.currentValue = val; } }, methods: { increase (val) { this.currentValue += val; this.$emit('input', this.currentValue); } } } </script>
props 一般不能在組件內(nèi)修改,它是通過(guò)父級(jí)修改的,因此實(shí)現(xiàn) v-model 一般都會(huì)有一個(gè) currentValue 的內(nèi)部 data,初始時(shí)從 value 獲取一次值,當(dāng) value 修改時(shí),也通過(guò) watch 監(jiān)聽(tīng)到及時(shí)更新;組件不會(huì)修改 value 的值,而是修改 currentValue,同時(shí)將修改的值通過(guò)自定義事件 input 派發(fā)給父組件,父組件接收到后,由父組件修改 value。所以,上面的數(shù)字選擇器組件可以有下面兩種使用方式:
<template> <InputNumber v-model="value" /> </template> <script> import InputNumber from '../components/input-number/input-number.vue'; export default { components: { InputNumber }, data () { return { value: 1 } } } </script>
或:
<template> <InputNumber :value="value" @input="handleChange" /> </template> <script> import InputNumber from '../components/input-number/input-number.vue'; export default { components: { InputNumber }, data () { return { value: 1 } }, methods: { handleChange (val) { this.value = val; } } } </script>
如果你不想用 value 和 input 這兩個(gè)名字,從 Vue.js 2.2.0 版本開(kāi)始,提供了一個(gè) model 的選項(xiàng),可以指定它們的名字,所以數(shù)字選擇器組件也可以這樣寫:
<template> <div> <button @click="increase(-1)">減 1</button> <span style="color: red;padding: 6px">{{ currentValue }}</span> <button @click="increase(1)">加 1</button> </div> </template> <script> export default { name: 'InputNumber', props: { number: { type: Number } }, model: { prop: 'number', event: 'change' }, data () { return { currentValue: this.number } }, watch: { value (val) { this.currentValue = val; } }, methods: { increase (val) { this.currentValue += val; this.$emit('number', this.currentValue); } } } </script>
在 model 選項(xiàng)里,就可以指定 prop 和 event 的名字了,而不一定非要用 value 和 input,因?yàn)檫@兩個(gè)名字在一些原生表單元素里,有其它用處。
.sync 修飾符
如果你使用過(guò) Vue.js 1.x,一定對(duì) .sync 不陌生。在 1.x 里,可以使用 .sync 雙向綁定數(shù)據(jù),也就是父組件或子組件都能修改這個(gè)數(shù)據(jù),是雙向響應(yīng)的。在 Vue.js 2.x 里廢棄了這種用法,目的是盡可能將父子組件解耦,避免子組件無(wú)意中修改了父組件的狀態(tài)。
不過(guò)在 Vue.js 2.3.0 版本,又增加了 .sync 修飾符,但它的用法與 1.x 的不完全相同。2.x 的 .sync 不是真正的雙向綁定,而是一個(gè)語(yǔ)法糖,修改數(shù)據(jù)還是在父組件完成的,并非在子組件。
仍然是數(shù)字選擇器的示例,這次不用 v-model,而是用 .sync,可以這樣改寫:
<template> <div> <button @click="increase(-1)">減 1</button> <span style="color: red;padding: 6px">{{ value }}</span> <button @click="increase(1)">加 1</button> </div> </template> <script> export default { name: 'InputNumber', props: { value: { type: Number } }, methods: { increase (val) { this.$emit('update:value', this.value + val); } } } </script>
用例:
<template> <InputNumber :value.sync="value" /> </template> <script> import InputNumber from '../components/input-number/input-number.vue'; export default { components: { InputNumber }, data () { return { value: 1 } } } </script>
看起來(lái)要比 v-model 的實(shí)現(xiàn)簡(jiǎn)單多,實(shí)現(xiàn)的效果是一樣的。v-model 在一個(gè)組件中只能有一個(gè),但 .sync 可以設(shè)置很多個(gè)。.sync 雖好,但也有限制,比如:
- 不能和表達(dá)式一起使用(如 v-bind:title.sync="doc.title + '!'" 是無(wú)效的);
- 不能用在字面量對(duì)象上(如 v-bind.sync="{ title: doc.title }" 是無(wú)法正常工作的)。
$set
在上一節(jié)已經(jīng)介紹過(guò) $set,有兩種情況會(huì)用到它:
由于 JavaScript 的限制,Vue 不能檢測(cè)以下變動(dòng)的數(shù)組:
- 當(dāng)利用索引直接設(shè)置一個(gè)項(xiàng)時(shí),例如:this.items[index] = value;
- 當(dāng)修改數(shù)組的長(zhǎng)度時(shí),例如:vm.items.length = newLength。
由于 JavaScript 的限制,Vue 不能檢測(cè)對(duì)象屬性的添加或刪除。
舉例來(lái)看,就是:
// 數(shù)組 export default { data () { return { items: ['a', 'b', 'c'] } }, methods: { handler () { this.items[1] = 'x'; // 不是響應(yīng)性的 } } }
使用 $set:
// 數(shù)組 export default { data () { return { items: ['a', 'b', 'c'] } }, methods: { handler () { this.$set(this.items, 1, 'x'); // 是響應(yīng)性的 } } }
以對(duì)象為例:
// 對(duì)象 export default { data () { return { item: { a: 1 } } }, methods: { handler () { this.item.b = 2; // 不是響應(yīng)性的 } } }
使用 $set:
// 對(duì)象 export default { data () { return { item: { a: 1 } } }, methods: { handler () { this.$set(this.item, 'b', 2); // 是響應(yīng)性的 } } }
另外,數(shù)組的以下方法,都是可以觸發(fā)視圖更新的,也就是響應(yīng)性的:
push()、pop()、shift()、unshift()、splice()、sort()、reverse()。
還有一種小技巧,就是先 copy 一個(gè)數(shù)組,然后通過(guò) index 修改后,再把原數(shù)組整個(gè)替換,比如:
handler () { const data = [...this.items]; data[1] = 'x'; this.items = data; }
計(jì)算屬性的 set
計(jì)算屬性(computed)很簡(jiǎn)單,而且也會(huì)大量使用,但大多數(shù)時(shí)候,我們只是用它默認(rèn)的 get 方法,也就是平時(shí)的常規(guī)寫法,通過(guò) computed 獲取一個(gè)依賴其它狀態(tài)的數(shù)據(jù)。比如:
computed: { fullName () { return `${this.firstName} ${this.lastName}`; } }
這里的 fullName 事實(shí)上可以寫為一個(gè) Object,而非 Function,只是 Function 形式是我們默認(rèn)使用它的 get 方法,當(dāng)寫為 Object 時(shí),還能使用它的 set 方法:
computed: { fullName: { get () { return `${this.firstName} ${this.lastName}`; }, set (val) { const names = val.split(' '); this.firstName = names[0]; this.lastName = names[names.length - 1]; } } }
計(jì)算屬性大多時(shí)候只是讀取用,使用了 set 后,就可以寫入了,比如上面的示例,如果執(zhí)行 this.fullName = 'Aresn Liang',computed 的 set 就會(huì)調(diào)用,firstName 和 lastName 會(huì)被賦值為 Aresn 和 Liang。
總結(jié)
到此這篇關(guān)于Vue.js中讓人容易忽略的API的文章就介紹到這了,更多相關(guān)Vue.js中易忽略的API內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue對(duì)Element中el-tab-pane添加@click事件無(wú)效問(wèn)題解決
這篇文章主要給大家介紹了關(guān)于Vue對(duì)Element中el-tab-pane添加@click事件無(wú)效問(wèn)題的解決辦法,文中通過(guò)圖文以及代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07vue路由傳參頁(yè)面刷新參數(shù)丟失問(wèn)題解決方案
這篇文章主要介紹了vue路由傳參頁(yè)面刷新參數(shù)丟失問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10Vue2?Observer實(shí)例dep和閉包中dep區(qū)別詳解
這篇文章主要為大家介紹了Vue2?Observer實(shí)例dep和閉包中dep區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Vue向后臺(tái)傳數(shù)組數(shù)據(jù),springboot接收vue傳的數(shù)組數(shù)據(jù)實(shí)例
這篇文章主要介紹了Vue向后臺(tái)傳數(shù)組數(shù)據(jù),springboot接收vue傳的數(shù)組數(shù)據(jù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11vue如何監(jiān)聽(tīng)el-select選擇值的變化
這篇文章主要介紹了vue如何監(jiān)聽(tīng)el-select選擇值的變化,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue 3項(xiàng)目如何安裝Element-Plus
Element Plus 是一個(gè)基于 Vue 3 的現(xiàn)代前端UI框架,它旨在提升開(kāi)發(fā)體驗(yàn),并為開(kāi)發(fā)者提供高效、優(yōu)雅的組件,在本文中將詳細(xì)介紹如何在 Vue 3 項(xiàng)目中安裝 Element Plus,感興趣的朋友一起看看吧2024-07-07vue組件之間通信實(shí)例總結(jié)(點(diǎn)贊功能)
這篇文章主要介紹了vue組件之間通信,結(jié)合實(shí)例形式分析了vue父子組件、兄弟組件之間通信的原理、實(shí)現(xiàn)方法,并給出了一個(gè)類似點(diǎn)贊功能的總結(jié)實(shí)例,需要的朋友可以參考下2018-12-12vue動(dòng)態(tài)綁定class的幾種常用方式小結(jié)
這篇文章主要介紹了vue動(dòng)態(tài)綁定class的幾種常用方式,結(jié)合實(shí)例形式總結(jié)分析了vue.js常見(jiàn)的對(duì)象方法、數(shù)組方法進(jìn)行class動(dòng)態(tài)綁定相關(guān)操作技巧,需要的朋友可以參考下2019-05-05