compositionApi
setup
setup 是Vue3.x新增的一个选项, 他是组件内使用 Composition API
的入口。
setup执行时机,在beforeCreate之前执行
setup(props,context) 参数
props: 组件传入的属性
context:{attrs,slot,emit}
//注意:setup中接受的props是响应式的, 当传入新的props 时,会及时被更新。由于是响应式的, 所以不可以使用ES6解构,解构会消除它的响应式。
//错误代码示范:段代码会让props不再支持响应式
export default defineComponent ({
setup(props, context) {
const { name } = props //错误用法
console.log(name)
},
})
可以使用toRefs进行转变,变成普通ref对象
什么是原始对象:
let obj={
name:'zhang',
age:'12'
} //这种就是原始对象
注意:定义的原始对象是没有响应式的
readonly(将响应式对象转为原始对象)
let obj=reactive({
name:'zhang',
age:'12'
}) //当前为响应式对象
obj=readonly(obj); //将响应式数据转为普通原始对象
reactive(只能用于代理对象)
reactive
函数可以代理一个对象, 但是不能代理基本类型,例如字符串、数字、boolean等
返回对象的响应式副本,返回的 proxy 是不等于原始对象的。建议只使用响应式 proxy,避免依赖原始对象。
reactive 将解包所有深层的 refs,同时维持 ref 的响应性。
import { reactive, ref } from 'vue'
const count = ref(1)
const obj = reactive({ count })
// ref 会被解包
//解包相当于是将.value赋值给了obj.count
console.log(obj.count === count.value) // true
count.value++ // 它会更新 `obj.count`
console.log(count.value) // 2
console.log(obj.count) // 2
// 它也会更新 `count` ref
obj.count++
console.log(obj.count) // 3
console.log(count.value) // 3
ref
接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value
property,指向该内部值。
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
//如果将对象分配为 ref 值,则它将被 reactive 函数处理为深层的响应式对象。
toRef
可以用来为源响应式对象上的某个 property 新创建一个 ref
。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。
const state = reactive({
foo: 1,
bar: 2
})
const fooRef = toRef(state, 'foo')
fooRef.value++
console.log(state.foo) // 2
state.foo++
console.log(fooRef.value) // 3
toRefs
将响应式对象转换为ref普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref
const state = reactive({
foo: 1,
bar: 2
})
const stateAsRefs = toRefs(state)
/*
stateAsRefs 的类型:
{
foo: Ref<number>,
bar: Ref<number>
}
*/
// ref 和原始 property 已经“链接”起来了
state.foo++
console.log(stateAsRefs.foo.value) // 2
stateAsRefs.foo.value++
console.log(state.foo) // 3
//当从组合式函数返回响应式对象时,toRefs 非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行解构/展开:
或者
const state=reactive({
num1:0,
num2:0,
result:0
});
const showstate=toRefs(state)
let {num1,num2,result}=showstate
这里的展开不会丢失响应性
在setup中使用方法
<button @click="setTitle">执行方法改变父组件的title</button>
import {ref} from "vue"
export default {
name:"App",
setup(){
let title =ref("app组件中的标题");
let setTitle=()=>{
title.value="哈哈哈"
}
return{
title
}
}
}
函数编程写法
{{num1}} {{num2}}
import {reactive,toRefs} from "vue"
export default{
name:"页面名",
props:{
msg:String
}
setup(){
const {num1,num2}=stateData()
return{
num1,
num2,
add
}
}
function stateData(){
const state=reactive({
num1:0,
num2:0,
result:0
});
function add(){
state.result=state.num1+state.num2;
}
return toRefs(state)
//这里的toRefs相当于可以将state的值进行展开解构出来
}
}
computed
import {reactive ,computed} from "vue"
export default{
name:"页面名",
props:{
msg:String
}
setup(){
const state=reactive({
num1:0,
num2:0,
result:computed(()=>parseInt(state.num1)+parseInt(state.num2))
});
//或者这么写
const full=computed(()=>{
return parseInt(state.num1)+parseInt(state.num2)
})
return{
state,
}
}
}
//parseInt:将字符串转为数字
watch
watch(source, callback, [options])
参数说明:
- source:可以支持string,Object,Function,Array; 用于指定要侦听的响应式变量
- callback: 执行的回调函数
- options:支持deep、immediate 和 flush 选项。
//侦听reactive定义的数据
import { defineComponent, ref, reactive, toRefs, watch } from "vue";
export default defineComponent({
setup() {
const state = reactive({ nickname: "xiaofan", age: 20 });
setTimeout(() =>{
state.age++
},1000)
// 修改age值时会触发 watch的回调
watch(
state,
(curAge, preAge) => {
console.log("新值:", curAge, "老值:", preAge);
}
);
//如果需要监听reactive里面的值需要这样写
watch(
() => state.age,
(curAge, preAge) => {
console.log("新值:", curAge, "老值:", preAge);
}
);
return {
...toRefs(state)
}
},
//侦听ref定义的数据
const year = ref(0)
setTimeout(() =>{
year.value ++
},1000)
watch(year, (newVal, oldVal) =>{
console.log("新值:", newVal, "老值:", oldVal);
})
侦听多个ref定义的数据
watch([() => state.age, year], ([curAge, newYear], [preAge, oldYear]) => {
console.log("新值:", curAge, "老值:", preAge);
console.log("新值:", newYear, "老值:", oldYear);
})
注意如果要监听复杂数据对象要在后面加deep:true
const state = reactive({
room: {
id: 100,
attrs: {
size: "140平方米",
type:"三室两厅"
},
},
});
watch(() => state.room, (newType, oldType) => {
console.log("新值:", newType, "老值:", oldType);
}), {deep:true})
wacthEffect
无论你的值是否改变,都会先执行一次
import {reactive,toRefs,watchEffect}
export default{
setup(){
let data=reactive({
num:1
})
watchEffect(()=>{
console.log("data.num",data.num) //当前监听的值为data.num
})
setInterval(()=>{
data.num
},1000)
return{
...toRefs(data)
}
}
}
vue3生命周期函数
注意:vue3的生命周期函数要写在setup中
import { defineComponent, onBeforeMount, onMounted, onBeforeUpdate,onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured, onRenderTracked, onRenderTriggered
} from "vue";
export default defineComponent({
// beforeCreate和created是vue2的
beforeCreate() {
console.log("------beforeCreate-----");
},
created() {
console.log("------created-----");
},
setup() {
console.log("------setup-----");
// vue3.x生命周期写在setup中
onBeforeMount(() => {
console.log("------onBeforeMount-----");
});
onMounted(() => {
console.log("------onMounted-----");
});
// 调试哪些数据发生了变化
onRenderTriggered((event) =>{
console.log("------onRenderTriggered-----",event);
})
},