Vue3.0 生命周期函数变更
在Vue2.x中,实现一个功能,需要在data中新增数据,在methods/computed/watch中新增业务逻辑,数据和业务逻辑是分离的,不利于管理
Vue3.0推出了Composition API(组合API),也叫做注入API,setup()是组合API的入口函数,可以直接在里面定义变量和方法(数据和业务逻辑),通过对象的形式返回暴露出去
执行时机
setup执行顺序是在beforeCreate之前的
生命周期函数
与 2.x 版本生命周期相对应的组合式 API :onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted
新增的钩子函数onRenderTracked、onRenderTriggered,两个钩子函数都接收一个 DebuggerEvent,与 watchEffect 参数选项中的 onTrack 和 onTrigger 类似
<template>
<div>
{{ message }}
<van-button type="primary" @click="changeMessage">修改</van-button>
<van-button type="primary" @click="go">跳转</van-button>
</div>
</template>
<script>
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onRenderTracked,
onRenderTriggered,
ref,
getCurrentInstance
} from 'vue';
export default {
name: "temp",
setup() {
const { ctx } = getCurrentInstance();
let message = ref("你好");
const changeMessage = () => {
message.value = "hello";
}
onBeforeMount(() => {
console.log("挂载前");
})
onMounted(() => {
console.log("挂载");
})
onBeforeUpdate(() => {
console.log("更新前");
})
onUpdated(() => {
console.log("更新");
})
onBeforeUnmount(() => {
console.log("销毁前");
})
onUnmounted(() => {
console.log("销毁");
})
onRenderTracked(() => {
console.log("onRenderTracked");
})
onRenderTriggered(() => {
console.log("onRenderTriggered");
})
const go = () => {
ctx.$router.push({
path: "/cart"
})
}
return {
message,
changeMessage,
go
}
}
}
</script>
基本使用
- ref单值
<template>
<div>
{{ message }}
<van-button type="primary" @click="changeMessage">修改</van-button>
</div>
</template>
<script>
import {
ref
} from 'vue';
export default {
name: "temp",
setup() {
// 它其实是用proxy代理了一个对象 `{ value: '你好' }`
let message = ref("你好");
const changeMessage = () => {
message.value = "hello";
}
return {
message
}
}
}
</script>
修改变量值有两种方法:
setup中暴露一个函数,直接去修改.value;
在methods中定义一个方法,在此方法的内部通过this.XX=新值来修改
<script>
import {
ref
} from 'vue';
export default {
name: "temp",
setup() {
let message = ref("你好");
const changeMessage = () => { // 方式一
message.value = "hello";
}
return {
message,
changeMessage
}
},
methods: {
changeMessageC() { // 方式二
this.message = "helloC"
}
}
}
</script>
- reactive对象
<template>
<div>
{{ obj.name }}
{{ obj.arr }}
<van-button type="primary" @click="changeData">修改</van-button>
</div>
</template>
<script>
import {
reactive
} from 'vue';
export default {
name: "temp",
setup() {
let obj = reactive({
name: "张三",
arr: []
});
const changeData = () => {
obj.name = "ZS";
obj.arr.push("1", "2");
}
return {
obj,
changeData
}
}
}
</script>
要修改这个值,有两种方式:
在setup中暴露一个函数,直接去修改 ;
在methods中定义一个方法,在内部通过this.ojb.XX=新值 来修改
<script>
import {
reactive
} from 'vue';
export default {
name: "temp",
setup() {
let obj = reactive({
name: "张三",
arr: []
});
const changeData = () => { // 方式一
obj.name = "ZS";
obj.arr.push("1", "2");
}
return {
obj,
changeData
}
},
methods: {
changeDataC() { // 方式二
this.obj.name = "ZSC"
this.obj.arr.push("3");
}
}
}
</script>
- reactive对象+toRefs
通过引入toRefs包装一个reactive对象,然后再展开,就可以省略obj这个前缀了
<template>
<div>
{{ name }}
{{ arr }}
</div>
</template>
<script>
import {
reactive,
toRefs
} from 'vue';
export default {
name: "temp",
setup() {
let obj = reactive({
name: "张三",
arr: []
});
return {
...toRefs(obj)
}
}
}
</script>
- 定义计算属性
通过computed(回调)的方式来计算属性,然后在setup中返回即可。
<template>
<div>
<div>
原始值: {{ obj.count }}
<van-button type="primary" @click="add">修改</van-button>
</div>
<div>2倍原始值: {{ doubleB }}</div>
</div>
</template>
<script>
import {
reactive,
computed
} from 'vue';
export default {
name: "temp",
setup() {
let obj = reactive({
count: 1
});
const add = () => { // 修改原始值
obj.count++;
}
const doubleB = computed(() => {
return 2 * obj.count;
})
return {
obj,
add,
doubleB
}
}
}
</script>
- watch
<template>
<div>
{{ obj.count }}, {{ a }}
<br />
<van-button type="primary" @click="obj.count+=1">原址obj.count+1</van-button>
<van-button type="primary" @click="a+=1">原值a+1</van-button>
</div>
</template>
<script>
import {
ref,
reactive,
watch
} from 'vue';
export default {
name: "temp",
setup() {
const a = ref(0);
// reactive: 会对对象进行包装
const obj = reactive({
count: 0
})
// 通过watch来监听
watch(a, () => {
console.log("变量a改变了")
})
watch(() => obj.count, () => {
console.log("obj.count改变了")
})
return {
a,
obj
}
}
}
</script>
- 使用路由
<template>
<div>
<van-button type="primary" @click="go">跳转</van-button>
</div>
</template>
<script>
import {
getCurrentInstance
} from 'vue';
export default {
name: "temp",
setup() {
const { ctx } = getCurrentInstance();
const go = () => {
ctx.$router.push({
path: "/cart"
})
}
return {
go
}
}
}
</script>
- vuex使用
<template>
<div>
{{ goodsList }}
</div>
</template>
<script>
import {
ref,
nextTick
} from "vue";
import { useStore } from "vuex";
export default {
name: "temp",
setup() {
const store = useStore(); // 使用vuex
let goodsList = ref([]);
const addCar = () => { // 添加购物车
// 调用vuex cart模块mutations中的addToCar方法
store.commit("cart/addToCar", {
id: 2,
title: "临时数据",
desc: "描述",
thumb_path: imgUrl,
sell_price: 12.8,
count: 10,
select: false
})
}
const getGoodsList = () => { // 获取购物车数据
nextTick(() => {
goodsList.value = store.getters.shopCar;
});
}
getGoodsList();
return {
goodsList,
addCar,
getGoodsList,
}
}
}
</script>
代码地址
gitee.com/smallgrey/new-features-of-vue3