Vue3 响应式侦听与计算的实现


Posted in Javascript onNovember 11, 2020

响应式侦听和计算

有时我们需要依赖于其他状态的状态——在 Vue 中,这是用组件 计算属性 处理的,以直接创建计算值,我们可以使用 computed 方法:它接受 getter 函数并为 getter 返回的值返回一个不可变的响应式 ref 对象。

我们先来看看一个简单的例子,关于计算值的方式,同样我们在 src/TemplateM.vue 写下如下代码:

<template>
 <div class="template-m-wrap">
  count ---> {{count}}
  plusOne ---> {{plusOne}}
 </div>
</template>
<script>
import { ref, defineComponent, reactive, computed } from "vue";
export default defineComponent({
 name: 'TemplateM',
 setup() {
  let count = ref(2)
  let plusOne = computed(() => {
   return count.value++
  })
  console.log(plusOne.value)
  return {
   count,
   plusOne
  }
 }
})
</script>

访问链接效果如下:

Vue3 响应式侦听与计算的实现

我们可以看到 plusOne 没有值。或者,它可以使用一个带有 getset 函数的对象来创建一个可写的 ref 对象。

<template>
 <div class="template-m-wrap">
  count ---> {{ count }} plusOne ---> {{ plusOne }}
 </div>
</template>
<script>
import { ref, defineComponent, reactive, computed } from "vue";
export default defineComponent({
 name: "TemplateM",
 setup() {
  let count = ref(2);
  let plusOne = computed({
   get() {
    return count.value++;
   },
   set(val) {
    count.value = val;
   },
  });
  plusOne.value = 1;
  console.log(count.value); // 0
  return {
   count,
   plusOne,
  };
 },
});
</script>

同样访问效果如下:

Vue3 响应式侦听与计算的实现

watchEffect

为了根据响应式状态 自动应用重新应用 副作用,我们可以使用 watchEffect 方法。它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

<template>
 <div class="template-m-wrap">
  count ---> {{ count }}
 </div>
</template>
<script>
import { ref, defineComponent, reactive, computed, watchEffect } from "vue";
export default defineComponent({
 name: "TemplateM",
 setup() {
  let count = ref(2);
  watchEffect(() => {
   console.log(count.value)
  })
  setTimeout(() => {
   count.value++
  }, 1000)
  return {
   count,
  };
 },
});
</script>

查看效果如下:

Vue3 响应式侦听与计算的实现

停止侦听

watchEffect 在组件的 setup() 函数或 生命周期钩子 被调用时,侦听器会被链接到该组件的生命周期,并在组件卸载时自动停止。

在一些情况下,也可以显式调用返回值以停止侦听:

<template>
 <div class="template-m-wrap">
  count ---> {{ count }}
 </div>
</template>
<script>
import { ref, defineComponent, reactive, computed, watchEffect } from "vue";
export default defineComponent({
 name: "TemplateM",
 setup() {
  let count = ref(2);
  const stopWatch = watchEffect(() => {
   console.log(count.value)
  })
  stopWatch()
  setTimeout(() => {
   count.value++
  }, 1000)
  return {
   count,
  };
 },
});
</script>

查看效果如下:

Vue3 响应式侦听与计算的实现

副作用刷新时机

Vue 的响应性系统会缓存副作用函数,并异步地刷新它们,这样可以避免同一个“tick” 中多个状态改变导致的不必要的重复调用。在核心的具体实现中,组件的 update 函数也是一个被侦听的副作用。当一个用户定义的副作用函数进入队列时,默认情况下,会在所有的组件 update 执行:

<template>
 <div>{{ count }}</div>
</template>

<script>
 export default {
  setup() {
   const count = ref(0)

   watchEffect(() => {
    console.log(count.value)
   })

   return {
    count
   }
  }
 }
</script>

在这个例子中:

  • count 会在初始运行时同步打印出来
  • 更改 count 时,将在组件 更新前 执行副作用。

如果需要在组件更新 重新运行侦听器副作用,我们可以传递带有 flush 选项的附加 options 对象 (默认为 'pre' ):

// fire before component updates
watchEffect(
 () => {
  /* ... */
 },
 {
  flush: 'post'
 }
)

flush 选项还接受 sync ,这将强制效果始终同步触发。然而,这是低效的,应该很少需要。

侦听器调试

onTrackonTrigger 选项可用于调试侦听器的行为。

  • onTrack 将在响应式 property 或 ref 作为依赖项被追踪时被调用。
  • onTrigger 将在依赖项变更导致副作用被触发时被调用。

这两个回调都将接收到一个包含有关所依赖项信息的调试器事件。建议在以下回调中编写 debugger 语句来检查依赖关系:

watchEffect(
 () => {
  /* 副作用 */
 },
 {
  onTrigger(e) {
   debugger
  }
 }
)

onTrackonTrigger 只能在开发模式下工作。

watch

