【若依】18、Vue3和Vue2的差异
Vue3 中可以原封不动的使用 Vue2 中的方法(Options API)。 但是 Vue3 中提供了一些语法糖。
变量定义
例如 Vue2 中,我们定义变量,可以按照如下方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<h1>Hello Vue3</h1>
<div></div>
</div>
</template>
<script>
export default {
name: "Test01",
data() {
return {
msg: "hello yueyazhui"
}
}
}
</script>
<style lang='scss' scoped>
</style>
以上代码,在 Vue3 中,可以按照如下方式来写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<div>
<h1>Hello Vue3</h1>
<div></div>
<input type="text" v-model="msg">
</div>
</template>
<script>
import {ref} from 'vue'
export default {
name: "Test02",
/**
* Vue2 中定义的各种变量、方法、生命周期钩子函数等等,现在统一都在 setup 中进行定义
*
* 所有定义的变量、方法等,都需要返回之后才可以使用
*/
setup() {
// 直接这样写,这个变量不是响应式数据
// let msg = "hello yueyazhui"
let msg = ref("hello yueyazhui")
return {msg}
}
}
</script>
<style lang='scss' scoped>
</style>
两个要点:
- 变量定义,需要用到 ref 函数,该函数,直接从 vue 中导入,否则直接定义的变量不具备响应式的特性。
- 所有定义的变量、方法等,都需要 return,不 return,用不了。
方法定义
在 Vue2 中,我们一般是将方法定义在 methods 节点中,但是在 Vue3 中,我们将方法定义在 setup 方法中,尤其要注意,方法定义完成之后,必须要返回方法名,否则方法用不了。 ```vue
Hello Vue3
<button @click="handleLogin('yue', '123')">登录</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
如上,像定义一个变量一样去定义方法,方法定义完成之后,一定要返回。
### 钩子函数
在 Vue2 中,定义钩子函数,直接定义对应的方法名即可:
```vue
<template>
<div>
<h1>Hello Vue3</h1>
<div></div>
</div>
</template>
<script>
export default {
name: "Test01",
data() {
return {
msg: "hello yueyazhui"
}
},
mounted() {
console.log('---Vue2 mounted()---')
}
}
</script>
<style lang='scss' scoped>
</style>
但是,在 Vue3 中,由于所有的东西都是在 setup 中定义的,包括钩子函数。 Vue3 中定义钩子函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<template>
<div>
<h1>Hello Vue3</h1>
<div></div>
<input type="text" v-model="msg">
<div><button @click="handleLogin('yue', '123')">登录</button></div>
</div>
</template>
<script>
import {ref, onMounted} from 'vue'
export default {
name: "Test02",
/**
* Vue2 中定义的各种变量、方法、生命周期钩子函数等等,现在统一都在 setup 中进行定义
*
* 所有定义的变量、方法等,都需要返回之后才可以使用
*/
setup() {
// 直接这样写,这个变量不是响应式数据
// let msg = "hello yueyazhui"
let msg = ref("hello yueyazhui")
const handleLogin = (username, password) => {
console.log('username', username)
console.log('password', password)
}
// 调用钩子函数,并传入回调函数
// 注意:钩子函数不需要返回
onMounted(() => {
console.log('---Vue3 onMounted()---')
})
return {msg, handleLogin}
}
}
</script>
<style lang='scss' scoped>
</style>
- 首先从 vue 中导入钩子函数。
- 在 setup 方法中去定义钩子函数的逻辑。
- 在 return 中,不需要返回钩子函数。
钩子函数对照:
Vue2 | Vue3 |
---|---|
beforeCreate | onBeforeCreate |
created | onCreated |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | OnUpdated |
beforeUnmount | OnBeforeUnmount |
unmounted | OnUnmounted |
activated | OnActivated |
deactivated | OnDeactivated |
errorCapture | OnErrorCapture |
renderTracked | OnRenderTracked |
renderTriggered | OnRenderTriggered |
computed 属性
计算属性和钩子函数比较类似,计算属性使用步骤:
- 从 vue 中导入计算属性函数。
- 定义计算属性。
- 在 return 中返回计算属性值。 ```vue
Hello Vue3
<button @click="handleLogin('yue', '123')">登录</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
计算属性更新的例子:
```vue
<template>
<div>
<h1>Hello Vue3</h1>
<div></div>
<input type="text" v-model="msg">
<div><button @click="handleLogin('yue', '123')">登录</button></div>
<div></div>
</div>
</template>
<script>
import {ref, onMounted, computed} from 'vue'
export default {
name: "Test02",
/**
* Vue2 中定义的各种变量、方法、生命周期钩子函数等等,现在统一都在 setup 中进行定义
*
* 所有定义的变量、方法等,都需要返回之后才可以使用
*/
setup() {
// 直接这样写,这个变量不是响应式数据
// let msg = "hello yueyazhui"
let msg = ref("hello yueyazhui")
let num = ref(99)
const handleLogin = (username, password) => {
console.log('username', username)
console.log('password', password)
num.value++
}
// 调用钩子函数,并传入回调函数
// 注意:钩子函数不需要返回
onMounted(() => {
console.log('---Vue3 onMounted()---')
})
// 通过计算属性去定义一个变量
// 注意:计算属性需要返回
const currentTime = computed(() => {
num.value
return Date.now()
})
return {msg, handleLogin, currentTime, num}
}
}
</script>
<style lang='scss' scoped>
</style>
由于生成计算属性 currentTime 依赖 num 变量,所以当 num 变量发生变化的时候,计算属性会自动更新,否则计算属性将一直使用缓存中的数据(num 没有发生变化的情况)。 另外还有一点,就是定义的变量入 num、msg 等 ,在 HTML 节点中,直接使用 num、msg,但是如果是在方法中操作这些变量,则一定要使用 num.value 或者 msg.value 去操作这些变量。
watch 函数
Vue3 中,watch 函数的写法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<template>
<div>
<h1>Hello Vue3</h1>
<div></div>
<input type="text" v-model="msg">
<div><button @click="handleLogin('yue', '123')">登录</button></div>
<div></div>
</div>
</template>
<script>
import {ref, onMounted, computed, watch} from 'vue'
export default {
name: "Test02",
/**
* Vue2 中定义的各种变量、方法、生命周期钩子函数等等,现在统一都在 setup 中进行定义
*
* 所有定义的变量、方法等,都需要返回之后才可以使用
*/
setup() {
// 直接这样写,这个变量不是响应式数据
// let msg = "hello yueyazhui"
let msg = ref("hello yueyazhui")
let num = ref(99)
const handleLogin = (username, password) => {
console.log('username', username)
console.log('password', password)
num.value++
}
// 调用钩子函数,并传入回调函数
// 注意:钩子函数不需要返回
onMounted(() => {
console.log('---Vue3 onMounted()---')
})
// 通过计算属性去定义一个变量
// 注意:计算属性需要返回
const currentTime = computed(() => {
num.value
return Date.now()
})
watch(num, (newValue, oldValue) => {
console.log('newValue', newValue)
console.log('oldValue', oldValue)
})
return {msg, handleLogin, currentTime, num}
}
}
</script>
<style lang='scss' scoped>
</style>
- 先从 vue 中导入 watch 函数。
- 在 setup 中去监控变量,第一个参数是要监控的变量,第二个参数则是一个回调函数,回调函数的参数就是所监控变量值的变化。
ref 和 reactive
```vue
Hello Vue3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
一般来说,我们通过 ref 来定义一个变量,一般都是原始数据类型,例如 String、Number、BigInt、Boolean 等,通过 reactive 来定义一个对象。
如上面的案例所示,定义了 book 对象之后,接下来的访问中,通过 book.xxx 就可以访问到 book 中的属性值了。
但是,假设我们在定义的时候,定义的是 book 对象,但是我们访问的时候,却希望能够直接按照属性来访问,此时可以直接展开变量,但是,如果直接通过三个点去展开变量,会导致变量的响应式特点失效,此时,我们可以通过 toRefs 函数,让变量恢复响应式的特点:
```vue
<template>
<div>
<h1>Hello Vue3</h1>
<div></div>
<!-- <div></div>
<div></div> -->
<div></div>
<div></div>
<div><button @click="updateBookInfo">更改图书信息</button></div>
</div>
</template>
<script>
import {ref, reactive, toRefs} from 'vue'
export default {
name: "Test03",
setup() {
let num = ref(99)
let book = reactive({
name: '燕倾天下',
author: '天下归元'
})
const updateBookInfo = () => {
book.name = '扶摇'
}
return {num, ...toRefs(book), updateBookInfo}
}
}
</script>
<style lang='scss' scoped>
</style>
总结:
- ref 定义原始数据类型;reactive 定义对象。
- 如果用到了对象展开,那么需要用到 toRefs 函数将对象中的属性变为响应式。
- 在 vue3 中,定义的变量、函数等等,在使用的时候,都不需要 this。
setup
- 写的时候,容易忘记返回变量或者方法等等。
- 写法有点臃肿。 ```vue
Hello Vue3
<button @click="updateBookInfo">更改图书信息</button>
``` 现在,就直接在 script 节点中,增加 setup 属性,然后 script 节点中定义的变量名、方法名等等,默认就会自动返回,我们只需要定义即可。
本文由作者按照
CC BY 4.0
进行授权