Vue3(二)计算属性Computed,监视属性watch,watchEffect,标签的ref属性,propos属性,生命周期,自定义hook

文章目录

  • 一 、计算属性
    • 1. 简写
    • 2. 完整写法
  • 二、监视watch
    • 1. 监视【ref】定义的【基本类型】数据
    • 2. 监视【ref】定义的【对象类型】数据
    • 3. 监视【reactive】定义的【对象类型】数据
    • 4. 监视【ref】或【reactive】定义的【对象类型】数据中的某个属性
    • 5. 监视多个数据
    • 总结
  • 三、watchEffect
  • 四、标签的ref属性
  • 五、Propos
    • 1.子组件接收,接收并保存
    • 2. 限制接收的类型,限制必要性
    • 3. 子组件给默认值
  • 六、生命周期
  • 七、自定义Hook

一 、计算属性

computed:根据已有数据计算出新数据(和Vue2中的computed作用一致).
在这里插入图片描述
还是那个案例,当输入框里的内容变化时,全名跟着修改。

1. 简写

语法:computed(()=>{....})

// 引入computed 
import { ref, computed } from "vue"

let firstName = ref("zhang")
let lastName = ref("san")

// 这么定义的fullName是一个计算属性,且是只读的(也就是简写形式)
let fullName = computed(() => {
  return firstName.value + "-" + lastName.value
})

2. 完整写法

语法:computed({ get() {...}, set(val) {... }, })

给按钮绑定事件,修改姓名

 <button @click="changeFullName">全名改为:li-si</button>

在这里插入图片描述
代码:

let fullName = computed({
  get() {
    return firstName.value + "-" + lastName.value
  },
  set(val) {
    const [str1, str2] = val.split("-")
    firstName.value = str1
    lastName.value = str2
  },
})

二、监视watch

  • 作用:监视数据的变化(和Vue2中的watch作用一致)
  • 特点:Vue3中的watch只能监视以下四种数据
  1. ref定义的数据(基本数据类型,对象类型)。
  2. reactive定义的数据。
  3. 对象类型数据里的某个属性。
  4. 一个包含上述内容的数组。

1. 监视【ref】定义的【基本类型】数据

语法watch(监视对象,回调函数)
监视对象直接写变量名即可,监视的是其value值的改变。

import { ref, watch } from "vue"
// 数据
let sum = ref(0)
// 方法
function changeSum() {
  sum.value += 1
}
// 监视 watch(监视对象,回调函数);
const stopWatch = watch(sum, (newValue, oldValue) => {
  if (newValue > 10) {
    stopWatch()
  }
})

如果想停止监视,则接收watch的返回值,watch返回的值是一个函数stopWatch,调用该函数就停止监视sum

2. 监视【ref】定义的【对象类型】数据

在这里插入图片描述

import { ref, watch } from "vue"
// 数据
let person = ref({
  name: "tom",
  age: 18,
})
function changeName() {
  person.value.name += "~"
}
function changeAge() {
  person.value.age += 1
}
function changePerson() {
  person.value = { name: "李四", age: 50 }
}
watch(person, (newValue, oldValue) => {
  console.log("person变化", newValue, oldValue)
})

点击这三个按钮发现,只有当点击修改整个人时,watch监视才起作用。因为对于ref定义的对象数据类型,watch监视的是地址值。若想监视对象里面的值,则开启深度监视

watch(
  person,
  (newValue, oldValue) => {
    console.log("person变化", newValue, oldValue)
  },
  { deep: true } // 也可配置 immediate: true
)

另外,点击前两个按钮发现newValueoldValue是同一个值。点击修改整个人时,两个值才不一样。
在这里插入图片描述
因为修改名字和年龄只是修改了对象的属性,而修改整个人是修改了对象的地址。地址不一样了,newValueoldValue值也就不一样了。

总结:

  1. 语法:watch(监视对象,回调函数,{配置对象deep、immediate等等.....})
  2. 监视【ref】定义的【对象类型】数据时,监视的是对象的地址值,若想监视对象内部属性的变化,需要手动开启深度监视
  3. 若修改的是ref定义的对象中的属性,newValueoldValue 都是新值,因为它们是同一个对象。
    若修改整个ref定义的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。

3. 监视【reactive】定义的【对象类型】数据