watch API 完全等同于组件侦听器 property。 watch 需要侦听特定的数据源,并在回调函数中执行副作用。默认情况下,它也是惰性的,即只有当被侦听的源发生变化时才执行回调。

与watchEffect 比较, watch 允许我们:

  • 懒执行副作用;
  • 更具体地说明什么状态应该触发侦听器重新运行;
  • 访问侦听状态变化前后的值。

 侦听单个数据源

侦听器数据源可以是返回值的 getter 函数,也可以直接是 ref

// 侦听一个 getter
const state = reactive({ count: 0 })
watch(
 () => state.count,
 (count, prevCount) => {
  /* ... */
 }
)

// 直接侦听ref
const count = ref(0)
watch(count, (count, prevCount) => {
 /* ... */
})

到此这篇关于Vue3 响应式侦听与计算的实现的文章就介绍到这了,更多相关Vue3 响应式侦听与计算内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
用js生产批量批处理执行命令
Jul 28 Javascript
jquery 3D球状导航的文章分类
Jul 06 Javascript
jquery实现下拉菜单的二级联动利用json对象从DB取值显示联动
Mar 27 Javascript
浅谈jQuery的offset()方法及示例分享
Jul 17 Javascript
javascript下拉列表菜单的实现方法
Nov 18 Javascript
JCrop+ajaxUpload 图像切割上传的实例代码
Jul 20 Javascript
AngularJS基础 ng-mouseleave 指令详解
Aug 02 Javascript
js 用于检测类数组对象的函数方法
May 02 Javascript
node.js中express-session配置项详解
May 31 Javascript
BootStrap模态框不垂直居中的解决方法
Oct 19 Javascript
了解前端理论:rscss和rsjs
May 23 Javascript
vue组件命名和props命名代码详解
Sep 01 Javascript
详解Vue.js3.0 组件是如何渲染为DOM的
Nov 10 #Javascript
在vs code 中如何创建一个自己的 Vue 模板代码
Nov 10 #Javascript
JavaScript中常用的3种弹出提示框(alert、confirm、prompt)
Nov 10 #Javascript
原生JS实现弹幕效果的简单操作指南
Nov 10 #Javascript
vue解决跨域问题(推荐)
Nov 10 #Javascript
关于vue 项目中浏览器跨域的配置问题
Nov 10 #Javascript
如何在vue 中引入使用jquery
Nov 10 #jQuery
You might like
PHP取二进制文件头快速判断文件类型的实现代码
2013/08/05 PHP
Laravel 修改验证异常的响应格式实例代码详解
2020/05/25 PHP
firefox下frameset取不到值的解决方法
2010/09/06 Javascript
jquery 插件学习(一)
2012/08/06 Javascript
用按钮控制iframe显示的网页实现方法
2013/02/04 Javascript
JQuery实现超链接鼠标提示效果的方法
2015/06/10 Javascript
jQuery仿360导航页图标拖动排序效果代码分享
2015/08/24 Javascript
js实现横向伸展开的二级导航菜单代码
2015/08/28 Javascript
JavaScript 经典实例日常收集整理(常用经典)
2016/03/30 Javascript
Bootstrap被封装的弹层
2016/07/20 Javascript
BootStrap 图标icon符号图标glyphicons不正常显示的快速解决办法
2016/12/08 Javascript
vue 每次渲染完页面后div的滚动条保持在最底部的方法
2018/03/17 Javascript
详解处理bootstrap4不支持远程静态框问题
2018/07/20 Javascript
Json实现传值到后台代码实例
2020/06/30 Javascript
[00:14]护身甲盾
2019/03/06 DOTA
python获取指定路径下所有指定后缀文件的方法
2015/05/26 Python
Python编程pygame模块实现移动的小车示例代码
2018/01/03 Python
Pycharm 2020年最新激活码(亲测有效)
2020/09/18 Python
如何使用PyCharm引入需要使用的包的方法
2020/09/22 Python
HTML5新控件之日期和时间选择输入的实现代码
2018/09/13 HTML / CSS
韩国休闲女装品牌网站:ANAIS
2016/08/24 全球购物
FitFlop美国官网:英国符合人体工学的鞋类品牌
2018/10/05 全球购物
意大利香水和化妆品购物网站:Parfimo.it
2019/10/06 全球购物
中国制造网:Made-in-China.com
2019/10/25 全球购物
Ajax的工作原理
2015/12/04 面试题
学院书画协会部门职责
2013/11/28 职场文书
毕业生自我鉴定实例
2014/01/21 职场文书
2014年迎新年联欢会活动策划方案
2014/02/26 职场文书
出国留学担保书
2014/05/20 职场文书
巴西世界杯32强口号
2014/06/05 职场文书
优秀团员个人总结
2015/02/26 职场文书
党支部审查意见
2015/06/02 职场文书
生日寿星公答谢词
2015/09/29 职场文书
高一英语教学反思
2016/03/03 职场文书
go xorm框架的使用
2021/05/22 Golang
JavaScript流程控制(循环)
2021/12/06 Javascript