01、slots 新語法向 3.0 看齊
使用帶有“#”的新命名插槽縮寫語法,在Vue 2.6.0+中可用
舉個例子:
構建插槽時,最好規劃一下佈局。這就是我的文章佈局。
構建插槽與構建元件沒有什麼不同。本質上,插槽是具有超強功能的元件,讓我們細分一下上面的佈局,元件的外觀如下:
<div v-bind:[attr]="attributeName"></div>//簡寫<div :[attr]="attributeName"></div>
這裡的 attributeName 會被作為一個JavaScript表示式進行動態求值,求得的值將會作為最終的引數來使用。例如,如果你的 Vue 例項有一個 data 屬性 attributeName,其值為 href,那麼這個繫結將等價於 v-bind:href
同樣地,你可以使用動態引數為一個動態的事件名繫結處理函式:
<button v-on:[eventName]="handler"></button>//簡寫<button @[eventName]="handler"></button>
當 eventName 的值為 focus 時,v-on:[eventName] 將等價於 v-on:focus。
同樣可以適用於插槽繫結:
<my-component><template v-slot:[slotName]>Dynamic slot name</template></my-component>//簡寫<foo><template #[name]>Default slot</template></foo>
動態引數預期會求出一個字串,異常情況下值為 null。這個特殊的 null 值可以被顯性地用於移除繫結。任何其它非字串型別的值都將會觸發一個警告。
03、@hook那些事
處理元件內定時器的步驟。通常我們一般都是這樣操作的:
<script> export default { mounted() { this.timer = setInterval(() => { ... }, 1000); }, beforeDestroy() { clearInterval(this.timer); } };</script>
但是其實更好的做法是:
<script> export default { mounted() { const timer = setInterval(() => { ... }, 1000); this.$once('hook:beforeDestroy', () => clearInterval(timer);) } };</script>
設想一個場景 如果我們需要在資料渲染到頁面的之前讓頁面 loading。mounted 之後停止 loading。beforeUpdata 時開始 loading。updatad 之後停止 loading。
最簡單的方法就是改寫元件的生命週期函式,使其在 mounted/beforeUpdata /updatad 時通知父元件顯示或者隱藏 loading。
這樣做顯示不好,因為侵入了自元件的邏輯,增加的邏輯也和元件本身的功能好不關聯。最好的辦法就是使用 v-on="hook:xxx" 的方式:
<v-chart @hook:mounted="loading = false" @hook:beforeUpdated="loading = true" @hook:updated="loading = false" :data="data"/>
這樣,就實現了對子元件生命週期的監聽。對任意的元件都有效果,包括引入的第三方元件。
04、vue中的$props、$attrs和$listeners(可用來二次封裝元件)
$props:當前元件接收到的 props 物件。Vue 例項代理了對其 props 物件屬性的訪問。
假如有個input輸入框。我們有很多的原生屬性,比如:name、placeholder、disabled等等。我們如果都定義在props顯示接收,未免太過繁瑣。所以官網出現了:v-bind="$props"這樣的操作。如果父元件傳遞很多的原生屬性,那麼我們在子元件中直接可以:
//good<input v-bind="$props">//bad//而不是下面這樣,如果很多的屬性就特別繁瑣<input :name="name" :placeholder="placeholder" :disabled="disabled">
我們可以利用以下方式$attrs 將原生屬性直接傳遞給子元件,這是Vue在2.4.0新增的屬性,包含了父作用域中不作為 prop 被識別 (且獲取) 的特性繫結 (class 和 style 除外)。
當一個元件沒有宣告任何 prop 時,這裡會包含所有父作用域的繫結 (class 和 style 除外),並且可以透過 v-bind="$attrs" 傳入內部元件——在建立高級別的元件時非常有用。
$listeners:包含了父作用域中的 (不含 .native修飾器的) v-on 事件監聽器。它可以透過 v-on="$listeners" 傳入內部元件——在建立更高層次的元件時非常有用。
如果子元件不在父元件的根目錄下,則可以將所有事件偵聽器從父元件傳遞到子元件,如下所示:
<template><div> ...<childComponent v-on="$listeners" />...</div></template>
05、響應式資料(2.6.0新增)
我們習慣於用Vuex去解決狀態的共享問題,但是在小專案中使用就會有增大程式碼體積和將程式碼複雜化的煩惱,所以在後來的版本中Vue新增
Vue.observable( object )讓一個物件可響應,Vue 內部會用它來處理 data 函式返回的物件。
返回的物件可以直接用於渲染函式和 計算屬性 內,並且會在發生改變時觸發相應的更新。也可以作為最小化的跨元件狀態儲存器,用於簡單的場景:
官方示例:
const state = Vue.observable({ count: 0 })const Demo = { render(h) { return h('button', { on: { click: () => { state.count++ }} }, `count is: ${state.count}`) }}
06、jsx模板元件
以下面的一組狀態判斷按鈕為例,我們很容易就下意識地在模板內寫下這種程式碼
<button v-if="status === 1" class="btn1" :class="status === 1" @click="">未開始</button><button v-if="status === 2" class="btn2" :class="status === 2" @click="">進行中</button><button v-if="status === 3" class="btn3" :class="status === 3" @click="">可領取</button><button v-if="status === 4" class="btn4" :class="status === 4" @click="">已領取</button>
但是如果我們利用渲染函式可以將上面的程式碼抽取成優雅的使用元件
<!DOCTYPE html><html lang="en"><body> <div id="app"> <child :status="status"></child> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> Vue.component('child', { props: { status: { type: Number, required: true } }, render(createElement) { const innerHTML = ['未開始', '進行中', '可領取', '已領取'][this.status] return createElement('button', { class: { active: this.status }, attrs: { id: 'btn' }, domProps: { innerHTML }, on: { click: () => console.log(this.status) } }) } }) var app = new Vue({ el: '#app', data: { status: 0 } })</script></body></html>
我們將所有的邏輯封裝進渲染函式內,外部只需要傳遞一個狀態引數即可改變
<child :status="status"></child>
07、動態元件
透過 Vue 的 元素加一個特殊的 is attribute 可以實現動態元件的效果
如圖,這是一個v-for渲染的列表(只是目前這個版塊才剛開始做,目前只有一個),圓圈內的就是一個元件,也就是要v-for動態元件。
實際使用
一開始就是基本的元件引入了
import ColorIn from '@/components/Magic/ColorIn.vue'import LineIn from "@/components/Magic/LineIn.vue";import Header from "@/components/Magic/Header.vue";import Footer 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>
08、Vue.filter
簡單介紹一下過濾器,顧名思義,過濾就是一個數據經過了這個過濾之後出來另一樣東西,可以是從中取得你想要的,或者給那個資料新增點什麼裝飾,那麼過濾器則是過濾的工具。例如,從['abc','abd','ade']陣列中取得包含‘ab’的值,那麼可透過過濾器篩選出來‘abc’和‘abd’;把‘Hello’變成‘Hello World’,那麼可用過濾器給值‘Hello’後面新增上‘ World’;或者把時間節點改為時間戳等等都可以使用過濾器。
場景:時間戳轉化成年月日這是一個公共方法,所以可以抽離成過濾器使用
// 使用// 在雙花括號中{{ message | capitalize }}// 在 `v-bind` 中<div v-bind:id="rawId | formatId"></div>// 全域性註冊Vue.filter('stampToYYMMDD', (value) =>{ // 處理邏輯})// 區域性註冊filters: { stampToYYMMDD: (value)=> { // 處理邏輯 }}// 多個過濾器全域性註冊// /src/common/filters.jslet dateServer = value => value.replace(/(\d{4})(\d{2})(\d{2})/g, '$1-$2-$3') export { dateServer }// /src/main.jsimport * as custom from './common/filters/custom'Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))
09、sync 語法糖sync 就是為了實現prop 進行“雙向繫結”僅此而已(父對子,子對父,來回傳)
當你有需要在子元件修改父元件值的時候這個方法很好用,它的實現機制和v-model是一樣的。
10、利用 object.freeze 提升效能Object.freeze() 方法可以凍結一個物件。一個被凍結的物件再也不能被修改;凍結了一個物件則不能向這個物件新增新的屬性,不能刪除已有屬性,不能修改該物件已有屬性的可列舉性、可配置性、可寫性,以及不能修改已有屬性的值。此外,凍結一個物件後該物件的原型也不能被修改。freeze() 返回和傳入的引數相同的物件。
比方我們需要渲染一個非常大的陣列物件,例如使用者列表,物件列表,文章列表等等。
export default { data: () => ({ users: {} }), async created() { const users = await axios.get("/api/users"); this.users = users; }};
vue 會將 data 物件中的所有的屬性加入到 vue 的響應式系統中,當這些屬性的值發生改變時,檢視將會產生 響應,若物件的體積比較大,會消耗很多瀏覽器解析時間。
所以我們可以透過減少資料的響應式轉換來提供前端的效能。
export default { data: () => ({ users: {} }), async created() { const users = await axios.get("/api/users"); this.users = Object.freeze(users); }};