Vue3中的computed和watch属性

news2024/11/27 22:30:31

文章目录

  • 1. computed计算属性
  • 2. watch侦听器属性
    • 2.1 watchEffect
    • 2.2 watch


1. computed计算属性

简写写法(只实现了 get ):

<template>
  <div>
    <ul>
      <li v-for="item of carts" :key="item.id">
        {{ item.name }}
      </li>
    </ul>
    <hr />
    <h3>合计:{{ totalPrice }}</h3>
  </div>
</template>

<script>
import { computed, reactive, toRefs } from 'vue'
export default {
  setup() {
    let state = reactive({
      carts: [
        { id: 1, name: '小米', price: 1, num: 1 },
        { id: 2, name: '大米', price: 1, num: 1 }
      ],
      total: 0
    })

    // 计算属性   -- get
    let totalPrice = computed(() => {
      return state.carts.reduce((p, { price, num }) => {
        p += price * num
        return p
      }, 0)
    })

    // let totalPrice = computed({
    //   get() {
    //     return state.carts.reduce((p, { price, num }) => {
    //       p += price * num
    //       return p
    //     }, 0)
    //   }
    // })

    return { ...toRefs(state), totalPrice }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

标准写法(可以实现 get 和 set 方法):

<template>
  <div>
    <ul>
      <li v-for="item of carts" :key="item.id">
        {{ item.name }}
      </li>
    </ul>
    <hr />
    <h3>合计:{{ totalPrice }}</h3>
  </div>
</template>

<script>
import { computed, reactive, toRefs } from 'vue'
export default {
  setup() {
    let state = reactive({
      carts: [
        { id: 1, name: '小米', price: 1, num: 1 },
        { id: 2, name: '大米', price: 1, num: 1 }
      ],
      total: 0
    })

    let totalPrice = computed({
      get() {
        return state.carts.reduce((p, { price, num }) => {
          p += price * num
          return p
        }, 0)
      },
      // 了解一下
      set(v) {
        console.log('set', v)
      }
    })
    // 如果你给计算属性赋值,则一定要写标准方式,set方法一定要写
    totalPrice.value = 'abc'
    return { ...toRefs(state), totalPrice }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

完整的购物车案例:

<template>
  <div>
    <h3>{{ total }}</h3>
    <ul>
      <li v-for="(item, index) of carts" :key="item.id">
        <span>{{ item.name }}</span>
        <span>
          <button @click="setNum(index, 1)">+</button>
          <button @click="totalPrice = { index, n: 1 }">另一种实现求和的方式</button>
          <span>{{ item.num }}</span>
          <button @click="setNum(index, -1)">-</button>
        </span>
      </li>
    </ul>
    <hr />
    <h3>合计:{{ totalPrice }}</h3>
  </div>
</template>

<script>
import { computed, reactive, toRefs } from 'vue'
export default {
  setup() {
    let state = reactive({
      carts: [
        { id: 1, name: '小米', price: 1, num: 1 },
        { id: 2, name: '大米', price: 1, num: 1 }
      ],
      total: 0
    })

    let totalPrice = computed({
      get() {
        return state.carts.reduce((p, { price, num }) => {
          p += price * num
          return p
        }, 0)
      },
      // 求和方式2:
      set(v) {
        if (v.n) {
          state.carts[v.index].num += v.n
        }
      }
    })

    // 求和方式1:
    const setNum = (index, n) => {
      state.carts[index].num += n
      if (state.carts[index].num <= 1) state.carts[index].num = 1
      if (state.carts[index].num >= 10) state.carts[index].num = 10
    }

    return { ...toRefs(state), totalPrice, setNum }
  }
}
</script>

<style lang="scss" scoped></style>

在这里插入图片描述

2. watch侦听器属性

  • watchEffect 是自动去根据方法中的调用来确定依赖项。
  • watch 是手动指定依赖项 – 用它可能会多一些。

2.1 watchEffect

<template>
  <div>
    <h3>{{ num }}</h3>
    <!-- 输入的内容发生变化时,控制台不会打印,因为 name 不是侦听器的依赖项 -->
    <input type="text" v-model="name" />
    <button @click="num++">+++</button>
    <!-- <button @click="stop">停止侦听</button> -->
  </div>
</template>

<script>
// watchEffect 自动去根据方法中的调用来确定依赖项
// watch 手动指定依赖项  -- 用它可能会多一些
import { ref, watch, watchEffect } from 'vue'
export default {
  setup() {
    const num = ref(100)

    const name = ref('')

    // 侦听,它必须要有依赖项
    // 它在初始化时,会主动执行1次,如果没有依赖项,则不会再次执行
    // watchEffect(() => {
    //   // 这里只会在初始时打印一次222
    //   console.log(222)
    // })

    watchEffect(() => {
      // 此时它的依赖项为 num变量,如果它有改变,则回调函数会自动触发
      // 它的依赖项可以是1到N个
      console.log(222, num.value)
    })

    return { num,name }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

watchEffect 的返回值:

<template>
  <div>
    <h3>{{ num }}</h3>
    <button @click="num++">+++</button>
    <button @click="stop">停止侦听</button>
  </div>
</template>

<script>
// watchEffect 自动去根据方法中的调用来确定依赖项
// watch 手动指定依赖项  -- 用它可能会多一些
import { ref, watch, watchEffect } from 'vue'
export default {
  setup() {
    const num = ref(100)

    const stopHandle = watchEffect(() => {
      console.log(222, num.value)
    })

    const stop = () => stopHandle()

    return { num, stop }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

watchEffect 的 onCleanup 回调参数:

watchEffect 还有一个回调参数,此参数它也是一个函数,作用是清理副作用。

<template>
  <div>
    <h3>{{ num }}</h3>
    <button @click="num++">+++</button>
    <button @click="stop">停止侦听</button>
  </div>
</template>

<script>
// watchEffect 自动去根据方法中的调用来确定依赖项
// watch 手动指定依赖项  -- 用它可能会多一些
import { ref, watch, watchEffect } from 'vue'
export default {
  setup() {
    const num = ref(100)
    let timer

    // 此方法它还有一个回调参数,此参数它也是一个函数,作用,清理副作用
    const stopHandle = watchEffect(
      onCleanup => {
        console.log(num.value)
        // console.log(222, num.value, name.value)
        onCleanup(() => {
          console.log('清理上一次的处理')
          timer && clearTimeout(timer)
        })
        timer = setTimeout(() => {
          console.log('输出的')
        }, 1000)
      },
      {
        // flush?: 'pre' | 'post' | 'sync';
        // pre 模板渲染之前触发
        // post 模板渲染之后触发
        // sync 和模板渲染同步来触发
        // 默认为 pres
        flush: 'pre'
      }
    )

    const stop = () => stopHandle()

    return { num, stop }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

2.2 watch

监听一个变量值的变化:

<template>
  <div>
    <div>{{ num }} <button @click="num++">+++</button></div>
    <input type="text" v-model="name" />
  </div>
</template>

<script>

import { ref, watch } from 'vue'
export default {
  setup() {
    const num = ref(100)
    const name = ref('')

    // 监听num变量它的变化,如果有变化,则触发
    watch(
      num,
      (newValue, oldValue) => {
        console.log(newValue)
      },
      {
        // 初始化执行1次,默认为false
        immediate: false
      }
    )

    return { num, name }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

监听多个变量值的变化:

<template>
  <div>
    <div>{{ num }} <button @click="num++">+++</button></div>
    <input type="text" v-model="name" />
  </div>
</template>

<script>
import { ref, watch } from 'vue'
export default {
  setup() {
    const num = ref(100)
    const name = ref('')

    // 以数组的方式来写,它可以监听多个变量的值的变化,回调参数为一个数组
    watch([num, name], (nArr, oArr) => {
      console.log(nArr)
    })
    // 在工作中,通常只关心新的值,所以只会写一个参数,就像下面这样
    // watch([num, name], ([numValue, nameValue]) => {
    //   console.log(numValue, nameValue)
    // })

    return { num, name }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

监听对象中具体的值:

<template>
  <div>
    <input type="text" v-model="user.name" />
  </div>
</template>

<script>
import { ref, watch } from 'vue'
export default {
  setup() {
    const user = ref({ id: 1, name: '张三' })

    // 目前对于ref定义的引用类型,默认无法监听
    // watch(user, (n, o) => {
    //   console.log(n)
    // })

    // 但是可以指定监听对象中具体的值
    watch(
      // 'obj.name'(n,o){}
      () => user.value.name,
      (n, o) => {
        console.log(n)
      }
    )

    return { user }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

监听ref的引用对象(添加参数3):

<template>
  <div>
    <input type="text" v-model="user.name" />
  </div>
</template>

<script>
import { ref, watch } from 'vue'
export default {
  setup() {
    const user = ref({ id: 1, name: '张三' })

    // 监听ref的引用对象 添加参数3
    watch(user, (n, o) => {
      console.log(n)
    },{
      deep:true
    })

    return { user }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

监听 reactive 定义的响应变量:

<template>
  <div>
    <input type="text" v-model="user.name" />
  </div>
</template>

<script>
import { reactive, watch } from 'vue'
export default {
  setup() {
    const user = reactive({ id: 1, name: '张三' })

    // 监听的是一个reactive定义的响应变量,它默认就可以进行深层监听
    // 所以在工作中,如果你定义的值它是一个引用类型,建议使用reactive,基本类型用ref
    const stop = watch(user, (n, o) => {
      console.log(n)
    })

    return { user, stop }
  }
}
</script>

<style lang="scss" scoped>

</style>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/26996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

精华推荐 | 【深入浅出RocketMQ原理及实战】「底层原理挖掘系列」透彻剖析贯穿RocketMQ的存储系统的实现原理和持久化机制

RocketMQ的发展历史 RocketMQ是一个统一消息引擎、轻量级数据处理平台。RocketMQ是一款阿里巴巴开源的消息中间件。 2016 年 11 月 28 日&#xff0c;阿里巴巴向 广西党性培训 Apache 软件基金会捐赠RocketMQ&#xff0c;成为 Apache 孵化项目。 2017 年 9 月 25 日&#xff0…

webpack安装与基础

概念 webpack是一个前端打包工具用它来处理现代前端错综复杂的依赖关系&#xff08;A插件需要B插件B插件有D插件 F插件需要A插件&#xff09;生成浏览器可以识别静态资源Vue 前期脚手架就是用webpack制作&#xff08;Vue 开始推荐vite构建工具&#xff08;更快&#xff09;&am…

[UE][UE5]Gameplay框架,Actor,pawn,playerController(玩家控制器),Character(角色)之间的关系

[UE][UE5]Gameplay框架,actor,pawn,playerController,Character之间的关系Actor,pawn,playerController(玩家控制器),Character(角色)之间的关系Actor&#xff1a;pawn&#xff1a;character&#xff1a;控制器&#xff08;Controller&#xff09;&#xff1a;playerController…

sqlServer如何实现分页查询

sqlServer的分页查询和mysql语句不一样&#xff0c;有三种实现方式。分别是&#xff1a;offset /fetch next、利用max&#xff08;主键&#xff09;、利用row_number关键字 一、offset /fetch next关键字 2012版本及以上才有&#xff0c;SQL server公司升级后推出的新方法。 …

Shiro前后端分离流程

1.自定义filter 拦截所有携带token的请求&#xff0c; 调用自定义realm&#xff0c;判断token是否正确&#xff0c;不正确realm抛出异常&#xff0c;在filter中被捕获&#xff0c;重定向至token不正确界面 重写了三个方法&#xff1a; 1》isAccessAllowed&#xff1a;如果带…

有一个项目管理软件,名字叫8Manage PM!

优秀的软件工具在项目管理中起到极为重要的作用。8Manage PM项目管理软件由高亚科技自主研发&#xff0c;为项目工作提供项目功能、业务功能、服务功能和工具&#xff0c;有力推动项目成功。 8Manage软件项目功能包括完整性管理、需求管理、计划和执行、资源管理、工作量&…

锐捷BGP基础配置

目录 ​编辑 配置IBGP邻居 配置EBGP邻居 BGP其它配置 配置IBGP邻居 R2、R3、R4底层IGP互通&#xff0c;此处IGP互通配置不做介绍 R2与R4通过Loop0建立IBGP邻居&#xff0c;R3与R4通过Loop0建立IBGP邻居 R4充当反射器&#xff0c;R2和R3作为客户端&#xff08;通过反射可以将…

Vue中设置背景图片和透明度

如果文章对你有帮助欢迎【关注❤️❤️❤️点赞&#x1f44d;&#x1f44d;&#x1f44d;收藏⭐⭐⭐】一键三连&#xff01;一起努力&#xff01; 今天来为我自己的项目设置一个好看的登录页面之前是这样的&#xff1a; 乍一看感觉还行&#xff0c;越看越难受&#xff0c;弄一…

Nodejs http模块常用方法

视频链接&#xff1a;黑马程序员Node.js全套入门教程 文章目录http模块1 什么是http模块2 进一步理解http的作用3 服务器相关的概念3.1 IP地址3.2 域名和域名服务器3.3 端口号4 创建简单的web服务器1 步骤2 代码实现3 req请求对象4 res响应对象5 解决中文乱码问题5 简单路由效果…

《Java并发编程之美》读书笔记——ThreadLocalRandom类原理剖析

文章目录1.Random类的局限性2.ThreadLocalRandom3.源码分析Unsafe机制current()方法int nextInt(int bound)方法1.Random类的局限性 在JDK之前包括现在&#xff0c;java.util.Random都是使用比较广泛的随机数生成工具类。 下面我们先来看一下Random的使用方法。 // 创建一个…

kubelet源码 删除pod(一)

k8s版本为1.25.3版本 kubectl delete pod name当删除一个pod的时候会经历一下流程 kubectl会发pod消息给api server。apiserver将信息存入etcd&#xff0c;然后返回确认信息。apiserver开始反馈etcd中pod对象的变化&#xff0c;其他组件使用watch机制跟踪apiserver上的变动。…

行业生态重塑中,新氧如何逆风翻盘

美东时间11月18日盘前&#xff0c;中国互联网医美第一股新氧科技发布2022财年第三季度的业绩报告&#xff0c;业绩符合其业绩指引。 据新氧该季度财报显示&#xff0c;第三季度实现非美国通用会计准则归属于新氧科技的净利润990万元人民币&#xff08;140万美元&#xff09;。…

表格分组标签:表格行分组中的隐藏功能

在程序员的认知中&#xff0c;表格中存在行分组标签&#xff0c;也就是thead&#xff0c;tbody&#xff0c;tfoot三个行分组标签。也许你会认为我在这里还是为大家继续讲解thead&#xff0c;tbody&#xff0c;tfoot三个标签&#xff0c;那就大错特错了 今天除了要讲解他的基础作…

栈和队列

声明&#xff1a;本文主要作为作者的复习笔记&#xff0c;由于作者水平有限&#xff0c;难免有错误和不准确之处&#xff0c;欢迎读者批评指正。 目录快捷跳转线性表接口两个常用子类什么时候选择ArrayList&#xff0c;什么时候选择LinkedList?栈和队列的关系栈栈的实现根据使…

ASP.NET Core教程-Exception(异常和错误处理)

更新记录 转载请注明出处&#xff1a; 2022年11月22日 发布。 2022年11月20日 从笔记迁移到博客。 错误处理基础 错误处理说明 ASP.NET Core中的错误处理分为&#xff1a; ​ 局部Controller中处理错误 ​ 在Controller中定义错误代码和转到错误界面即可 ​ 全局应用中设置错误…

vue.js毕业设计,基于vue.js前后端分离教室预约系统设计与实现(H5移动项目)

功能模块 【后台管理功能模块】 系统设置&#xff1a;设置关于我们、联系我们、加入我们、法律声明 广告管理&#xff1a;设置小程序首页轮播图广告和链接 留言列表&#xff1a;所有用户留言信息列表&#xff0c;支持删除 会员列表&#xff1a;查看所有注册会员信息&#xff0c…

[附源码]计算机毕业设计JAVA家政管理系统

[附源码]计算机毕业设计JAVA家政管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis M…

Spring Boot中Node.js的下载与Vue CLI在IDEA中的部署及使用(图文解释 简单易懂)

仍有问题可点赞关注收藏后在评论区留言~~~ 一、Node.js与npm的下载 在使用Vue CLI(Vue脚手架)搭建前端系统的时候&#xff0c;因为需要用到npm安装Vue CLI&#xff0c;而npm是集成在Node.js中的&#xff0c;所以需要首先安装Node.js Node.js官网 下载过程很简单&#xff0c;…

数据库错误知识集2

Oracle数据库中最常见的索引类型是b-tree索引&#xff0c;也就是B-树索引&#xff0c;以其同名的计算科学结构命名。 union与union all的区别&#xff08;摘&#xff09;&#xff1a; ①对重复结果的处理&#xff1a;union会去掉重复记录&#xff0c;union all不会&#xff1b;…

转铁蛋白偶联糖(单糖/多糖),(Transferrin)TF-PEG-Dextran葡聚糖/Lysozyme溶菌酶

产品名称&#xff1a;转铁蛋白-聚乙二醇-葡聚糖 英文名称&#xff1a;TF-PEG-Dextran 纯度&#xff1a;95% 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 外观:固体或粘性液体&#xff0c;取决于分子量 PEG分子量可选&#xff1a;350、550、750、1k、2k、34k、5k…