当前位置:网站首页>组合式API-composition-api
组合式API-composition-api
2022-06-23 03:55:00 【tianruine】
setup()
基本使用
原理就是之前我们写的options API写成了API-composition-api
首先我们创建一个vue后缀的文件名,然后里面的内容是这样
注意:在setup()不能访问this
<script>
import { ref } from 'vue' //从vue里面把组合Api解构出来
export default {
data() { //这还是之前的optioons API
return {
title: 'hello'
}
},
setup() { //在这个函数里面的使用就是组合API
const counter = ref(0)
// 不能访问 this
// console.log(this.title)
return {
counter
}
},
mounted() {
console.log(this.counter)
}
}
</script>
<template>
<h1>{
{counter}}</h1>
</template>
<style>
</style>访问props
注意:在组合API ref或者reactive等等API的时候是具有响应式特点的,但是要是通过props从父组件中把这些具有响应是的数据传递给子元素,直接使用props.obj,这样的数据数据有响应式的,是指传递过来一个对象,这个对象有响应式,但是要是通过props传递过来的是一个值就没有响应式了,在子元素使用的时候是没有响应式特点的,要是想要让他具有响应式特点,可以通过toRef,或者toRefs进行传递
例子:在父元素
<script>
import { onMounted, reactive, ref, watchEffect,toRef } from 'vue'
import Child from './Child.vue'
export default {
setup() {
const title = ref('hello')
const obj = reactive({
x: 100,
y: 200
})
onMounted(() => {
setTimeout(() => { //计时器改变,看看子元素是否具有响应式
title.value = 'world'
obj.x = 1000
obj.y = 2000
}, 2000)
})
return {
title,
obj
}
},
components: {
Child
}
}
</script>
<template>
<Child :title="title" :obj="obj"></Child> //在这里通过自定义属性把父元素的值传递给子元素
</template>在子组件中
<script>
import { toRef, toRefs } from 'vue'
export default {
props: ['title', 'obj'], //在这里接收父组件传递过来的值
setup(props) {
const {obj} = props //在这里直接2解构props里面传递过来的对象是具有响应式的
// const{title}=props//是里面的值就没有响应式
//const obj=props.obj 传递过来的是一个对象就具有响应式了
const x = toRef(props.obj, 'x')//之前写成const x = props.obj.x是没有响应式的,需要toRef来让他具有响应式
const title = toRef(props, 'title')// const title = props.title没有响应式
const { title: title2, obj: { value } } = toRefs(props)
const y = toRef(value, 'y')//通过toRefs可以直接把props里面的值都让他具有响应式,但是对象也用的时候需要对里面的值在进行toRef或者toRefs
return {
title,
title2,
x,
y,
obj
}
}
}
</script>
<template>
<h1>{
{title}}</h1>
<h1>{
{title2}}</h1>
<h1>{
{x}}</h1>
<h1>{
{y}}</h1>
{
{obj}}
</template>setup的上下文
1、attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 this.$attrs。
父子组件通信过程中,父组件把数据传递过来,如果子组件没有用props进行接收,就会出现在attrs中,而vm中没有
例如:在父组件传递过来的

在child组件中并没有用props接收,在setup里console.log(attrs);就是
![]()
注意一点,在属性前面加冒号与不加冒号的区别是,加冒号传递过来的是父组件里面的变量,不加冒号就是字符串obj,字符串title,这也就是父子通信,自定义属性加冒号的原因,不加冒号传递的是属性的字符串值
2、emit: 分发自定义事件的函数, 相当于 this.$emit。
在父元素中

在子组件中触发事件并且可以传值过去

3、slots: 收到的插槽内容, 相当于 this.$slots
4.expose() 通过ref后代想要暴露给什么
例如,在父元素绑定子元素的ref

在子元素 setup函数中

那么在父元素去ref的时候只能拿到这个{x:100}

![]()
与渲染函数一起用
import { h } from 'vue'
export default {
setup() {
return () => h('div', {class: 'abc'}, h('a', {href: 'http://www.baidu.com'}, '百度'))
} //h函数第一个参数是根节点,第二个参数是属性,第三个参数是子节点
}
</script>
<template>
</template>页面结构

