<template>
<h1>求和结果是{{ sum }}</h1>
<button @click="sum++">计算+1</button>
<br>
<h3>msg为{{ msg }}</h3>
<button @click="msg+='!'">修改msg</button>
<br>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>薪资:{{ person.job.j1.salary }}</h2>
<button @click="person.age++">增加年龄</button>
<button @click="person.name+='~'">增加姓名</button>
<button @click="person.job.j1.salary++">涨薪</button>
<button @click="person.job.j1.aaa[0] = 10 ">测试监听reactive中的数组</button>
</template>
<script>
import {reactive, ref, watchEffect} from "vue";
export default {
name: "Demo",
setup() {
let sum = ref(0);
let msg = ref("我是msg");
let person = reactive({
name: '花花',
age: 20,
job: {
j1: {
salary: 100,
aaa: [1, 2, 3, 4]
}
}
})
//只要回调函数中用到的数据发生变化,就会自动执行回调
//自带immediate:true
watchEffect(() => {
console.log(person.age)
console.log(person.job.j1.salary)
console.log("修改了")
})
return {
sum, msg, person
}
}
}
</script>
<style scoped>
</style>
vue2的生命周期图
vue3的生命周期图
总结
vue3中依然可以使用v2的配置方式来定义生命周期钩子,但是有两个生命周期更改了名字
beforeDestroy
改名为beforeUnmount
destroyed
改名为unmounted
vue3也提供了composition api
的形式的生命周期钩子,与vue2中钩子对应关系如下
beforeCreate
=> setup()
created
=> setup()
beforeMount
=> onBeforeMount
mounted
=> onMounted
beforeUpdate
=>onBeforeUpdate
updated
=> onUpdated
beforeUnmount
=> onBeforeUnmount
unmounted
=> onUnmounted
回顾vue2方式的生命周期写法
<template>
<demo v-if="isShow">
</demo>
<button @click="isShow=!isShow">显示影藏</button>
</template>
<script>
import Demo from "@/components/Demo";
import {ref} from "vue";
export default {
name: 'App',
components: {Demo},
setup(){
let isShow = ref(true);
return{
isShow
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
<template>
<h1>标题</h1>
<h2>{{age}}</h2>
<button @click="age++">更改数据</button>
</template>
<script>
import {ref} from "vue";
export default {
name: "Demo",
beforeCreate() {
console.log('---beforeCreate---')
},
created() {
console.log('---created---')
},
beforeUpdate() {
console.log('---beforeUpdate---')
},
updated() {
console.log('---updated---')
},
beforeMount() {
console.log('---beforeMount---')
},
mounted() {
console.log('---mounted---')
},
beforeUnmount() {
console.log('---beforeUnmount---')
},
unmounted() {
console.log('---unmounted---')
},
setup() {
return {
age:ref(10)
}
}
}
</script>
<style scoped>
</style>
使用vue3写法写生命周期
<template>
<h1>标题</h1>
<h2>{{ age }}</h2>
<button @click="age++">更改数据</button>
</template>
<script>
import {onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, ref} from "vue";
export default {
name: "Demo",
beforeCreate() {
console.log('---beforeCreate---')
},
created() {
console.log('---created---')
},
beforeUpdate() {
console.log('---beforeUpdate---')
},
updated() {
console.log('---updated---')
},
beforeMount() {
console.log('---beforeMount---')
},
mounted() {
console.log('---mounted---')
},
beforeUnmount() {
console.log('---beforeUnmount---')
},
unmounted() {
console.log('---unmounted---')
},
setup() {
console.log("---setup---")
onBeforeUpdate(() => {
console.log("---onBeforeUpdate---")
})
onUpdated(() => {
console.log("---onUpdated---")
})
onBeforeMount(() => {
console.log("---onBeforeMount---")
})
onMounted(() => {
console.log("---onMounted---")
})
onBeforeUnmount(() => {
console.log("---onBeforeUnmount---")
})
onUnmounted(() => {
console.log("---onUnmounted---")
})
return {
age: ref(10)
}
}
}
</script>
<style scoped>
</style>
需求,获取鼠标的点击位置
<template>
<h2>测试hook</h2>
<p>鼠标点击的坐标是 x:{{ point.x }} ,y:{{ point.y }}</p>
</template>
<script>
import {onMounted, onUnmounted, reactive, ref} from "vue";
export default {
name: "Demo",
setup() {
let point = reactive({
x: 0,
y: 0
})
const clickFun = event => {
point.x = event.pageX
point.y = event.pageY
};
onMounted(()=>{
window.addEventListener("click",clickFun )
})
onUnmounted(()=>{
window.removeEventListener("click",clickFun )
})
return {
age: ref(10),
point
}
}
}
</script>
<style scoped>
</style>
usePoint.js
import {onMounted, onUnmounted, reactive} from "vue";
export default function () {
let point = reactive({
x: 0,
y: 0
})
const clickFun = event => {
point.x = event.pageX
point.y = event.pageY
};
onMounted(() => {
window.addEventListener("click", clickFun)
})
onUnmounted(() => {
window.removeEventListener("click", clickFun)
})
return point
}
<template>
<h2>测试hook</h2>
<p>鼠标点击的坐标是 x:{{ point.x }} ,y:{{ point.y }}</p>
</template>
<script>
import {ref} from "vue";
import usePoint from '../hooks/UserPoint'
export default {
name: "Demo",
setup() {
const point = usePoint()
return {
age: ref(10),
point
}
}
}
</script>
<style scoped>
</style>
自定义hook函数
先看下原始代码
<template>
<h2>测试toRef</h2>
<h1>姓名{{ person.name }}</h1>
<h2>年龄{{ person.age }}</h2>
<h3>薪水{{ person.job.j1.salary }}</h3>
<button @click="person.age++">年龄增长</button>
<button @click="person.name+='~'">姓名修改</button>
<button @click="person.job.j1.salary++">涨薪</button>
</template>
<script>
import {reactive} from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
name: '花花',
age: 20,
job: {
j1: {
salary: 300
}
}
})
return {
person
}
}
}
</script>
<style scoped>
</style>
存在的问题: 在模板中反复使用了person.
来取值
<template>
<h2>测试toRef</h2>
<h1>姓名{{ name }}</h1>
<h2>年龄{{ age }}</h2>
<h3>薪水{{ salary }}</h3>
<button @click="age++">年龄增长</button>
<button @click="name+='~'">姓名修改</button>
<button @click="salary++">涨薪</button>
</template>
<script>
import {reactive, toRef} from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
name: '花花',
age: 20,
job: {
j1: {
salary: 300
}
}
})
return {
name: toRef(person, 'name'),
age: toRef(person, 'age'),
salary: toRef(person.job.j1,'salary')
}
}
}
</script>
<style scoped>
</style>
Ref
,因为Ref
会生成新对象,不会修改原有的person
使用ToRefs简化ToRef
<template>
<h2>测试toRef</h2>
<h1>姓名{{ name }}</h1>
<h2>年龄{{ age }}</h2>
<h3>薪水{{ job.j1.salary }}</h3>
<button @click="age++">年龄增长</button>
<button @click="name+='~'">姓名修改</button>
<button @click="job.j1.salary++">涨薪</button>
</template>
<script>
import {reactive, toRefs} from "vue";
export default {
name: "Demo",
setup() {
let person = reactive({
name: '花花',
age: 20,
job: {
j1: {
salary: 300
}
}
})
//这里对toRefs之后的对象进行了解构
return {
person,
...toRefs(person)
}
}
}
</script>
<style scoped>
</style>
总结
const name = toRef(person,'name')
toRef
和toRefs
功能一致,但是可以批量创建多个ref对象,语法:toRefs(person)