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
: 组件初始化后, 可以获取data
compositionAPI
没有beforeCreate
和created
钩子函数setup()
函数可以就是初始化阶段,执行时机还要在created
钩子函数之前
挂载阶段
此阶段会挂载真实 DOM
optionsAPI
中的两个钩子
beforeMount
: 组件挂载前, 此时真实 DOM 还有挂载(无法获取真实 DOM )mounted
: 组件挂载后, 可以获取真实 DOM
compositionAPI
中的两个钩子onBeforeMount
: 组件挂载前onMounted
: 组件挂载后
更新阶段
数据改变会触发此阶段,数据改变会重新渲染虚拟 DOM 给真实 DOM 打补丁
optionsAPI
中的两个钩子
beforeUpdate
: 组件更新前, 此时真实 DOM 还有没有更新(无法获取修改后的真实 DOM )updated
: 组件跟新后, 可以获取修改后的真实 DOM
compositionAPI
中的两个钩子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 数据共享
作用 : 更加方便高效的实现组件间的数据共享