组合API
import { ref, onMounted, reactive, computed, readonly, watchEffect, watch } from 'vue'
ref 让属性具有响应式
一般里面写的都是基本数据类型
例子:
setup() {
const counter = ref({
x: 100,
y: {
a: 300
}
})
onMounted(() => {
setTimeout(() => {
counter.value.x = 10000 //这里注意在setup函数里面用的时候必须.value
counter.value.y.a = 30000
}, 3000)
})
return {
counter //外面用的话必须return出去
}
}
reactive
同样也是为了让数据具有响应式,一般写的都是复杂数据类型,
const count = ref(0) const obj = reactive({ count }) obj.count++ console.log(obj.count) count.value = 100 console.log(obj.count) obj.count = 200 console.log(count.value) const books = reactive([ref('JavaScript学习指南')]) books[0].value = 'html学习指南' console.log(books[0].value) const map = reactive(new Map([['count', ref(0)]])) console.log(map.get('count').value) map.set('count.value', 300) console.log(map.get('count').value)
computed() 计算属性
const count = ref(0)
const addOne = computed(() => count.value + 1) //里面写一个回调,当里面的值改变的时候就会触发
console.log(addOne.value)
count.value++
console.log(addOne.value)readonly()只读属性
const original = reactive({ count: 0 })
const copy = readonly(original)
original.count = 100 //但是赋值的变了,这个只读的也会变成100
// copy.count = 200 //因为是只读的所以不可以改
console.log(copy.count) //100watchEffect()
有个特性,与mobx里面的autorun一样,在最开始就会执行
const count = ref(0)
const title = ref('line1')
const stop = watchEffect(() => console.log(count.value + title.value)) // 总是要执行一次
stop()
count.value = 100
count.value = 100 //因为两次改变的值是一样的,所以就会执行一次
title.value = 'line2'
watch() 监听
const state = reactive({count: 0})
watch(
() => state.count, //变成了两个参数,第一个参数是函数,返回的是监听的值
(count, prevCount) => {
console.log(count)
console.log(prevCount)
}
)
state.count++watch与watcheffect区别:
- 执行时机:watchEffect是立即执行的,在页面加载时会主动执行一次,来收集依赖;而watch是惰性地执行副作用,它不会立即执行,但可以配置 immediate,使其主动触发
- 参数不同:watchEffect只需要传递一个回调函数,不需要传递侦听的数据,它会在页面加载时主动执行一次,来收集依赖;而watch至少要有两个参数(第三个参数是配置项),第一个参数是侦听的数据,第二个参数是回调函数
结果不同:watchEffect获取不到更改前的值;而watch可以同时获取更改前和更改后的值
类型判断
import { ref, isRef, readonly, computed, reactive, unref, toRef, toRefs, isProxy, isReactive, isReadonly } from 'vue'
isRef 判断是不是ref类型
注意通过computed处理的ref类型也是ref类型
const count = ref(0)
const count2 = 0
const count3 = readonly(count)
const count4 = computed(() => count.valut + 2)
const count5 = reactive({x: 0})
console.log(isRef(count)) //1
console.log(isRef(count2))//0
console.log(isRef(count3))//0
console.log(isRef(count4))//1
console.log(isRef(count5))//0unref() 不是ref类型的
unref(参数)
isReactive()
检查一个对象是否是由 reactive 或者 readonly 方法创建的代理。
const msg = readonly(ref(2))
const msg1 = reactive({a:2})
const msg2 = ref(2)
const msg3 = {}
console.log(isProxy(msg))//1
console.log(isProxy(msg1))//1
console.log(isProxy(msg2))//0
console.log(isProxy(msg3))//0isReadonly() 判断是不是readonly类型
const msg = readonly(reactive({}))
const msg2 = ref(0)
console.log(isReadonly(msg))//1
console.log(isReadonly(msg2))//0在setup函数的生命周期
- `beforeCreate` -> 使用 `setup()`
- `created` -> 使用 `setup()`
- `beforeMount` -> `onBeforeMount`
- `mounted` -> `onMounted`
- `beforeUpdate` -> `onBeforeUpdate`
- `updated` -> `onUpdated`
- `beforeDestroy` -> `onBeforeUnmount`
- `destroyed` -> `onUnmounted`
在setup函数中的provide与inject
在上层组件中
export default {
components: {
Child
},
setup() {
const title = ref('hello') //通过这种方式传递是具有响应式的
provide('title',title) //第一个是变量名,第二个是传的参数,要是传多个的时候title可以传递一个对象,到时候再取值,要是想传递多个变量就需要定义多个provide了
}
}}在下层组件inject接收的时候
export default {
setup() {
//const title = inject('title', 'hello') r如果provide没有传值的时候第二个参数是默认值
const title = inject('title') 通过inject拿到在provide定义的'title'变量
return {
title
}
}
}setup函数的语法糖
只需要在<script setup></script>标签写上setup就可以了
例子1:
<script setup>
import { ref, provide } from 'vue'
import Child from './Child.vue'
//之前是下面这种写法,加上标签之后就没注释的写法,不用return出数据,不用components写子组件了
// export default {
// components: {
// Child
// },
// setup() { //
// const title = ref('hello')
// // provide('title')
// }
// }
const title = ref('hello')
provide('title', title)
</script>
<template>
<Child></Child>
</template>
<style>
</style>当有参数,例如props的写法
<script>
import { toRef, toRefs } from 'vue'
export default {
props: ['title', 'obj'],
setup(props){
const obj=props.obj
console.log(props)
const {title:title4}=props
const x = toRef(props.obj, 'x')
return {
x,
obj,
title4
// }
}
}
}
</script>
<template>
<h1>{
{x}}</h1>
{
{obj.x}}
{
{title4}}
</template>用语法糖的写法,不需要return,不需要export default,但是注意接收参数的写法props,用到defineProps(),可以写一个数组也可以写一个对象
<script setup>
import { toRef, toRefs } from 'vue'
// props: ['title', 'obj'],
const props = defineProps(['title', 'obj'])
//const obj = props
const obj=props.obj
console.log(props)
const {title:title4}=props
const x = toRef(props.obj, 'x')
// return {
// //title,
// // title2,
// x,
// obj,
// title4
// }
</script>
<template>
<h1>{
{x}}</h1>
{
{obj.x}}
{
{title4}}
</template>context中的参数的时候
defineProps 和 defineEmits
在 <script setup> 中必须使用 defineProps 和 defineEmits API 来声明 props 和 emits ,它们具备完整的类型推断并且在 <script setup> 中是直接可用的:
emit用defineEmits
<script setup>
const props = defineProps({
foo: String
})
const emit = defineEmits(['change', 'delete'])
// setup code
</script>defineProps和defineEmits都是只在<script setup>中才能使用的编译器宏。他们不需要导入且会随着<script setup>处理过程一同被编译掉。defineProps和defineEmits在选项传入后,会提供恰当的类型推断。传入到
defineProps和defineEmits的选项会从 setup 中提升到模块的范围。因此,传入的选项不能引用在 setup 范围中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块范围内。
使用 <script setup> 的组件是默认关闭的,也即通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定。
defineExpose
为了在 <script setup> 组件中明确要暴露出去的属性,使用 defineExpose 编译器宏:
expose()的写法
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
defineExpose({
a,
b
})
</script>
useSlots 和 useAttrs
在 <script setup> 使用 slots 和 attrs 的情况应该是很罕见的,因为可以在模板中通过 $slots 和 $attrs 来访问它们。在你的确需要使用它们的罕见场景中,可以分别用 useSlots 和 useAttrs 两个辅助函数:
<script setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>useSlots 和 useAttrs 是真实的运行时函数,它会返回与 setupContext.slots 和 setupContext.attrs 等价的值,同样也能在普通的组合式 API 中使用
边栏推荐
- Arduino火焰传感器(含代码)
- Raspberry pie network remote access
- Arduino温湿度传感器DHT11(含代码)
- 微信小程序:老年祝福短视频
- Event日志关键字:EventLogTags.logtags
- 当SBAS遇上rtklib
- Baidu PaddlePaddle's "universal gravitation" first stop in 2022 landed in Suzhou, comprehensively launching the SME empowerment plan
- MVC three-tier architecture
- Web application security testing guide
- 树莓派网络远程访问
猜你喜欢

