前言:如果你是从vue2转到vue3的一份子,那么你重点学一下核心内容Composition API 。vue3的更新使代码写起来更加清晰,而且更接近于原生开发,对TS支持友好,现在我们来学习一下API。
如果你也想学一下TS那么请看这里 带你学习语法Typescript
setup(props,context){
// 不可以通过this获取所以要通过参数获取
console.log(props.message)
console.log(context.attrs.id + ' ' + context.attrs.class)
console.log(context.emit)
console.log(context.slots)
返回值return{ }可以代替 data(){}可以在模板中直接引用
setup()函数里可以写函数 可以代替methon{} 写方法
// 响应式方法一
// const state = reactive({
// title: 'hello kun',
// content: 100
// })
// 响应式方法二 挂载后可以直接在template中引用,不需要.value,vue自动解包为你省了一步
// 但是下面方法里依然还是要.value的
//template中浅层的解包,如果嵌套了不能解包。但是reactive中嵌套可以解包,但是我们不建议这么做
const title = ref('hello kun')
const content = ref(100)
一个proxy的set方法被劫持,可以传用但是不能修改,返回只读的代理
1,普通对象
无法响应式,比如我们可以传入到子组件,子组件无法修改但是无法做到响应式
2,传入reactive对象
子组件不能改,但是是响应式的,可以在这里改state1 或者ref的state3
const state1 = reactive({
name:'kun',
height:1.88
})
const state2 = readonly(state1)
3, 传入ref对象
const state3 = ref("why")
const state4 = readonly(state3)
isproxy
检查对象是否是由 reactive 或 readonly创建的 proxy
isReactive
检查对象是否是由 reactive创建的响应式代理:
如果该代理是 readonly 建的,但包裹了由 reactive 创建的另一个代理,它也会返回 true;
isReadonly
检查对象是否是由 readonly 创建的只读代理。
toRaw
返回 reactive 或 readonly 代理的原始对象(不建议保留对原始对象的持久引用。请谨慎使用)。
shallowReactive
创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (深层还是原生对象)。
shallowReadonly
创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换(深层还是可读、可写的)。
对reactive返回的对象进行解构获取的值,那么无论是修改结构后的变量,还是修改reactive返回的state对象,数据都不是响应式的,
vue提供了各函数torefs,可以将reactive返回的对象中的属性都转成ref
const state = reactive({
name:'zlk',
age:18
})
let {name,age} = toRefs(state);
const btnclick = () => {
// state.name = 'kun'
name.value = 'kun'
}
state.name和name.value建立链接,任何一个修改都会变化
如果我们只希望转换一个属性为ref,而不是整个reactive对象,可以使用toref方法
const state = reactive({
name:'zlk',
age:18
})
const name = toRef(state,'name')
const {age} = state;
const btnclick = () => {
// state.name = 'kun'
name.value = 'kun'
}
const info = shallowRef({name:'kun'})
const btnclick = () => {
info.value.name = 'feiji'
triggerRef(info)
}
shallowRef浅层ref,未响应式
triggerRef手动触发后,响应式了
<template>
<div>
<input v-model="message">
<h3>{{message}}</h3>
</div>
</template>
const message = ref('hello');
return{
message
}
这是普通双向绑定,
我们来自定义一个ref,做防抖
import {customRef} from "vue";
export function useref(value,delay = 1000){
let timer;
return customRef((track, trigger) => {
return{
get(){
track(); // 收集依赖
return value
},
set(newvalue){
clearTimeout(timer) // 防抖
timer = setTimeout(() => {
value = newvalue //赋值
trigger(); //更新模板依赖
},delay)
}
}
})
}
方式一:接收一个getter函数,并为 getter 函数返回的值,返回一个不变的 ref 对象
setup(){
let first = ref("kun");
let last = ref("ba");
let haha = 'nihao'
const fullName = computed(() => {
return first.value + ' ' + last.value
})
return{
first,
last,
fullName,
haha
}
}
方式二:接收一个具有 get 和 set 的对象,返回一个可变的**(可读写)ref 对象**;
setup(){
let first = ref("kun");
let last = ref("ba");
let fullName = computed({
get:() => {
return first.value + ' ' + last.value
},
set:(newvalue) => {
const names = newvalue.split(" ");
first.value = names[0];
last.value = names[1];
}
})
const btnclick = () => {
fullName.value = "coder kun"
}
watchEffect传入的函数会被立即执行一次,并且在执行的过程中会收集依赖;
只有收集的依赖发生变化时,watchEffect传入的函数才会再次执行;
const name = ref("hello")
const age = ref("18")
watchEffect(() => {
console.log("watcheffect",name.value,age.value)
})
const btnclick = () => {
name.value = "hi"
age.value = 23
}
return{
name,
age,
btnclick
}
setup(){
const name = ref("hello")
const age = ref("18")
const stop = watchEffect(() => {
console.log("watcheffect",name.value,age.value)
})
const btnclick = () => {
// name.value = "hi"
// age.value = 23
age.value++;
if (age.value > 25){
stop();
}
}
这个时候我们可以获取watchEffect的返回值函数,调用该函数即可。
setup(){
const name = ref("zlk");
const age = ref(18);
const titleref = ref(null)
const stopwatch = watchEffect(() => {
console.log(titleref.value)
},{
flush:"post"
})
{
flush:“post”
}
单个数据源监听
一个getter函数:但是该getter函数必须引用可响应式的对象(比如reactive或者ref);
直接写入一个可响应式的对象,reactive或者ref(比较常用的是ref);
ref
// const name = ref('zlk')
// const age = ref(18)
// watch(name , (newname,oldname) => {
// console.log(newname,oldname)
// })
reactive
// const state = reactive({
// name:'zlk',
// age:18
// })
// watch(() => state.name, (newname,oldname) => {
// console.log(newname,oldname)
// })
侦听器还可以使用数组同时侦听多个源
// watch([name,age], (newname,oldname) => {
// console.log(newname,oldname)
// })
侦听一个数组或者对象 ,使用一个getter函数,并且对可响应对象进行解构
// const names = reactive(["abc","bnm","nba"])
// watch(() => [...names],(newvalue,oldvalue) => {
// console.log(newvalue,oldvalue)
// })
侦听一个深层的侦听,那么依然需要设置 deep 为true:
p也可以传入 immediate 立即执行;
setup(){
const content = ref(0);
console.log("开始创建组件")
onMounted(() => {
console.log("onMounted-组件挂载到页面之后")
})
onBeforeMount(() => {
console.log("onBeforeMount-组件挂载到页面之前")
})
onUpdated(() => {
console.log("onUpdated-组件更新之后")
})
onActivated(() => {
console.log("onActivated")
})
onUnmounted(() => {
console.log("onUnmounted")
})
onBeforeUpdate(() => {
console.log("onBeforeUpdate-组件更新之前")
})
const btnclick = () => {
content.value++;
}
return{
content,
btnclick
}
}
created 和 beforecreate直接在setup里面写就可以了,vue3取消了,例如之前我们请求数据在created中请求,现在可以直接在setup里面写axios代码不用函数包裹调用