Vue3對比Vue2,有哪些不同?


vue2的響應式是通過object.defineproperty實現的,JavaScript對象傳入vue實例時,vue會遍歷對象的所有property,並通過object.defineproperty把這些property轉化為getter和setter,數據發生變化時,就會觸發視圖的更新;不過這種方式有點缺陷,就是不能監測到對象屬性的添加和刪除,因此需要用vue.set()來添加和刪除。並且也不能監聽數組的變化;

而vue3則很好的解決了這個問題,Vue3 利用 Proxy(代理) 實現數據讀取和設置攔截,在攔截 trap 中實現數據依賴收集和觸發視圖更新的操作。

vue2和vue3在寫法上有什么變化?
90%的寫法完全一致,只是部分發生了改變:
1、Vue 3 的 Template 支持多個根標簽,Vue 2 不支持
2、Vue 3 有 createApp(),而 Vue 2 的是 new Vue()
createApp(組件),new Vue({template, render})
3、v-model代替以前的v-model和.sync
vue3中v-model的用法要求:props屬性名任意,這里假設為 x,那么事件名必須為“update:x”

> <Switch :value="y" @update:value="y=$event"/>
> vue2中的寫法:<<Switch:value.sync=“y”/>>
> vue3中的寫法:<<Switch v=model:value="y">>

4、context.emit
新增context.emit,與this.$emit(vue3中只能在方法里使用)作用相同

context.emit的用法

setup(props, context) {
const toggle = () => {
context.emit('update:value', !props.value)
}
return {
toggle
}


5. Vue3中的屬性綁定

默認所有屬性都綁定到根元素
使用inheritAttrs: false可以取消默認綁定
使用attrs或者context.attrs獲取所有屬性
使用v-bing="$attrs"批量綁定屬性
使用 const {size, level, …rest} = context.attrs 將屬性分開
使用場景
在vue2中我們在父組件綁定click事件,子組件必須內部觸發click,而vue3中在父組件綁定子組件的根元素上也會跟着綁定

ButtonDemo.vue

<div>
<Button @click="onClick" @focus="onClick" size="small">你好</Button>
</div>
setup() {
const onClick = () => {
console.log("aaa")
}
return {onClick}
},

  


Button.vue

<template>
<div>
<button>
<slot/>
</button>
</div>
</template>

 

上面的代碼Button的click事件會默認傳給最外層元素div上綁定,怎么取消這個默認綁定呢?我們就需要使用inheritAttrs:false,使用v-bind=”$attrs”可以把內層的事件綁定到外層想綁定的元素上

Button.vue

<template>
<div>
<button v-bind="$attrs">
<slot/>
</button>
</div>
</template>
<script lang="ts">
export default {
inheritAttrs: false
}
</script>

 

如果想要一部分屬性綁定在button上一部分在div上就需要在setup里設置

Button.vue

<template>
<div :size="size">
<button v-bind="rest">
<slot/>
</button>
</div>
</template>
<script lang="ts">
import {SetupContext} from 'vue'
export default {
inheritAttrs: false,
setup(props: any, context:SetupContext ) {
const {size, ...rest} = context.attrs
return {size, rest}
}
}
</script>

  

props和attrs的區別

props要先聲明才能取值,attrs不用先聲明
props不包含事件,attrs包含
props沒有聲明的屬性,會跑到attrs里
props支持string以外類型,attrs只有string類型

export default{
inheritAttrs:false,
setup(props:any,context:SetupContext){
console.log({...props}) **==>>{}**
const {size,...rest} = context.attrs
return {size,rest}

export default{
inheritAttrs:false,
props:{
size:String
}
setup(props:any,context:SetupContext){
console.log({...props}) **==>>{size:small}**

 

第一張圖里因為沒有聲明props所以是空對象,第二個聲明了size,所以只得到了size

6.slot具名插槽的使用

vue2中的用法
子組件

<slot name="title">

  


父組件

<template slot="title">
<h1>哈哈哈</h1>
</template>

  



vue3中子組件用法不變,父組件需要使用v-slot:插槽名

父組件

<template v-slot:title>
<h1>哈哈哈</h1>
</template>

  

7. Teleport傳送門組件

<Teleport to="body">
需要傳送到body下面的內容
</Teleport>

  

8. vue3中動態掛載組件的方法
通過引入h函數第一個參數是組件,第二個是元素的屬性(第一個參數組件的props,也就是直接可以在使用組件的時候傳入的屬性),第三個是插槽的屬性。
其中我們在render里監聽我們v-model綁定的update事件的時候,需要使用onUpdate:屬性名

import {createApp, h} from 'vue'
import Dialog from './Dialog.vue'
export const openDialog = (options: Options) => {
const {title, content} = options
const div = document.createElement('div')
document.body.append(div)
const app = createApp({
render() {
return h(Dialog, {
visible: true, cancel: () => {},
'onUpdate:visible': (newValue: boolean) => {
if (newValue === false) {
app.unmount(div)
}
}
}, {title, content})
}
})
app.mount(div)
}

 

9. watchEffect用來代替生命周期里的onMounted和onUpdated

初始化頁面的時候watchEffect里的代碼會執行,當watchEffect里的數據有更新的時候同樣會執行

const count = ref(0)

watchEffect(() => console.log(count.value))
// -> logs 0

setTimeout(() => {
count.value++
// -> logs 1
}, 100)

  

注意watchEffect第一次運行是在組件掛載之前,如果需要訪問DOM需要將我們的watchEffect放在onMounted里

onMounted(() => {
watchEffect(() => console.log(count.value))
})


免責聲明!

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



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