PRCS-1016 : Failed to resolve Single Client Access Name

Visual display of TEQC quality analysis results using teqcplot

C'est dur de trouver un emploi? Ali des trois côtés, heureusement qu'il s'est bien préparé et qu'il a pris un produit.

618 how to break through the siege? Haier Zhijia: do a good job in digitalization of users

Sift特征点提取

使用teqcplot对teqc 质量分析结果进行可视化展示

Raspberry pie network remote access

BGP experiment

Beyond chips and AI, why is hard technology capital becoming more and more "hard core"?

MVC三層架構
随机推荐
985测试工程师被吊打,学历和经验到底谁更重要?
vmware网络连接出错Unit network.service not found
PHP move_ uploaded_ File failed to upload mobile pictures
【Leetcode】最长递增子序列问题及应用
How can functional testers spend one month to become advanced automation software test engineers
Post processing of multisensor data fusion using Px4 ECL
Web 应用程序安全测试指南
新晋职场人的 技术进击?之旅
Event日志关键字:EventLogTags.logtags
Hcip switch experiment
如何进行探索性数据分析
Difficult to find a job in a bad environment? Ali on three sides. Fortunately, he has made full preparations and has offered
OSPF分流实验
STP summary
Penetration test basis | attached test points and test scenarios
BGP summary of hcip operation
8 years' experience: monthly salary of 3000 to 30000, the change of Test Engineer
C'est dur de trouver un emploi? Ali des trois côtés, heureusement qu'il s'est bien préparé et qu'il a pris un produit.
Cookie session explanation
MySQl基础