Vue2 到 Vue3,重溫這 5 個常用的 API

距離Vue3發布已經過去一年多時間了,從Vue2到Vue3是一個不小的升級,包括周邊生態等。雖然目前大多數開發者們在使用的仍舊以Vue2為準,但Vue3顯然是Vue開發者們未來必須面對的,而且前不久Vue官方也發布了Vue2.7.0,使得Vue2可以兼容Vue3的API,這讓開發者可以在項目不升級Vue3的情況下依舊可以使用Vue3的開發方式,這為Vue2開發者學習Vue3提供了一個非常好的過渡途徑。

Vue3之於Vue2最大的變化,當屬composition API了,而除了引入composition API外,一些我們在Vue2上經常使用的東西到了Vue3時也發生了不小的變化,本文將介紹一些有Vue2到Vue3中幾個比較重要且常用的知識點,歡迎感興趣的同學閱讀。

文中程式碼示例使用setup語法糖 + ts

v-model

支援多個v-model

Vue3中,可以通過參數來達到一個組件支援多個v-model的能力。

// 父組件
<template>
  <child v-model="name" v-model:email="email" />
  <p>姓名:{{ name }}</p>
  <p>郵箱:{{ email }}</p>
</template>

<script lang="ts" setup>
import child from './child.vue'
import { ref } from 'vue'

const name = ref<string>('張三')
const email = ref<string>('[email protected]')
</script>
複製程式碼
// 子組件
<template>
  <button @click="updateName">更新name</button>
  <button @click="updateEmail">更新email</button>
</template>

<script lang="ts" setup>
// 定義emit
const emits = defineEmits<{
  (e: 'update:modelValue', value: string): void
  (e: 'update:email', value: string): void
}>()

const updateName = () => {
  emits('update:modelValue', '李四')
}

const updateEmail = () => {
  emits('update:email', '[email protected]')
}
</script>

如果v-model沒有使用參數,則其默認值為modelValue,如上面的第一個v-model,注意此時不再是像Vue2那樣使用$emit('input')了,而是統一使用update:xxx的方式。

廢棄.sync

在Vue2中,由於一個組件只支援一個v-model,當我們還有另外的值也想要實現雙向綁定更新時,往往用.sync修飾符來實現,而在Vue3中該修飾符已被廢棄,因為v-model可以支援多個,所以.sync也就沒有存在的必要了。

watch

不同數據類型的監聽

基礎數據類型的監聽:

const name = ref<string>('張三')
watch(name, (newValue, oldValue) => {
  console.log('watch===', newValue, oldValue)
})
複製程式碼

複雜數據類型的監聽:

interface UserInfo {
  name: string
  age: number
}

const userInfo = reactive<UserInfo>({
  name: '張三',
  age: 10
})
// 監聽整個對象
watch(userInfo, (newValue, oldValue) => {
  console.log('watch userInfo', newValue, oldValue)
})

// 監聽某個屬性
watch(() => userInfo.name,  (newValue, oldValue) => {
  console.log('watch name', newValue, oldValue)
})

支援監聽多個源

Vue3里,watch多了一個特性,可以傳入一個數組同時偵聽多個數據,這比起Vue2確實優雅多了,以往在Vue2中為了實現同時監聽多個數據,往往需要藉助computed,現在在Vue3里我們可以少一些不必要的程式碼了。

const name = ref<string>('張三')
const userInfo = reactive({
  age: 18
})

// 同時監聽name和userInfo的age屬性
watch([name, () => userInfo.age], ([newName, newAge], [oldName, oldAge]) => {
  // 
})

watchEffect

watchEffect與watch的區別

相比Vue2Vue3watchEffect這個API,watchEffect傳入一個函數參數,該函數會立即執行,同時會響應式的最終函數內的依賴變數,並在依賴發生改變時重新運行改函數。

const name = ref<string>('張三')
const age = ref<number>(18)

watchEffect(() => {
  console.log(`${name.value}:${age.value}`) // 張三:18
})

setTimeout(() => {
  name.value = '李四' // 李四:18
}, 3000)

setTimeout(() => {
  age.value = 20 // 李四:20
}, 5000)

和watch的區別:

  • 運行時機不同,watchEffect會立即執行,相當於設置了immediate: truewatch
  • watchEffect無法獲取改變前後的值。
  • watch顯示的指定依賴源不同,watchEffect會自動收集依賴源。

watchEffect還是watch

建議在大部分時間裡使用watch,避免一些不必要的重複觸發。

$attrs

Vue3中,$attrs包含父組件中除props和自定義事件所有屬性集合

不同於Vue2$attrs包含了父組件的事件,因此$listenners則被移除了。

// 父組件
<template>
  <child id="root" class="test" name="張三" @confirm="getData" />
</template>

<script lang="ts" setup>
const getData = () => {
  console.log('log')
}
</script>

// 子組件
<template>
  <div>
    <span>hello:{{ props.name }}</span>
  </div>
</template>

<script lang="ts">
export default {
  inheritAttrs: false
}
</script>

<script lang="ts" setup>
const props = defineProps(['name'])

const attrs = useAttrs()
console.log('attrs', attrs)
</script>

 

 

 

使用v-bind即可實現組件屬性及事件透傳:

// 父組件
<template>
  <child closeable @close="onClose" />
</template>

<script lang="ts" setup>
const onClose = () => {
  console.log('close')
}
</script>

// 子組件
<template>
  <div>
    <el-tag v-bind="attrs">標籤</el-tag>
  </div>
</template>

使用ref訪問子組件

Vue2中,使用ref即可訪問子組件里的任意數據及方法,但在Vue3中則必須使用defineExpose暴露子組件內的方法或屬性才能被父組件所調用。

// 父組件
<template>
  <child ref="childRef" />
</template>

<script lang="ts" setup>
import { ref, onMounted } from 'vue'

const childRef = ref()

onMounted(() => {
  childRef.value.getData()
})
</script>

// 子組件
<script lang="ts" setup>
import { defineExpose } from 'vue'

const getData = () => {
  console.log('getData')
}
const name = ref('張三')

defineExpose({
  getData,
  name
})
</script>

感謝

本次分享就到此結束了,感謝您的閱讀!!!如有什麼不到位的地方還望大佬不吝賜教!!!江湖最高禮儀

Tags: