Vue3
侦听器 watch 函数
watch 函数作用 : 定义侦听器,侦听数据的变化
watch 监听的三个参数
参数1 : 被监听的数据
- 实参可以直接写需要监听的数据
- 也可以传入一个函数
() => 被监听的数据或者对象的属性参数2 : 回调函数 - 语法 :
(NewVal,OldVal) => {} - 回调函数也有两个参数
NewVal: 修改后的新值OldVal: 修改前的旧值 参数3 : 额外的配置,是一个对象
- 对象中的可选属性
deep: true: 开启深度监听,用来监听复杂类型的数据(可以直接监听到对象中的属性发生改变)immediate: true: 初次进入立即监听( 不用等到监听的数据发生改变)
watch 函数的 3 种语法
1 . 监听响应式数据的语法
watch(响应式数据,处理函数)2 . 监听响应式数据 某个属性 的语法watch( () => 对象.属性名, 处理函数)3 . 深度监听 的语法watch( () => 对象.属性名,处理函数,{ deep: true, immediate: true })
watch 监听数据的四种写法
注意 : 要监听的数据如果是复杂类型的数据,有四种写法(得到的结果也会不同)
写法1 : 直接写对象(复杂类型)
setup () {
var n=ref(0)
var obj=reactive({
id:1,
name:'rose',
age:18
})
watch(obj,(newVal,oldVal)=>{
console.log(newVal,oldVal) // 新值 , undefined
})
const say = () => {
n.value++
obj.age++
}
return {say,n,obj}
}
结论 :
- 可以直接监听到属性内部,但是只能获取新值
- 开启深度监听后,可以获取新旧值
写法2 : 监听是一个函数
watch( ()=>obj,(newVal,oldVal)=>{
console.log(newVal,oldVal)// 新值 , undefined
},{
deep:true
})
结论 :
- 改变对象中的属性不会触发监听器
- 想触发需要使用深度监听,但是也只能获取到新值
写法3 : 函数写法,监听的是对象中的属性
watch( ()=>obj.age,(newVal,oldVal)=>{
console.log(newVal,oldVal) // 新值 , 旧值
})
结论 :
- 可以触发,可以获取新旧值
写法4 : 监听对象包在数组中
watch([obj,n],(newVal,oldVal)=>{
console.log(newVal,oldVal)// 新值 , undefined
})
结论 :
- 那就可以触发,只能获取新值
- 注意 : 监听对象包裹在数组中的话可以写多个
Vue3 中的生命周期钩子
生命周期函数 vue3 中的生命周期函数, 需要在 setup 中调用
注意 : 使用时都需要先导入
import { onMounted, onUpdated, onUnmounted } from 'vue'
export default {
setup() {
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
}
}
optionsAPI 和 compositionAPI 钩子函数的对比
初始化阶段
此阶段会生成 data
optionsAPI中的两个钩子
beforeCreate: 组件初始化前, 此时还没有生成data(无法获取data)created: 组件初始化后, 可以获取datacompositionAPI没有beforeCreate和created钩子函数setup()函数可以就是初始化阶段,执行时机还要在created钩子函数之前
挂载阶段
此阶段会挂载真实 DOM
optionsAPI中的两个钩子
beforeMount: 组件挂载前, 此时真实 DOM 还有挂载(无法获取真实 DOM )mounted: 组件挂载后, 可以获取真实 DOMcompositionAPI中的两个钩子onBeforeMount: 组件挂载前onMounted: 组件挂载后
更新阶段
数据改变会触发此阶段,数据改变会重新渲染虚拟 DOM 给真实 DOM 打补丁
optionsAPI中的两个钩子
beforeUpdate: 组件更新前, 此时真实 DOM 还有没有更新(无法获取修改后的真实 DOM )updated: 组件跟新后, 可以获取修改后的真实 DOMcompositionAPI中的两个钩子onBeforeUpdate: 组件更新前onUpdated: 组件挂载后
销毁阶段
使用 v-if 可以触发此阶段,此阶段会清楚定时器和一些全局事件,还有表单中填写的数据
optionsAPI中的两个钩子
beforeDestory: 组件销毁前destoryed: 组件销毁后compositionAPI中的两个钩子onBeforeUnmount: 组件销毁前onUnmounted: 组件销毁后
Vue3 中 ref 属性的使用
作用 : 用于获取模板中的元素 (真实 DOM 元素或者某个组件对象)
Vue3之前的版本
- 模板中使用
ref属性, mounted()中通过$refs获取真实 DOM 元素或者某个组件对象
Vue3 中 ref 的使用
- 创建一个空的 ref 对象 :
const myRef = ref(null) - 模板中建立关联 :
<h1 ref="myRef">123</h1> onMounted()钩子函数中使用 :Rref.value
<template>
<div>
<h1 ref="myRef">钩子函数-----123</h1>
<my-demo ref="myDemoRef"></my-demo>
</div>
</template>
<script>
import MyDemo from './components/my-demo.vue'
import { onMounted, ref } from 'vue'
export default {
components: {
MyDemo
},
setup () {
// 创建 ref
const myRef = ref(null)
const myDemoRef = ref(null)
onMounted(() => {
console.log(myRef.value) // DOM元素
console.log(myDemoRef.value) // 组件对象
})
return {
myRef,
myDemoRef
}
}
}
</script>
Vue 组件通信
1 . props 传值(父向子)
作用 : 父组件向子组件传值
props 属性中定义数据
语法1 (数组)
props : [ '数据名1' , '数据名2' ]语法2 (对象)props : { 数据名: { 属性 ...}}- 对象语法定义数据时的三个可选属性
type: 数据类型(可选值String/Array... 等)default: 父组件不传值时的默认值required:true或flase(true表示父组件必需传值)
简写 :
- 如果只有类型可以简写为
props : { 数据名: String }
使用 props 属性传值
父组件内 : 在模板的子组件中, 用自定义组件传值
- 语法 :
<组件名 自定义属性名="要传递的数据" />子组件内 : 在props中定义变量接收数据 , 并在模板中使用
export default {
// props: ['自定义属性名'],
props: {
自定义属性名: {
type: Number,
default: 1
}
}
}
Vue3 中使用 props 传值
父组件用法不变
子组件内 :
- 在
props中定义变量接收数据 - 在
setup()函数中使用数据 - 在模板中展示数据
export default {
props: {
自定义属性名: {
type: Number,
default: 1
}
},
// setup中使用
setup(props) {
props.自定义属性名
}
}
props 注意点
props用来接收父组件传过来的值- 在
props中使用驼峰形式,模版中要改为使用短横线拼接的格式 props里面的值只读,不能修改props是单向数据流
2 . $emit 传值(子向父)
父组件内 : 绑定自定义事件,声明事件处理函数用于接收
- 语法 :
<组件 @自定义事件名 = "事件处理函数" />
子组件内 : 使用 $emit 传值, 触发父组件中的自定义事件, 并传值
- 语法 :
this.$emit( 参数1 , 参数2 , 参数3 ... ) - 参数1 : 父组件中的
自定义事件名 - 参数2~N : 要传递给父组件中的数据
最后在父组件的事件处理函数中, 以形参的方式接收传递过来的值(可以修改)
Vue3 中的 emit 传值
父组件用法不变
子组件内 :
- 先使用
emits接收- 语法 :
emits[自定义事件名]
- 语法 :
- 在
setup( )函数中 , 用形参context调用emit方法 传递参数
export default {
emits: ['自定义事件名'],
setup( context ) {
const change = () => {
// 子传父
context.emit('自定义事件名', 数据 )
}
return {
change
}
}
}
</script>
3 . .sync修饰符传值
作用 : 修饰 props 的传值, 使其不再是单向数据流, 可以在子组件中修改父组件传递过来的数据
语法 :
-
父组件内 :
<组件名 自定义属性名.sync = "要传递的数据" /> -
子组件中 : 先在
props中接收, 再使用$emit("update:自定义属性名", 修改后的属性值)修改值- 需要使用 update 关键字
export default {
// props: ['自定义属性名'],
props: {
自定义属性名: {
type: Number,
default: 1
}
},
methods:{
dd(){
this.$emit("update:自定义属性名", 修改后的属性值)
}
}
}
Vue3 中已经废弃了 .sync 修饰符
4 . 依赖注入- provide 和 inject 传值
依赖注入的作用 : 可以非常方便的 , 实现跨层级的组件通信(例如: 父传子组件 , 父传孙组件)
使用方法 :
- 父组件利用
provide属性提供数据 - 子组件使用
inject属性获取数据 (子孙后代, 都可以拿到这个数据)
语法 :
- 父组件内
provide : { 属性名 : '数据' } - 子组件内
ingect : ['属性名']
注意 : provide 和 inject 都是和 data 同级的
Vue3 中的依赖注入
父组件中 : 先导入 provide, 再在 setup() 函数中使用 provide 传值
import {provide} from 'vue'
setup(){
provide('属性名',数据)
}
子组件中 : 先导入 inject, 再在 setup() 函数中使用 inject 接收
import {inject} from 'vue'
setup(){
const r=inject('rootMsg')
}
5 . v-model 传值
v-model 本质和 sync 修饰符一样, 都是双向绑定, 可以直接在子组件中修改父组件中的值
使用 :
- 父组件中 :
<组件名 v-model = "值" /> - 子组件中 : 在
props中使用value属性接收
export default {
// props: ['value'],
props: {
value : {
type: Number,
default: 1
}
}
}
- 子组件中 : 使用
$emit修改数据$emit("update:value", 修改后的值)
Vue3 中 v-model 传值
父组件中用法不变
子组件中 :
- 接收 : 在
props中使用modelValue属性接收
export default {
// props: ['value'],
props: {
modelValue : {
type: Number,
default: 1
}
}
}
- 修改 : 在
setup( )函数中 , 用形参context调用emit方法修改数据
export default {
setup( context ) {
const change = () => {
// 子传父
context.emit("update:modelValue", 修改后的值 )
}
return {
change
}
}
}
</script>
6 . vuex 数据共享
作用 : 更加方便高效的实现组件间的数据共享