前言:如果你是从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手动触发后,响应式了
{{message}}
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 = 23age.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代码不用函数包裹调用