创建项目
需要 Node.js 16.0 或更高版本,执行指令
这一指令将会安装并执行 create-vue
setup
执行周期
执行时机比 beforeCreate()
还要早,所以也无法使用 this
1
2
3
4
5
6
7
8
9
10
| <script>
export default{
setup(){
console.log('setip', this)
},
beforeCreate(){
console.log('beforeCreate')
}
}
</script>
|
执行后,先打印 setup undefined
然后才是 beforeCreate
数据调用
如果想要在 template
中使用 setup()
函数里定义的数据或函数,必须要 return
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| <script>
export default{
setup(){
// data
const msg = 'hello vue3'
// function
const logMsg = () => {
console.log(msg)
}
// return
return{
msg,
logMsg
}
}
}
</script>
|
只有 return
之后,才可以在 template
里使用
1
2
3
4
| <template>
<div>{{ msg }}</div>
<button @click="logMsg">button</button>
</template>
|
语法糖
每次都要返回属实麻烦,实际上可以直接通过在 script
标签加上 setup
这样就可以自动返回,上述就可以改为
1
2
3
4
5
6
| <script setup>
const msg = 'hello vue3'
const logMsg = () => {
console.log(msg)
}
</script>
|
当然,实际上还是会 return
的,只是不用写出来了
响应式数据
reactive
reactive()
函数接收一个对象类型的数据,返回一个响应式的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <script setup>
import {reactive} from 'vue'
const state = reactive({
count: 100
})
const addCount = () => {
state.count++
}
</script>
<template>
<div>
<div>{{ state.count }}</div>
<button @click="addCount">+1</button>
</div>
</template>
|
ref
ref()
接收简单类型或复杂类型,返回一个响应式对象。其本质是在原有传入数据的基础上,外层包了一个对象,包成了更复杂类型。其实也是再使用 reactive()
实现的响应式
所以,在 <script>
中访问数据,需要通过 .value
才行。而在 <template>
中访问数据直接用变量就行。上述例子用 ref()
重写如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| <script setup>
import {ref} from 'vue'
const c = ref(0)
const addC = () => {
c.value++
}
</script>
<template>
<div>
<div>{{ c }}</div>
<button @click="addC">+1</button>
</div>
</template>
|
实际开发只使用 ref()
会比较灵活统一
computed
计算属性 computed()
与 Vue2 类似,只是变成了可以任意调用的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| <script setup>
import { computed, ref} from 'vue'
const list = ref([1, 2, 3, 4, 5, 6, 7, 8])
const computedList = computed(() => {
return list.value.filter(item => item > 2)
})
</script>
<template>
<div>{{ list }}</div>
<div>{{ computedList }}</div>
</template>
|
这样创建出来的属性是只读的,不是可写的,若需要可写,需要显式声明 get()
与 set()
,以下摘自官方示例
1
2
3
4
5
6
7
8
9
10
11
12
| <script>
const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: (val) => {
count.value = val - 1
}
})
plusOne.value = 1
console.log(count.value) // 0
</script>
|
摘自:
https://cn.vuejs.org/api/reactivity-core.html#computed
watch
watch()
函数同样是侦听一个或多个数据的变化,数据变化时执行回调函数。不过多了两个额外参数 immediate
和 deep
1
2
3
| watch(count, (newValue, oldValue) => {
console.log('count changed', oldValue, newValue)
})
|
1
2
3
| watch([count, name], ([newCount, newName], [oldCount. oldName]) => {
console.log('count or name has changed', [newCount, newName], [oldCount. oldName])
})
|
示例,这里我用了简化的 pug,不过其实也很好懂啦
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
| <script setup>
import { ref, watch } from 'vue'
const count = ref(0)
const name = ref('John')
const addCount = () => count.value++
const changeName = () => name.value = 'Mike'
// 监视单个数据的变化
watch(count, (newValue, oldValue) =>{
console.log('count changed', oldValue, newValue)
})
// 监听多个数据的变化
watch([count, name], (newArr, oldArr) => {
console.log('count or name changed', oldArr, newArr)
})
</script>
<template lang="pug">
div count: {{ count }}
button(@click="addCount") +1
div name: {{ name }}
button(@click="changeName") change name
</template>
|
immediate
表示立即执行,即在进入页面后会立马执行一次,此时的 oldValue
是 undefined
1
2
3
4
5
| watch(count, (newValue, oldValue) =>{
console.log('count changed', oldValue, newValue)
}, {
immediate: true
})
|
deep
deep
是深度监视,因为默认 watch
进行浅层监视是无法监视到复杂类型的变化的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| <script setup>
import { ref, watch } from 'vue'
const userInfo = ref({
name: 'John',
age: 18
})
const changeUserInfo = () => {
userInfo.value.age++
}
watch(userInfo, (newValue) => {
console.log('userInfo changed', newValue)
}, {
deep: true
})
</script>
<template lang="pug">
div {{ userInfo }}
button(@click="changeUserInfo") change userInfo
</template>
|
复杂类型单个属性侦听
使用 deep
将会对复杂类型所有属性进行侦听,也就是只要任一属性发生变化,都会执行函数
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
| <script setup>
import { ref, watch } from 'vue'
const userInfo = ref({
name: 'John',
age: 18
})
const changeAge = () => {
userInfo.value.age++
}
const changeName = () => {
userInfo.value.name = 'Mike'
}
watch(() => userInfo.value.age, (newValue, oldValue) => {
console.log('age changed', oldValue, newValue)
})
</script>
<template lang="pug">
div {{ userInfo }}
button(@click="changeAge") change age
button(@click="changeName") change name
</template>
|
这样就只有 age
改变时候才会触发,且返回值是 age
的值
生命周期函数
Vue3 的生命周期对比
Option API | Composition API |
---|
beforeCreate/created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
和组合式 API 的不同就是变成了函数调用,且可以调用多次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| <script setup>
import { onMounted } from 'vue';
// 组合式的 beforeCreate 和 created 直接写
const getList = () => {
console.log('从后端获取数据')
}
// 执行,进入页面便请求
getList()
// 生命周期函数可以调用多次,会按顺序执行
onMounted(() => {
console.log('逻辑一')
})
onMounted(() => {
console.log('逻辑二')
})
</script>
|