前序
以前我们使用的data()、computed()等等,在Composition API中都不会再使用了,API可以替代
认识Mixin
我们的Compositio API就是替代Mixin
以前放在组件中的数据,我们都可以放在Mixin中
data/methods/computed等等
1.新建mixins文件夹,里面存放Mixin.js文件,书写代码
export const Mixin = {
data(){
return{
message:"Hello"
}
},
methods:{
foo(){
console.log('foo')
}
},
//生命周期函数
created(){
console.log('created')
}
}
2.App.vue
<template>
<div>
//引入mixins后,就可以使用里面的数据和方法
<h2>{{message}}</h2>
<button @click="foo"></button>
</div>
</template>
<script>
import {Mixin} from './Minix.js'
export default{
mixins:[Mixin],
data(){
return{
}
}
}
</script>
Mixin的合并规则
优先保存自身组件中的数据 但是:生命周期都会被调用
全局混入Mixin
main.js
const app = createApp(App)
app.mixin({
data(){
return{}
},
methods:{
}
});
Composition API
我们曾经使用的Options API的弊端
同一个逻辑写一块,而不是像Options API一样如此分散
Home.vue
<template>
<div>
</div>
</template>
<script>
export default{
//尽管setup有参数props,但是还需要写props
props:{
message:{
type:String,
required:true
}
},
//setup函数有哪些参数、有什么样的返回值
//setup中,不可以使用this
setup(props,context){
//props:父组件传递过来的属性
//因为不可以用this,所以用props拿数据
console.log(props)
context.attrs.id/class
context.slots
context.emit
-->1.attrs[所有非prop的属性、class]
-->2.slots[父组件传递过来的插槽]
-->3.emit[组件需要发出事件时,可以用到]
}
}
</script>
context的解构写法:
setup(props,{attrs,slots,emit}){
//此时使用的时候,就不用再使用context调用
console.log(attrs.id,attrs.class)
console.log(slots)
console.log(emit)
}
setup的使用
setup的返回值
<template>
{{title}}
</template>
<script>
export default{
props:{
message:{
type:String,
required:true
}
},
setup(props,{attrs,slots,emit}){
console.log(attrs.id,attrs.class)
console.log(slots)
console.log(emit)
//return后的数据,可以在template中使用
return{
title:"标题"
}
},
}
</script>
实际上这里就算点了方法,页面展示的count也不会变,因为在vue2中,我们使用data的时候,实际上使用reactive()进行了包裹,因此这里我们没有包裹就只能展示最初始的数据,没有响应式。
如何实现在Composition API中实现响应式功能? 我们需要学会儿Reactive API
Reactice API
{{state.count}}
setup(){
//绑定reactive()
//会数据劫持Proxy,然后调用Proxy.get(){},知道你取了counter的数据
const state = reactive({
counter:100
})
return{
state,
}
}
setup中的this问题
Ref API
//counter变成了一个ref的可响应式的引用
let counter = ref(100)
这个时候如果我添加方法,对counter进行改变,此时counter已经是响应式的了。
但是counter已经是对象了,所以在方法中使用counter的值的时候需要:counter.value++;但是在template模板中使用ref对象,会自动解包的,直接使用{{counter}}
<template>{{counter}}</template>
increate(){counter.value++}
注:我们ref的解包只能是一个浅层解包(info是一个js的对象,在他里面写上ref过的counter,是不能解包的)
<template>
{{info.counter.value}}
</template>
setup(){
let counter = ref(100);
const info = {
counter
}
}
但是如果最外层包裹的是一个reactive可响应对象,那么ref的数据是可以自动解包的(不推荐这样嵌套)
setup(){
let counter = ref(100);
const info = reactive({
counter
})
}
认识readonly
import {ref,reactive,readonly} from 'vue'
setup(){
const info = {name:"why"};
const readonlyInfo = readonly(info)
const readonlyInfo2 = reactive({
name:"why"
})
const readonlyInfo3 = ref("why")
const updateState = () =>{
//readonlyInfo.name = "coderwhy"
readonlyInfo2.name = "coderwhy"
同样也是修改不了的
ref需要通过value来修改
readonlyInfo3.value="coderwhy"
还是改不了
}
return{
updateState
}
此时使用update方法,会输出warn警告
}