vue3 day4
分类:vue
watchEffie
- watch套路是:既要指明监视的属性,也要指明监视的回调
- watchEffie的套路是:不用指明监视哪个属性,监视的回调中用到哪个,就监视哪个属性
- watchEffie有点像computed
- 但是computed注重计算出来的值(回调函数的返回值),所以必须写返回值
- 而watchEffie更加注重的是过程(回调函数的函数体),所以不用写返回值
<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方式的生命周期写法
- demo.vue
<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>
- app.vue
<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写法写生命周期
- 注意点 setup会最先执行
- vue3写法执行会优先vue2
<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>
hook
需求,获取鼠标的点击位置
- 基础代码实现
<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>
- hook代码实现
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
}
- 使用hook
<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函数
- 什么是hook? 本质是一个函数,把setup函数中使用到的composition api 进行了封装
- 类似于vue2中的mixin
- 自定义hook的优势,复用代码,让setup中的逻辑更清晰易懂
toRef
先看下原始代码
<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.
来取值
- 使用toRef简化操作
<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>
总结
- 作用: 创建一个ref对象,其value值指向另一个对象中的某个属性
- 语法
const name = toRef(person,'name')
- 应用": 要将响应式数据中的某一个属性给外部使用
- 扩展:
toRef
和toRefs
功能一致,但是可以批量创建多个ref对象,语法:toRefs(person)
一线大厂高级前端编写,前端初中阶面试题,帮助初学者应聘,需要联系微信:javadudu