助你上手Vue3全家桶之Vue3教程


前言

這些內容是博主在學習過程中記錄下來的,有一些不重要的點就跳過了,需要時自行查詢文檔。其實V2V3的學習成本不高,熟悉V2的話,看完這篇文章就可以上手V3

Vue3官網

在線源碼編譯地址

1,setup


setup是所有Composition API的容器,值為一個函數。組件中所用到的數據、方法等等,均要配置在setup中,它會在beforeCreate之前執行一次,注意:V3this不再是指向Vue實例,訪問this會是undefined

1.1,返回值


  • 若返回一個對象,則對象中的屬性、方法, 在模板中均可以直接使用。
  • 若返回一個渲染函數:則可以自定義渲染內容。

1.2,注意點


盡量不要與V2配置混用

V2配置(datamethoscomputed...)中可以訪問到setup中的屬性、方法。
但在setup中不能訪問到V2配置(datamethodscomputed...)。
如果有重名, setup優先。

setup不能是一個async函數

因為返回值不再return的對象, 而是promise, 模板看不到return對象中的屬性。(后期也可以返回一個Promise實例,但需要Suspense和異步組件的配合)

1.3,語法


<script>
import { ref, reactive } from 'vue'

export default {
	name: 'Home',
	setup(props, context) {
		const title = ref('標題')
		const data = reactive({
			value: '哈哈哈'
		})
		return {
		  title,
		  data
		}
	}
}
</script>

1.4,setup的參數


  • props:值為對象,包含組件外部傳遞過來,且組件內部聲明接收了的屬性

  • context:上下文對象

    • attrs: 值為對象,包含組件外部傳遞過來,但沒有在props配置中聲明的屬性, 相當於this.$attrs
    • slots: 收到的插槽內容, 相當於this.$slots
    • emit: 分發自定義事件的函數, 相當於this.$emit

2,ref 創建響應式數據


使用ref可以創建一個包含響應式數據的引用對象(reference對象,簡稱ref對象),可以是基本類型、也可以是對象。

語法

// 創建
const xxx = ref(value)

// 使用
xxx.value

// 在模板中
<div>{{xxx}}</div>

3,reactive 創建響應式數據


定義一個對象類型的響應式數據,內部基於ES6Proxy實現,通過代理對象操作源對象內部數據進行操作

語法

// 創建
const xxx = reactive({
    xxx: ''
})

// 使用
xxx.xxx

4,computed 計算屬性


V2computed配置功能一致

語法

import { computed } from 'vue'

setup(){
	// 簡寫語法
    let fullName = computed(() => {
        return person.firstName + '-' + person.lastName
    })
    
    // 完整語法
    let fullName = computed({
        get(){
            return person.firstName + '-' + person.lastName
        },
        set(value){
            const nameArr = value.split('-')
            person.firstName = nameArr[0]
            person.lastName = nameArr[1]
        }
    })
    
    return fullName
}

5,watch 監聽


V2watch配置功能一致,語法有點改動

語法

  • 情況一:監視ref定義的響應式數據
watch(sum, (newValue, oldValue) => {
	console.log('sum變化了', newValue, oldValue)
}, {immediate:true})
  • 情況二:監視多個ref定義的響應式數據
watch([sum, msg], (newValue,oldValue) => {
	console.log('sum或msg變化了', newValue,oldValue)
}) 
  • 情況三:監視reactive定義的響應式數據
// 若watch監視的是reactive定義的響應式數據,則無法正確獲得oldValue
// 若watch監視的是reactive定義的響應式數據,則強制開啟了深度監視
watch(person, (newValue, oldValue) => {
	console.log('person變化了', newValue, oldValue)
}, { immediate:true, deep:false }) // 此處的deep配置不再奏效
  • 情況四:監視reactive定義的響應式數據中的某個屬性
watch(() => person.job, (newValue, oldValue) => {
	console.log('person的job變化了', newValue, oldValue)
}, { immediate:true, deep:true }) 
  • 情況五:監視reactive定義的響應式數據中的某些屬性
watch([() => person.job, () => person.name], (newValue, oldValue) => {
	console.log('person的job變化了', newValue, oldValue)
}, { immediate:true, deep:true })
  • 特殊情況:此處由於監視的是reactive素定義的對象中的某個屬性,所以deep配置有效
watch(() => person.job, (newValue, oldValue) => {
    console.log('person的job變化了', newValue, oldValue)
}, { deep:true })

6,watchEffect 監聽回調


watch的區別是,watch既要指明監視的屬性,也要指明監視的回調。而watchEffect,不用指明監視哪個屬性,監視的回調中用到哪個屬性,那就監視哪個屬性,不用寫返回值。

