1. vue 3.0 的源代碼管理方式: monorepo
2. 指令:
2.1 v-once指令,只渲染一次:
<!--插值指令-->
v-once:<span v-once>{{counter}}</span>
2.2 動態改變dom的attr值
<a v-bind:[attrname]="url">attr 動態改變</a>
data(){
return {
attrname : 'href,
}
}
3. 計算屬性的getter和setter
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
4. v-for遍歷對象
<li v-for="(value, name, key) in object">{{key}}.{{name}}.{{value}}</li>
5. 數組更新檢測
Vue 將被偵聽的數組的變更方法進行了包裹,所以它們也將會觸發視圖更新。這些被包裹過的方法包括:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
6. 事件對象
1. 隱式event事件對象
methods中的function默認有一個隱式事件參數對象名是 event;
2. $event傳參
如果fun(num)需要傳參,則加上fun(num, $event)進行傳遞;
3. 事件修飾符:
3.1事件修飾符:
.stop
.prevent
.capture
.self
.once
.passive
- <!-- 阻止單擊事件繼續冒泡 -->
- <a @click.stop="doThis"></a>
- <!-- 提交事件不再重載頁面,阻止默認行爲 -->
- <form @submit.prevent="onSubmit"></form>
- <!-- 修飾符可以串聯 -->
- <a @click.stop.prevent="doThat"></a>
- <!-- 只有修飾符 -->
- <form @submit.prevent></form>
- <!-- 添加事件監聽器時使用事件捕獲模式 -->
- <!-- 即內部元素觸發的事件先在此處理,然後才交由內部元素進行處理 -->
- <div @click.capture="doThis">...</div>
- <!-- 只當在 event.target 是當前元素自身時觸發處理函數 -->
- <!-- 即事件不是從內部元素觸發的 -->
- <div @click.self="doThat">...</div>
- <!-- 點擊事件將只會觸發一次 -->
- <a @click.once="doThis"></a>
Vue 還對應 addEventListener
中的 passive 選項提供了 .passive
修飾符。
這個 .passive 修飾符尤其能夠提升移動端的性能。
<!-- 滾動事件的默認行爲 (即滾動行爲) 將會立即觸發, -->
<!-- 而不會等待 `onScroll` 完成, -->
<!-- 以防止其中包含 `event.preventDefault()` 的情況 -->
<div @scroll.passive="onScroll">...</div>
TIP
不要把 .passive 和 .prevent 一起使用,因爲 .prevent 將會被忽略,同時瀏覽器可能會向你展示一個警告。請記住,.passive 會告訴瀏覽器你不想阻止事件的默認行爲。
passived主要用於優化瀏覽器頁面滾動的性能,讓頁面滾動更順滑。
passive 的意思是“順從的”,表示它不會對事件的默認行爲說 no,瀏覽器知道了一個監聽器是 passive 的,它就可以在兩個線程裏同時執行監聽器中的 JavaScript 代碼和瀏覽器的默認行爲了。
3.2按鍵修飾符:
Vue 爲最常用的鍵提供了別名:
- .enter
- .tab
- .delete (捕獲“刪除”和“退格”鍵)
- .esc
- .space
- .up
- .down
- .left
- .right
3.3 表單輸入修飾符:
.lazy
在默認情況下,v-model
在每次 input
事件觸發後將輸入框的值與數據進行同步 (除了上述輸入法組織文字時)。你可以添加 lazy
修飾符,從而轉爲在 change
事件之後進行同步:
<!-- 在“change”時而非“input”時更新 -->
<input v-model.lazy="msg" />
.number
如果想自動將用戶的輸入值轉爲數值類型,可以給 v-model
添加 number
修飾符
<input v-model.number="age" type="text" />
.trim
如果要自動過濾用戶輸入的首尾空白字符,可以給 v-model
添加 trim
修飾符:
<input v-model.trim="msg" />
7組件
(1). props:
傳入一個對象的所有 property:
如果想要將一個對象的所有 property 都作爲 prop 傳入,可以使用不帶參數的 v-bind
(用 v-bind
代替 :prop-name
)。
post: {
id: 1,
title: 'My Journey with Vue'
}
模板:
<blog-post v-bind="post"></blog-post>
等價於:
<blog-post v-bind:id="post.id" v-bind:title="post.title"></blog-post>
(2) Prop 驗證
類型檢查
type
可以是下列原生構造函數中的一個:
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
此外,type
還可以是一個自定義的構造函數,並且通過 instanceof
來進行檢查確認。例如,給定下列現成的構造函數:
function
Person(firstName, lastName)
{
this.firstName
= firstName
this.lastName
= lastName
}
你可以使用:
app
.component('blog-post',
{
props:
{
author: Person
}
})
- validator自定義驗證函數:
props: {
// 基礎的類型檢查 (`null` 和 `undefined` 值會通過任何類型驗證)
propA: Number,
// 多個可能的類型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 帶有默認值的數字
propD: {
type: Number,
default: 100
},
// 帶有默認值的對象
propE: {
type: Object,
// 對象或數組的默認值必須從一個工廠函數返回
default() {
return { message: 'hello' }
}
},
// 自定義驗證函數
propF: {
validator(value) {
// 這個值必須與下列字符串中的其中一個相匹配
return ['success', 'warning', 'danger'].includes(value)
}
},
// 具有默認值的函數
propG: {
type: Function,
// 與對象或數組的默認值不同,這不是一個工廠函數——這是一個用作默認值的函數
default() {
return 'Default function'
}
}
}
(3)監聽子組件事件:
emits:
// 定義子組件的自定義事件
emits : ['child-event']; // vue3新特性,
emits: {
// 不驗證
//'child-event' : null
// 複雜驗證
'child-event' : (value) => {
if (value !== 'abc') {
console.log('驗證失敗~')
return false
} else {
return true
}
}
}
PS: 屬於vue3的新特性,在文檔上, 這塊內容分了兩個部分, 一個是“基礎組件”, 另一個是“深入組件”都有講解;
Vue2向vue3遷移策略:
強烈建議使用 emits 記錄每個組件所觸發的所有事件。
這尤爲重要,因爲我們移除了 .native 修飾符。任何未在 emits 中聲明的事件監聽器都會被算入組件的 $attrs,並將默認綁定到組件的根節點上。
8. slot插槽
1. 普通用法
- Props:
- name - string,用於具名插槽
- 用法:
<slot> 元素作爲組件模板之中的內容分發插槽。<slot> 元素自身將被替換。
// 模板
template : `
<div>{{message}}</div>
<div><slot></slot></div>
`
PS: v-slot 也支持縮寫方案, 用#號代替即可;
<html-a #header>header</html-a>
2. 具名插槽
具名插槽也就是給插槽起一個名字, 然後調用對應的內容, 而其它則被忽略;
<div id="app">
<html-a>****</html-a>
<html-a v-slot:header>header</html-a>
</div>
// 模板
template : `
<div>{{message}}</div>
<div><slot name="header"></slot></div>
`
3. 作用域插槽
有時讓插槽內容能夠訪問子組件中才有的數據是很有用的。當一個組件被用來渲染一個項目數組時,這是一個常見的情況,我們希望能夠自定義每個項目的渲染方式。
- 插槽提供了 v-slot:default 方案來處理, 具體如下:
<html-a v-slot:default="slotProps">
{{slotProps.message}}
</html-a>
template : `
<div>{{message}}</div>
<div><slot v-bind:message="message"></slot></div>
`
使用 ES6+的解構語法, 更加方便, 具體如下:
<html-a v-slot="{message}">
{{message}}
</html-a>
9. 應用實例
// 創建一個應用實例,{}裏是選項對象
const app = Vue.createApp({})
// app.mount()這個返回的是一個代理對象,並不返回應用本身
// 它返回的是這個組件本身,也就是根組件
const vm = app.mount('#app')
PS: .mount()方法作用是掛載 DOM 元素, 是 Vue 的應用 API, 並允許鏈式調用;
PS: 在“API 參考” 中找到“應用 API” 目錄, 可以參考更多的應用 API;
10. 生命週期
10.1 生命週期示意圖:
// 註冊
app
.directive('my-directive',
{
// 指令具有一組生命週期鉤子:
// 在綁定元素的 attribute 或事件監聽器被應用之前調用
created()
{},
// 在綁定元素的父組件掛載之前調用
beforeMount()
{},
// 在綁定元素的父組件掛載之後調用
mounted()
{},
// 在包含組件的 VNode 更新之前調用
beforeUpdate()
{},
// 在包含組件的 VNode 及其子組件的 VNode 更新之後調用
updated()
{},
// 在綁定元素的父組件卸載之前調用
beforeUnmount()
{},
// 在綁定元素的父組件卸載之後調用
unmounted()
{}
})
11. 動畫及轉場效果:
構建所需進場和離場的 CSS:
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s ease;
} .
fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
使用 Vue 的效果組件<transition>來實現過渡效果:
<transition name="fade">
<p v-if="show">顯示/隱藏</p>
</transition>
<button @click="show = !show">切換</button>
12. ref 和$refs 的使用:
在子組件上使用 ref 時, 在外部父組件調用時, 根據調用鏈對應即可;
<!--在子組件註冊 ref-->
<html-a ref="child"></html-a>
// 模板
template : `
<input type="text" ref="user" value="Mr.Wang">
`
// 掛載後,父組件的
mounted() {
// 調用子組件的 ref
console.log(this.$refs.child.$refs.user.value)
},
`
13. watch偵聽:
13.1 偵聽對象:
(1)如果要監聽的類型是對象, 那麼需要配合計算屬性進行監聽, 具體如下:
<div id="app">
<input type="text" v-model="user.name"><br>
{{user.name}}
</div>
data() {
return {
user: {
name: 'Mr.Lee'
}
}
},
// 計算屬性
computed: {
getUserName() {
return this.user.name
}
},
// 方法
methods: {
getValue(newValue, oldValue) {
console.log('new:' + newValue + ', old:' + oldValue)
}
},
// 監聽
watch: {
// 調用計算屬性監聽
getUserName: 'getValue'
}
(2) 也可以使用字符串方式監聽對象的屬性:
// 監聽對象
watch : {
// 字符串形式
'user.name' : 'getUser'
}
13.2 偵聽進階
①watch 提供了監聽的三種屬性,
具體如下:
(1) .handle: 要監聽的方法名;
(2) .deep: 是否開啓深度監聽;
(3) .immediate: 是否以當前的初始值執行方法(立即執行);
-使用數組的方式, 可以同時實現多個監聽;
// 方法
methods: {
getUser(obj) {
console.log('監聽 1~')
},
getUser2(obj) {
console.log('監聽 2~')
}
},
// 監聽對象
watch: {
user: [
{
handler: 'getUser',
deep: true,
},
{
handler: 'getUser2',
deep: true,
}
]
}
②$watch
-如果對於複雜的對象類型, 需要使用箭頭函數來表示需要監聽的內容;
this.$watch(() => this.user.name, (newValue, oldValue) => {
console.log(newValue + ',' + oldValue)
})
-PS: 這裏本身會返回一個取消偵聽的函數;
const unwatch = vm.$watch...
// 可以根據業務適時取消監聽
unwatch()
- $watch 也支持深度監聽的, 支持關鍵字 deep 和 immediate 選項;
// 深度監聽
this.$watch('user', (obj) => {
console.log(obj.age)
}, {
deep: true,
immediate: true
})
14. 混入可複用
1. 混入(mixin): 用來分發 Vue 組件中可複用的部分, 先簡單的看下語法
// 創建一個要複用的混入 Mixin
const baseMixin = {
data() {
return {
count: 0
}
},
created() {
this.count = 100
}
}
// 創建一個應用實例,
const app = Vue.createApp({
// 載入複用的混入
mixins: [baseMixin],
})
2. 選項合併: 如果在組件體內設置自己的選項內容時, 會進行恰當的合併;
(1) .重名時, 會替換掉混入的部分, 沒有重名, 則合併;
(2) .如果複用的部分有聲明週期鉤子, 比如 created(), 將會執行這個;
(3) .如果複用的部分都有聲明週期鉤子, 那麼兩個鉤子都會被執行;
(4) .如果複用的部分有 methods 等方法, 重名將覆蓋, 不重名則合併;