与Options API 的区别
//Options API 写法
export default {
components: {},
data() {},
computed: {},
watch: {},
mouted() {}
}
Options API 官方定义好写法,规定在哪写就在哪写。随着功能增加,代码会更复杂
Composition API 将同一功能逻辑组织在一个函数内部,利于维护,通过setup选项来组织代码
export default {
setup(props,context) {}
}
setup
是组件内使用Composition API的入口
是一个接收props和context的函数,其返回的所有内容都暴露给组件的其余部分
注意事项:
- 避免使用
this - 调用发生在
data、coumputed、methods被解析之前
接收参数:
props:当传入新的prop时,将被更新;
- props是响应式的,当不能使用ES6解构,会消除prop响应性
- 解构prop,可以在setup函数里使用**
toRefs**函数完成
import { toRef } from 'vue'
setup(props) {
const title = toRef(props, 'title')
}
context :普通的js对象,暴露了其他可能在setup中有用的值
不是响应式,可以使用ES6解构
访问的property
执行setup时,组件实例尚未被创建。
仅可访问 props,attrs,slots,emit
结合模板使用
<!-- MyBook.vue -->
<template>
<div>{{ collectionName }}: {{ readersNumber }} {{ book.title }}</div>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
props: {
collectionName: String
},
setup(props) {
const readersNumber = ref(0)
const book = reactive({ title: 'Vue 3 Guide' })
// 暴露给 template
return {
readersNumber,
book
}
}
}
</script>
使用渲染函数
可以返回一个渲染函数,直接使用在同一作用域中声明的响应状态
import { h, ref, reactive } from 'vue'
export default {
setup() {
const readersNumber = ref(0)
const book = reactive({ title: 'Vue 3 Guide' })
// 请注意这里我们需要显式使用 ref 的 value
return () => h('div', [readersNumber.value, book.title])
}
}
ref
可以通过一个新的ref函数使任何响应式变量在任何地方起作用
ref接收参数并将其包裹在一个带有valueproperty的对象中返回,任何可以使用该property访问或更改响应式变量的值
import { ref } from 'vue'
const counter = ref(0)
console.log(counter) // { value: 0 }
console.log(counter.value) // 0
counter.value++
console.log(counter.value) // 1
ref 为值创建了一个响应式引用。
reactive
将对象包装成 响应式对象——通过Proxy代理后的对象,参数必须是对象
当ref对象被作为属性,传入响应式对象reactive 时,会自动获取其内部值
const count = ref(0)
const state = reactive({
count
})
console.log(state.count) // 0
//reactive 属性绑定新的ref对象后,原ref值不变
结合以上知识例子:
<template>
<div>我的名字:{{name}}</div>
<div>今天的天气:{{today.weather}}</div>
<button @click="changWeather">变化天气</button>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
const name = ref('kiya')
const today = reactive({
weather: 'sun'
})
const changWeather = () =>{
today.weather = 'rain'
}
return {
name, today
}
}
</script>
// 结果:
// 我的名字:kiya
// 今天的天气:sun
// 点击‘变化天气’
// 今天的天气:rain
vue 3.2 setup语法糖
在<stript>标签里加上setup 关键字就可以。
// 重写以上例子
<template>
<div>我的名字:{{name}}</div>
<div>今天的天气:{{today.weather}}</div>
<button @click="changWeather">变化天气</button>
</template>
<script setup>
import { ref, reactive } from 'vue'
const name = ref('kiya')
const today = reactive({
weather: 'sun'
})
const changWeather = () =>{
today.weather = 'rain'
}
return {
name, today
}
</script>
watch 监听
特点:
- 无法监听未被绑定的属性
- 可以直接监听
ref和ractive绑定对象
接收3个参数:
- 想要监听的 响应式引用或 getter函数
- 一个回调
- 可选配置选项
import { ref, watch } from 'vue'
const counter = ref(0)
watch(counter, (newValue,oldValue) => {
console.log('new counter is' + counter.value)
})
watchEffect
特点:
- 自动收集数据源作为依赖
- 无法访问监听状态前后的值
- 默认会执行一次,属性改变也会执行
const state = reactive({ count:0, name: 'kk'})
setTimeout(() => {
state.count ++
state.name = 'oo'
})
watchEffect(() => {
console.log(state.count)
console.log(state.name)
})
/* 初次打印: 0 kk
1秒后打印: 1 oo
*/
computed
- 接收一个getter函数,并根据 getter 的返回值返回一个不可变的响应式
ref对象。 - 接收具有
get和set函数对象,用来创建可以写的ref对象
import { computed } from 'vue'
//1 getter
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
//2 get set
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val -1
}
})
生命周期函数
只能同步的使用在setup函数里面。
vue3 相比 vue2 减少了beforeCreate 和 Created,因为setup是为了这两个生命周期钩子运行的。
生命周期对比
| Options API | setup |
|---|---|
beforeCreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
这些函数接收一个回调函数,钩子被调用时会被执行。
子父级传值——define
注意:
define类api必须在setup中外层使用,无法放入方法中
和TS兼容不太好
defineProps
定义props相关信息
// 基础写法
defineProps({
tags:Array
})
// TS 类型声明
const props = defineProps<{
tags:Array
}>()
两种写法不能一起使用。
defineEmits
定义emits相关信息
//基础用法
const emit = defineEmits(['change', 'delete'])
emits('change')
// TS声明类型
const emit = defineEmits<{
(e:'change', id:number):void
(e:'update', value:string):void
}>()
emits('change',1)
defineExpose
抛出方法
const getData = () => {
emit('getData','给父组件的值')
//触发父组件的方法
}
const setData = (val) => {
fatherData.value = val
//父组件调用
}
defineExpose({
getData,
setData
})
父组件调用子组件,需要子组件先定义好方法,通过defineExpose暴露出去。