語法

// 回調中用到的數據只要發生變化,則直接重新執行回調
watchEffect(() => {
    const x1 = sum.value
    const x2 = person.age
    console.log('watchEffect配置的回調執行了')
})

7,生命周期


生命周期全都寫在setup

7.1,改變


  • beforeDestroy 改名為 beforeUnmount
  • destroyed 改名為 unmounted
  • beforeCreate => setup
  • created => setup
  • beforeMount => onBeforeMount
  • mounted => onMounted
  • beforeUpdate => onBeforeUpdate
  • updated => onUpdated
  • beforeUnmount => onBeforeUnmount
  • unmounted => onUnmounted

7.2,語法


setup() {
    onMounted(() => {
      console.log('mounted')
    })
}

8,toRef 創建ref


創建一個ref對象,其value值指向另一個對象中的某個屬性

語法

const state = reactive({
  foo: 1,
  bar: 2
})

const fooRef = toRef(state, 'foo')

// 傳遞props
export default {
  setup(props) {
    useSomeFeature(toRef(props, 'foo'))
  }
}

9,toRefs 響應式轉換


將響應式對象轉換為普通對象,其中結果對象的每個property都是指向原始對象相應propertyref

語法

const state = reactive({
  foo: 1,
  bar: 2
})

const stateAsRefs = toRefs(state)
// 此時state和stateAsRefs是關聯的

10,shallowReactive 響應式外層轉換


只處理對象最外層屬性的響應式(淺響應式)。適用於:一個對象數據,結構比較深, 但變化時只是外層屬性變化

語法

const state = shallowReactive({
  foo: 1,
  nested: {
    bar: 2
  }
})

11,shallowRef 基本數據響應式


只處理基本數據類型的響應式, 不進行對象的響應式處理。適用於:一個對象數據,后續功能不會修改該對象中的屬性,而是生新的對象來替換

語法

const shallow = shallowRef({
  greet: 'Hello, world'
})

12,readonly 響應式變只讀


讓一個響應式數據變為只讀的(深只讀),應用於不希望數據被修改時

語法

const shallow = shallowRef({
  greet: 'Hello, world', // 只讀
  nested: {
    bar: 2 // 只讀
  }
})

13,shallowReadonly 響應式變只讀


讓一個響應式數據變為只讀的(淺只讀),應用於不希望數據被修改時

語法

const shallow = shallowReadonly({
  foo: 1, // 只讀
  nested: {
    bar: 2 // 非只讀
  }
})

14,toRaw 響應式變非響應式


將一個由reactive生成的響應式對象轉為普通對象,對這個普通對象的所有操作,不會引起頁面更新。

語法

const foo = {}
const Foo = reactive(foo)
console.log(toRaw(Foo) === foo) // true

15,markRaw 標記永遠不響應式


標記一個對象,使其永遠不會再成為響應式對象,有些值不應被設置為響應式的,例如復雜的第三方類庫等,當渲染具有不可變數據源的大列表時,跳過響應式轉換可以提高性能。

語法

const foo = markRaw({})
console.log(isReactive(reactive(foo))) // false

// 嵌套在其他響應式對象中時也可以使用
const bar = reactive({ foo })
console.log(isReactive(bar.foo)) // false

16,customRef 依賴更新控制


創建一個自定義的 ref,並對其依賴項跟蹤和更新觸發進行顯式控制。它需要一個工廠函數,該函數接收tracktrigger函數作為參數,並且應該返回一個帶有getset的對象。

語法

<script>
import { customRef } from 'vue'

export default {
	name: 'Home',
	setup() {
	    // 實現防抖函數
		const fn = function(value, delay = 500) {
			let timeout
			return customRef((track, trigger) => {
				return {
					get() {
						track()
						return value
					},
					set(newValue) {
						clearInterval(timeout)
						timeout = setTimeout(() => {
							console.log(newValue)
							value = newValue
							trigger()
						}, delay)
					}
				}
			})
		}
		const keyword = fn('', 500)
		return {
			keyword
		}
	}
}
</script>

17,provide & inject 通信


實現祖與后代組件間通信,父組件有一個provide選項來提供數據,后代組件有一個inject選項來開始使用這些數據

語法

// 祖組件
setup(){
    let car = reactive({ name:'奔馳', price:'40萬' })
    provide('car', car)
}

// 后代組件
setup(props, context){
    const car = inject('car')
    return { car }
}

18,響應式數據的判斷


18.1,isRef


檢查一個值是否為一個ref對象

語法

const val = ref('xxx')
isRef(val) // true

18.2,isReactive


