前言 在开发中遇到一个需求:
现有A、B两页面,其中B页面是A页面的新页面(不是父子组件关系),要求:A页面传递id参数,B页面接收传递参数,当A页面不传递参数(undefined)或传空时,B页面保持原先A页面传递过来的id值(B页面接收的参数不可能为空) 即:
A(id=1) => B(id=1)
A(不传&id=undefined) => B(id=1)
A(id=2) => B(id=2)
…
Vue侦听器(watch) 在前言中提到的需求,实现的方法有多种,例如 (以下将侦听器更换名为监听器)
sessionStorage (会话存储) 和 localStorage(本地存储)
Vue状态管理器
Vue监听器(watch)
….
本文主要以 Vue监听器(watch) 为方法进行实现(主要还是回顾Vue内置的监听方法使用)vue官网-侦听器
在watch函数中支持监听以下三种数据源类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const x = ref (0 )const y = ref (0 )watch (x, (newX ) => { console .log (`x is ${newX} ` ) })watch (() => x.value + y.value ,(sum ) => { console .log (`sum of x + y is: ${sum} ` ) } )watch ([x, () => y.value ], ([newX, newY] ) => { console .log (`x is ${newX} and y is ${newY} ` ) })
实现 以上就是监听器大致使用,进入正题,实现前言的需求
A页面通过点击事件携带id参数 跳转至B页面
1 2 3 4 5 6 7 const bindHandleA = (id )=>{ router.push ({ name : "B页面" , query : {id} }); }
B页面接收A页面传递过来的参数
1 2 3 const parA = ref (); parA.value = route.query .id
通过onActivated或onMounted生命周期方法进行监听每次传递id的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 let webId = null ;const newActive = ref (false );onMounted (() => { webId = route.query .id ; watch (()=> route.query .id ,(newID,oldID ) => { if (newID === undefined || newID === '' ){ webId = oldID; newActive.value = false ; } if (oldID === undefined ){ webId = newID; newActive.value = true ; } if (newActive.value ){ console .log (webId); } }); });onActivated (() => { watch (()=> route.query .id ,(newID,oldID ) => { if (newID === undefined || newID === '' ){ webId = oldID; newActive.value = false ; return ; } if (oldID === undefined ){ webId = newID; newActive.value = true ; return ; } }); if (newActive.value ){ console .log (webId); } })
完成,无论A页面传递什么id值过来都能保持最新状态同时当A页面传值为空时,在监听中保存了有上一次记录值,依旧能够有记录值在此保存着
补充 深层监听 监听器的深层监听,以上面的代码为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 watch (()=> route.query .id ,(newID,oldID ) => { if (newID === undefined || newID === '' ){ webId = oldID; newActive.value = false ; return ; } if (oldID === undefined ){ webId = newID; newActive.value = true ; return ; } }); if (newActive.value ){ console .log (webId); } },{deep : true })
通过deep:true 开启强制深层监听
注意 开启了深层监听是无法实现前言提到的需求因为传递回的newID,oldID是相等一样的
在Vue官网介绍中,直接给 watch() 传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发:
1 2 3 4 5 6 7 8 9 10 const obj = reactive ({ count : 0 })watch (obj, (newValue, oldValue ) => { }) obj.count ++
相比之下,一个返回响应式对象的 getter 函数,只有在返回不同的对象时,才会触发回调:
1 2 3 4 5 6 watch ( () => state.someObject , () => { } )
谨慎使用 深度侦听需要遍历被侦听对象中的所有嵌套的属性,当用于大型数据结构时,开销很大。因此请只在必要时才使用它,并且要留意性能。
即时回调的侦听器 watch函数是懒执行状态,只有监听数据源变化时才能执行watch函数回调 通过传入 immediate: true 选项来强制侦听器的回调立即执行:
1 2 3 4 5 6 7 watch ( source, (newValue, oldValue ) => { }, { immediate : true } )
watchEffect() 在vue官网中的介绍是:侦听器的回调使用与源完全相同的响应式状态是很常见的。例如下面的代码,在每当 todoId 的引用发生变化时使用侦听器来加载一个远程资源:
1 2 3 4 5 6 7 8 9 10 11 12 13 const todoId = ref (1 )const data = ref (null )watch ( todoId, async () => { const response = await fetch ( `https://jsonplaceholder.typicode.com/todos/${todoId.value} ` ) data.value = await response.json () }, { immediate : true } )
通过watchEffect来简化上述监听函数不需要immediate: true
1 2 3 4 5 6 watchEffect (async () => { const response = await fetch ( `https://jsonplaceholder.typicode.com/todos/${todoId.value} ` ) data.value = await response.json () })
这个例子中,回调会立即执行,不需要指定 immediate: true。在执行期间,它会自动追踪 todoId.value 作为依赖(和计算属性类似)。每当 todoId.value 变化时,回调会再次执行。有了 watchEffect(),我们不再需要明确传递 todoId 作为源值。
结尾 以上就是Vue侦听器(watch)的实践分享的全部内容,在补充中有很多都是Vue官网中的案例和介绍,就不再叙述补充了,详细可以去查看Vue官网中的介绍案例,如不理解的地方欢迎讨论。
Vue官网侦听器