把上边的代码改了改:
在这里插入图片描述
点击三个按钮,控制台打印的结果:
在这里插入图片描述

  1. 不用写deep:true,默认开启了深度监听。并且这个深度监听是不可关闭的。
  2. 注意到这三行打印的结果里newValueoldValue都是一样的值,这是因为person对象的地址始终没有发生变化。

总结:

监视reactive定义的【对象类型】数据时,默认开启了深度监视且无法关闭。

4. 监视【ref】或【reactive】定义的【对象类型】数据中的某个属性

上边都是监视一个对象,这里监视对象的某属性。
在这里插入图片描述

let person = reactive({
  name: "张三",
  age: 18,
  car: {
    c1: "奔驰",
    c2: "宝马",
  },
})
// 方法
function changeName() {
  person.name += "~"
}
function changeAge() {
  person.age += 1
}
function changeC1() {
  person.car.c1 = "奥迪"
}
function changeC2() {
  person.car.c2 = "大众"
}
function changeCar() {
// reactive对象里属性对象可以这样改
  person.car = { c1: "雅迪", c2: "爱玛" }
}

只监视对象里的某一个基本数据类型age

// 第一个参数写成函数的形式,指定监听的属性;
// 如果写的是person,则无论点击哪个按钮,都会被监听到
watch(() => person.age,  (newValue, oldValue) => {
    console.log("age改变", newValue, oldValue) // age改变 19 18
  }
)

监视对象里的对象类型属性car

watch(
  () => person.car,
  (newValue, oldValue) => {
    console.log("person.car变化了", newValue, oldValue)
  },
  { deep: true }
)

不写deep:true,则监视的是car这个对象,当其地址发生变化时才会执行console.log打印(也就是不会默认开始深度监听)。
deep:true,则也监视到car内部的属性c1,c2。属性或对象发生变化都会打印
在这里插入图片描述

总结:

  1. 监视响应式对象中的某个属性,且该属性是基本类型的,要写成函数式
  2. 监视响应式对象中的某个属性,且该属性是对象类型的,可以直接写,也能写函数,更推荐写函数
  3. 监视reactive响应式对象中的某个属性,且该属性是对象类型的(car),不会默认开始深度监听

5. 监视多个数据

还是4中的案例,需求是监视人的姓名和车

watch(
  [() => person.name, person.car],
  (newValue, oldValue) => {
    console.log("person.car变化了", newValue, oldValue)
  },
  { deep: true }
)

总结

  1. 对于ref定义的基本数据类型,监视的是其value
  2. 对于ref定义的对象数据类型,监视的是对象的地址值,若要监视对象里的属性,需要手动开启深度监视
  3. 对于reactive定义的对象数据类型,默认开启了深度监视
  4. 对于refreactive对象类型里的某个属性,如果是该属性是对象(car),监视的是其地址值,不会默认开始深度监视

三、watchEffect

watch对比watchEffect
(1) 都能监听响应式数据的变化,不同的是监听数据变化的方式不同
(2) watch:要明确指出监视的数据
(3) watchEffect:不用明确指出监视的数据(函数中用到哪些属性,就监视哪些属性)

在这里插入图片描述

import { ref, watch, watchEffect } from "vue"
// 数据
let temp = ref(0)
let height = ref(0)

// 方法
function changeTemp() {
  temp.value += 10
}
function changeHeight() {
  height.value += 10
}

// 用watch实现
watch([temp, height], (val) => {
  // 从value中获取最新的temp值、height值
  let [newTemp, newHeight] = val
  if (newTemp >= 50 || newHeight >= 20) {
    console.log("发送请求")
  }
})

// 用watchEffect
watchEffect(() => {
  if (temp.value >= 50 || height.value >= 20) {
    console.log("发请求")
  }
})

四、标签的ref属性

ref用于给标签打标识。
1. 用在普通DOM标签上

<template>
  <div class="person">
    <h2 ref="title">hello</h2>
    <h2 ref="title2">hello again</h2>
    <h2>world</h2>
    <button @click="showTitle">获取所有hello</button>
  </div>
</template>

<script lang="ts" setup name="Person">
import { ref } from "vue"
// 似乎是解构赋值,这里接收的变量名需要和ref定义的一致
let title = ref()
let title2 = ref()
// let title1 = ref()  这样打印出title1是undefined
function showTitle() {
  console.log('ref', ref());
  console.log('title', title.value)
  console.log('title2', title2.value)
}
</script>

变量名需要的ref的名称一致,否则undefined
在这里插入图片描述
(这个ref打印出来也不知道是什么东西,看不懂,有点子神奇了)

2. 用在组件标签上
(竟然可以实现子组件给父组件传值)

父组件

<template>
  <Person ref="ren" />
  <button @click="showInfo">点击获取组件信息</button>
</template>

<script lang="ts" setup name="APP">
import Person from "./components/Person.vue"
import { ref } from "vue"
let ren = ref()
function showInfo() {
  console.log(ren.value.name)
  console.log(ren.value.age)
}
</script>

子组件

// 不引入也行,definexxx都是一些宏函数,会自动引入
import { defineExpose } from "vue"
let name = "tom"
let age = 18
// 使用defineExpose将组件中的数据交给外部
defineExpose({ name, age })

五、Propos

propos用于父组件向子组件传值

父组件的数据:

import Person from './components/Person.vue'
import { reactive } from 'vue';
import { Persons } from './type';
// 父组件
let persons = reactive<Persons>([
  { id: '12345', name: 'tom', age: 18 },
  { id: '123456', name: 'jerry', age: 18 },
  { id: '1234567', name: 'lucy', age: 18 }
])

1.子组件接收,接收并保存

<!--父组件-->
 <Person :list=persons />
<!--子组件-->
<script>
	// 只接收
	defineProps(['list'])
	console.log(list[0]); // 没保存,直接读取会提示“找不到list”
	
	// 接收并保存
	let x = defineProps(['list'])
	console.log(x.list[0]); // Proxy(Object) {id: '12345', name: 'tom', age: 18}
</script>

2. 限制接收的类型,限制必要性

<!--父组件-->
<Person :list=persons />
 <Person :list="5" />  <!-- 不是Person类型会报错 -->
 <Person />            <!-- 没有给子组件传递数据也会报错,解决方法:添加`?` -->
  
<!--子组件-->
<script>
	// 接收+限制类型,只能接收Persons类型的数据
	defineProps<{ list: Persons }>()
</script>

当添加一个?之后,则父组件可传可不传。不传递也不会报错

 defineProps<{ list?: Persons }>()

3. 子组件给默认值

import { withDefaults } from 'vue';
// 接收+限制类型+限制必要性+指定默认值
withDefaults(defineProps<{ list?: Persons }>(), {
  list: () => [{ id: '默认', name: '默认', age: 10 }]
})

六、生命周期

回顾vue2的生命周期,vue2(三) vue生命周期

Vue2的生命周期

创建阶段:beforeCreatecreated

挂载阶段:beforeMountmounted

更新阶段:beforeUpdateupdated

销毁阶段:beforeDestroydestroyed

Vue3的生命周期

创建阶段:setup

挂载阶段:onBeforeMountonMounted

更新阶段:onBeforeUpdateonUpdated

卸载阶段:onBeforeUnmountonUnmounted

常用:onMounted(挂载完毕),onUpdated(更新完毕),onBeforeUnmount(卸载之前)

解释一下这个创建阶段,用代码表示就是:

<script lang="ts" setup name="Person">
import { onBeforeMount,  onMounted,  } from 'vue';

console.log('创建');

onBeforeMount(() => {
  console.log('挂载之前');
})

onMounted(() => {
  console.log('挂载完毕');
})
</script>

在这里插入图片描述

七、自定义Hook

一直在说vue3是组合式API,每个功能的数据,方法都放在一起。目前在<script>标签里还是上边写一堆功能的数据,下面写一堆功能的方法,和vue2没啥区别了。
hook其实就是将各个功能的数据和方法单独封装到一个hook文件中。以后修改功能就直接去这个hook文件里改就好了。

  • 什么是hook?—— 本质是一个函数,把setup函数中使用的Composition API进行了封装,类似于vue2.x中的mixin
  • 自定义hook的优势:复用代码, 让setup中的逻辑更清楚易懂。

现在页面上有两个功能:
在这里插入图片描述
src/hook/useSum.ts

import {  ref, computed } from 'vue'
export default function(){
// 功能一的数据
  let sum = ref(0)
// 功能一的函数
  let bigSum = computed(() => {
      return 10 * sum.value
  })
  function addSum() {
      sum.value += 1
   }
  return {sum,addSum,bigSum}
}

src/hook/useDog.ts

import { reactive, ref, computed } from 'vue'
import axios from 'axios';
export default function(){
// 功能二的数据
let dogList = reactive<string[]>([])
// 功能二的函数
async function getDog() {
  try {
    // 发请求
    let { data } = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')
    // 维护数据
    dogList.push(data.message)
  } catch (error) {
    // 处理错误
    console.log(error.message)
  }
}
return {dogList,getDog}
}

组件内:
src/components/Person.vue

<template>
  <div class="person">
    <h2> 求和为{{ sum }},扩大十倍后{{ bigSum }}</h2>
    <button @click="addSum">sum+1</button>
    <br>
    <br>
    <img v-for="(u, index) in dogList" :key="index" :src="(u as string)">
    <br>
    <button @click="getDog">再来一只狗</button>
  </div>
</template>

<script lang="ts" setup name="Person">
// 1. 引入
import useDog from '../hook/useDog.ts'
import useSum from '../hook/useSum.ts'
// 2. 解构获取信息
const { dogList, getDog } = useDog()
const { sum, addSum, bigSum } = useSum()
</script>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

html+css(如何用css做出京东页面,静态版)

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>京东</title><link rel"stylesheet&q…

基于Es和智普AI实现的语义检索

1、什么是语义检索 语义检索是一种利用自然语言处理&#xff08;NLP&#xff09;和人工智能&#xff08;AI&#xff09;技术来理解搜索查询的语义&#xff0c;以提供更准确和相关搜索结果的搜索技术&#xff0c;语义检索是一项突破性的技术&#xff0c;旨在通过深入理解单词和…

知识库管理系统的未来趋势:从单一平台到生态系统

在数字化浪潮的推动下&#xff0c;知识库管理系统&#xff08;Knowledge Base Management System, KBMS&#xff09;正逐步从传统的单一平台向更加开放、灵活、智能的生态系统转变。这一转变不仅体现了技术进步的必然结果&#xff0c;也深刻反映了市场需求的变化。本文将分析随…

neo4j节点关联路径的表示、节点的增删改查

目录 核心概念节点的增删改查&#xff08;1&#xff09;增&#xff08;2&#xff09;查&#xff08;3&#xff09;删&#xff08;4&#xff09;改 neo4j文档&#xff1a;https://neo4j.com/docs/ https://neo4j.com/docs/cypher-manual/current/introduction/ 核心概念 节点 ne…

如何将Excel表格嵌入Web网页在线预览、编辑并保存到自己服务器上?

猿大师办公助手作为一款专业级的网页编辑Office方案&#xff0c;不仅可以把微软Office、金山WPS和永中Office的Word文档内嵌到浏览器网页中实现在线预览、编辑保存等操作&#xff0c;还可以把微软Office、金山WPS和永中Office的Excel表格实现网页中在线预览、编辑并保存到服务器…

C++的哲学思想

C的哲学思想 文章目录 C的哲学思想&#x1f4a1;前言&#x1f4a1;C的哲学思想☁️C底层不应该基于任何其他语言&#xff08;汇编语言除外&#xff09;☁️只为使用的东西付费&#xff08;不需要为没有使用到的语言特性付费&#xff09;☁️以低成本提供高级抽象&#xff08;更…

在云渲染中3D工程文件安全性怎么样?

在云渲染中&#xff0c;3D工程文件的安全性是用户最关心的问题之一。随着企业对数据保护意识的增强&#xff0c;云渲染平台采取了严格的安全措施和加密技术&#xff0c;以确保用户数据的安全性和隐私性。 云渲染平台为了保障用户数据的安全&#xff0c;采取了多层次的安全措施。…

【VUE3.0】动手做一套像素风的前端UI组件库---Button

目录 引言做之前先仔细看看UI设计稿解读一下都有哪些元素&#xff1a;素材补充 代码编写1. 按钮四周边框2. 默认状态下按钮颜色立体效果3. 鼠标移入聚焦4. 模拟鼠标点击效果 组件封装1. 按类型设置颜色2. 设置按钮禁用状态3. 处理一个bug4. 看下整体组件效果5. 组件完整代码6. …

vue.js 展示一个树形结构的数据视图,并禁用其中默认选中的节点

功能描述 展示树形结构&#xff1a; 使用 Element UI 的 <el-tree> 组件展示树形结构数据。数据由 content 数组提供&#xff0c;树形结构包含了嵌套的节点及其子节点。 默认选中节点&#xff1a; 使用 defaultCheckedKeys 属性指定默认选中的节点。这些节点在树形结构渲…

求职Leetcode题目(11)

1.最长连续序列 解题思路: 方法一&#xff1a; • 首先对数组进行排序&#xff0c;这样我们可以直接比较相邻的元素是否连续。• 使用一个变量 cur_cnt 来记录当前的连续序列长度。• 遍历排序后的数组&#xff1a; 如果当前元素与前一个元素相等&#xff0c;则跳过&#xf…

Debian安装mysql遇到的问题解决及yum源配置

文章目录 一、安装mysql遇到的问题解决二、Debain系统mysql8.0的安装以及远程连接三、彻底卸载软件四、Python 操作 mysql五、debian软件源source.list文件格式说明1. 第一部分2. 第二部分3. 第三部分4. 第四部分5. 关于源的混用问题6. 按需修改自己的sources.list7. 更新软件包…

python爬虫案例——腾讯网新闻标题(异步加载网站数据抓取,post请求)(6)

文章目录 前言1、任务目标2、抓取流程2.1 分析网页2.2 编写代码2.3 思路分析前言 本篇案例主要讲解异步加载网站如何分析网页接口,以及如何观察post请求URL的参数,网站数据并不难抓取,主要是将要抓取的数据接口分析清楚,才能根据需求编写想要的代码。 1、任务目标 目标网…

LabVIEW提高开发效率技巧----使用LabVIEW工具

LabVIEW为开发者提供了多种工具和功能&#xff0c;不仅提高工作效率&#xff0c;还能确保项目的质量和可维护性。以下详细介绍几种关键工具&#xff0c;并结合实际案例说明它们的应用。 1. VI Analyzer&#xff1a;自动检查代码质量 VI Analyzer 是LabVIEW提供的一款强大的工…

Java — LeetCode 面试经典150题(一)

双指针 125.验证回文串 题目 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s&#xff0c;如果它是 回文串 &#xff0c;返回…

验收测试:从需求到交付的全程把控!

在软件开发过程中&#xff0c;验收测试是一个至关重要的环节。它不仅是对软件质量的把关&#xff0c;也是对整个项目周期的全程把控。从需求分析到最终的软件交付&#xff0c;验收测试都需要严格进行&#xff0c;以确保软件能够符合预期的质量和性能要求。 一、需求分析阶段 在…

0-1开发自己的obsidian plugin DAY 1

官网教程有点mismatch&#xff0c;而且从0-100跨度较大&#xff0c;&#x1f4dd;记录一下自己的踩坑过程 首先&#xff0c;官网给的example里只有main.ts&#xff0c;需要自己编译成main.js 在视频教程&#xff08;https://www.youtube.com/watch?v9lA-jaMNS0k&#xff09;里…

K8S服务发布

一 、服务发布方式对比 二者主要区别在于&#xff1a; 1. 部署复杂性&#xff1a;传统的服务发布方式通常涉及手动配置 和管理服务器、网络设置、负载均衡等&#xff0c;过程相对复 杂且容易出错。相比之下&#xff0c;Kubernetes服务发布方式 通过使用容器编排和自动化部署工…

大数据新视界 --大数据大厂之 Reactjs 在大数据应用开发中的优势与实践

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

虚幻引擎的射线检测/射线追踪

射线检测在 FPS/TPS 游戏中被广泛应用 什么是射线检测? 两个点行成一条线 , 射线检测是从一个起始点发出一条到终点的射线 , 如果射线命中一个游戏对象&#xff0c;就可以获取到对象命中时的 位置、距离、角度、是否命中、骨骼 等非常多的信息 , 这些信息在射击游戏中至关重…

付费电表系统的通用功能和应用过程参考模型(上)

Generic functions and application process reference model for the Payment Metering System 付费电表系统的通用功能和应用过程参考模型 1. 参考模型 Reference model 1.1 在参考模型中的符号的说明 Legend of symbols used in the reference model 功能框 (function bo…