檢查一個值是否為一個isReactive對象

語法

const val = isReactive({})
isRef(val) // true

18.3,isReadonly


檢查一個對象是否是由readonly創建的只讀代理

語法

const state = reactive({
  name: 'John'
})
console.log(isReactive(state)) // true

18.4,isProxy


檢查對象是否是由reactivereadonly創建的proxy

語法

const state = reactive({
  name: 'John'
})
console.log(isProxy(state)) // true

19,teleport 移動dom組件


Teleport提供了一種干凈的方法,允許我們控制在DOM中哪個父節點下渲染了HTML,而不必求助於全局狀態或將其拆分為兩個組件。

語法

<teleport to="移動位置">
	<div v-if="isShow" class="mask">
		<div class="dialog">
			<h3>我是一個彈窗</h3>
			<button @click="isShow = false">關閉彈窗</button>
		</div>
	</div>
</teleport>


// to的格式
<teleport to="#some-id" />
<teleport to=".some-class" />
<teleport to="[data-teleport]" />

// disabled的格式
<teleport to="#popup" :disabled="displayVideoInline">
  <video src="./my-movie.mp4">
</teleport>

20,Suspense 異步渲染組件


等待異步組件時先渲染一些額外內容,讓應用有更好的用戶體驗

語法

<template>
	<div class="app">
		<h3>我是App組件</h3>
		<Suspense>
			<template #default>
				<Child/>
			</template>
			<template #fallback>
				<h3>加載中.....</h3>
			</template>
		</Suspense>
	</div>
</template>


import { defineAsyncComponent } from 'vue'
const Child = defineAsyncComponent(() => import('./components/Child.vue'))

components: {
    Child
}

21,全局API調整


將全局的API,即:Vue.xxx調整到應用實例(app)上

V2的api V3的api
Vue.config.xxxx app.config.xxxx
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use
Vue.prototype app.config.globalProperties

22,移除api


名稱 現狀
Vue.config.productionTip 已移除
config.keyCodes 已移除
$children 已移除
$listeners 已移除
$on 已移除
$off 已移除
$once 已移除
filters 已移除
.native 已移除

23,Ref 獲取DOM


由於V3中不在存在this,所以ref的獲取調整了

23.1,單個ref


語法

<div ref="Qrcode" class="qr_codeode_url" />

import { ref } from 'vue'

export default {
  setup() {
    const Qrcode = ref(null)
    // 掛載后
	onMounted(() => {
		console.log(Qrcode.value)
	})
    return {
      Qrcode
    }
  }
}

23.2,循環中的ref


V3中在for循環元素上綁定ref將不再自動創建$ref數組。要從單個綁定獲取多個ref,請將ref綁定到一個更靈活的函數上

語法

<div v-for="item in list" :ref="setItemRef"></div>

import { onBeforeUpdate, onUpdated } from 'vue'

export default {
  setup() {
    let itemRefs = []
    const setItemRef = el => {
      if (el) {
        itemRefs.push(el)
      }
    }
    onBeforeUpdate(() => {
      itemRefs = []
    })
    onUpdated(() => {
      console.log(itemRefs)
    })
    return {
      setItemRef
    }
  }
}
  • itemRefs不必是數組:它也可以是一個對象,其ref可以通過迭代的key被設置
  • 如有需要,itemRef也可以是響應式的,且可以被偵聽

24,emits 自定義事件


定義一個組件可以向其父組件觸發的事件

// 在子組件中
<h1 @click="father">{{ msg }}</h1>

export default {
	name: 'HelloWorld',
	props: {
		msg: {
			type: String,
			default: ''
		}
	},
	emits: ['close'],
	setup(props, { emit }) {
		const father = function() {
			emit('close', 'child')
		}
		return {
			father
		}
	}
}

// 在父組件中
<HelloWorld :msg="msg" @click="fn" @close="fn2" />

25,$nextTick 異步更新


使用方式修改

import { nextTick } from 'vue'

nextTick(() => {
  // ...
})

26,hook 生命周期事件


通過事件來監聽組件生命周期中的關鍵階段

語法

// V2的語法
<template>
  <child-component @hook:updated="onUpdated">
</template>

// V3的語法
<template>
  <child-component @vnode-updated="onUpdated">
</template>

// 駝峰寫法
<template>
  <child-component @vnodeUpdated="onUpdated">
</template

如果看了覺得有幫助的,我是@上進的鵬多多,歡迎 點贊 關注 評論;END


PS:在本頁按F12,在console中輸入document.querySelectorAll('.diggit')[0].click(),有驚喜哦


面向百度編程

公眾號

weixinQRcode.png

往期文章

個人主頁


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM