(01)vue前端复习第一章——Vue的底子开始

[复制链接]
发表于 2024-11-14 02:10:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次

前言
一、vue工程的创建
二、Vue3的核心语法
2.1 【OptionsAPI 与 CompositionAPI】
2.1.1Options API 的弊端
2.1.2 组合式API(Composition API)
2.2 拉开序幕的setup
2.2.1setup 概述
2.3【ref 创建:基本类型的响应式数据】
2.4. 【reactive 创建:对象类型的响应式数据】
2.5. 【ref 创建:对象类型的响应式数据】
2.6. 【ref 对比 reactive】
2.7. 【toRefs 与 toRef】
2.8. 【computed】
说明
与 watch 的区别
2.9.【watch】
* 环境一
* 环境二
* 环境三
* 环境四
环境五 监视上述多个数据信息
2.10. 【watchEffect】
watchEffect 与 watch 的区别
特点
2.11. 【标签的 ref 属性】
示例 1:访问普通 DOM 节点
示例 2:访问子组件实例
子组件 ChildComponent.vue
参考文献


前言

本教程通过搭建一个简单项目,资助读者快速入门Vue3项目实战,把握Vue3、TS、Element Plus、axios等技术栈。
Vue 3是Vue.js的最新主要版本,它带来了许多改进和新特性,包罗但不限于:
性能提升:Vue 3提供了更快的渲染速度和更低的内存利用率。
Composition API:引入了一个新的API,答应更灵活的代码组织和复用,特别得当构建大型应用。
更好的TypeScript支持:Vue 3从头开始就思量了TypeScript的支持,使得利用TypeScript开辟Vue应用更加顺畅。
更小的体积:通过优化和树摇(tree-shaking),Vue 3的体积更小,使得加载时间更短。
一、vue工程的创建

Vue 3项目可以通过Vue CLI或Vite这两种方式创建。Vue CLI是Vue的官方命令行工具,而Vite是一个当代化的前端构建工具,提供了更快的开辟服务器启动和热重载

 利用Vue CLI创建项目:
起首,确保你安装了最新版的Vue CLI。如果尚未安装,可以通过npm安装:
  1. npm install -g @vue/cli
复制代码
然后,创建一个新的Vue 3项目: 
  1. vue create my-vue-app
复制代码
在创建过程中,CLI会让你选择预设设置。为了利用Vue 3,你可以选择“Manually select features”来自界说功能,确保选择了“Vue 3”选项。 
利用Vite创建项目:
Vite是一个建立在当代Web标准之上的新一代前端构建工具。利用Vite创建Vue 3项目,可以得到极速的服务启动和模块热更新。安装Vite并创建一个新项目:
  1. ## 1.创建命令
  2. npm create vue@latest
  3. ## 2.具体配置
  4. ## 配置项目名称
  5. √ Project name: vue3_test
  6. ## 是否添加TypeScript支持
  7. √ Add TypeScript?  Yes
  8. ## 是否添加JSX支持
  9. √ Add JSX Support?  No
  10. ## 是否添加路由环境
  11. √ Add Vue Router for Single Page Application development?  No
  12. ## 是否添加pinia环境
  13. √ Add Pinia for state management?  No
  14. ## 是否添加单元测试
  15. √ Add Vitest for Unit Testing?  No
  16. ## 是否添加端到端测试方案
  17. √ Add an End-to-End Testing Solution? » No
  18. ## 是否添加ESLint语法检查
  19. √ Add ESLint for code quality?  Yes
  20. ## 是否添加Prettiert代码格式化
  21. √ Add Prettier for code formatting?  No
复制代码
手动编写一个App组件
  1. <template>
  2.   <div class="app">
  3.     <h1>你好啊!</h1>
  4.   </div>
  5. </template>
  6. <script lang="ts">
  7.   export default {
  8.     name:'App' //组件名
  9.   }
  10. </script>
  11. <style>
  12.   .app {
  13.     background-color: #ddd;
  14.     box-shadow: 0 0 10px;
  15.     border-radius: 10px;
  16.     padding: 20px;
  17.   }
  18. </style>
复制代码
总结:


  • Vite 项目中,index.html 是项目标入口文件,在项目最外层。
  • 加载index.html后,Vite 剖析 <script type="module" src="xxx"> 指向的JavaScript。
  • Vue3中是通过 createApp 函数创建一个应用实例。
二、Vue3的核心语法

2.1 【OptionsAPI 与 CompositionAPI】



  • Vue2的API计划是Options(设置)风格的。
  • Vue3的API计划是Composition(组合)风格的。
2.1.1Options API 的弊端

Options类型的 API,数据、方法、计算属性等,是分散在:data、methods、computed中的,若想新增或者修改一个需求,就必要分别修改:data、methods、computed,不便于维护和复用。
  1. <template>
  2.   <div>{{ fullName }}</div>
  3. </template>
  4. <script>
  5. export default {
  6.   data() {
  7.     return {
  8.       firstName: 'Jane',
  9.       lastName: 'Doe'
  10.     }
  11.   },
  12.   computed: {
  13.     fullName() {
  14.       return this.firstName + ' ' + this.lastName;
  15.     }
  16.   }
  17. }
  18. </script>
复制代码

2.1.2 组合式API(Composition API)

Vue 3的组合式API提供了一种更灵活的组织组件逻辑的方式。它通过setup()函数答应你将相干功能组织在一起,而不是基于选项类型分开。这使得代码重用和逻辑提取变得更加简单,尤其是在构建复杂组件时。
  1. <template>
  2.   <div>{{ fullName }}</div>
  3. </template>
  4. <script>
  5. import { ref, computed } from 'vue';
  6. export default {
  7.   setup() {
  8.     const firstName = ref('Jane');
  9.     const lastName = ref('Doe');
  10.     const fullName = computed(() => firstName.value + ' ' + lastName.value);
  11.     return { fullName };
  12.   }
  13. }
  14. </script>
复制代码
API比较
        代码组织:组合式API使得按逻辑组织代码变得更加轻易,特别是在处置惩罚复杂组件时,可以将相干的逻辑放在一起,而不是分散在不同的选项中。
        类型推断:组合式API提供了更好的TypeScript集成,因为它能够利用TypeScript的类型推断,使得在利用TypeScript开辟Vue应用时更加顺畅。
        代码复用:通过组合式API,可以更轻易地将组件逻辑抽取到可复用的函数中,这对于保持代码的干净和维护性黑白常有资助的。
2.2 拉开序幕的setup

2.2.1setup 概述

setup是Vue3中一个新的设置项,值是一个函数,它是 Composition API “表演的舞台”,组件中所用到的:数据、方法、计算属性、监视......等等,均设置在setup中。
特点如下:


  • setup函数返回的对象中的内容,可直接在模板中利用。
  • setup中访问this是undefined。
  • setup函数会在beforeCreate之前调用,它是“领先”所有钩子实行的。
  1. <template>
  2.   <div class="person">
  3.     <h2>姓名:{{name}}</h2>
  4.     <h2>年龄:{{age}}</h2>
  5.     <button @click="changeName">修改名字</button>
  6.     <button @click="changeAge">年龄+1</button>
  7.     <button @click="showTel">点我查看联系方式</button>
  8.   </div>
  9. </template>
  10. <script lang="ts">
  11.   export default {
  12.     name:'Person',
  13.     setup(){
  14.       // 数据,原来写在data中(注意:此时的name、age、tel数据都不是响应式数据)
  15.       let name = '张三'
  16.       let age = 18
  17.       let tel = '13888888888'
  18.       // 方法,原来写在methods中
  19.       function changeName(){
  20.         name = 'zhang-san' //注意:此时这么修改name页面是不变化的
  21.         console.log(name)
  22.       }
  23.       function changeAge(){
  24.         age += 1 //注意:此时这么修改age页面是不变化的
  25.         console.log(age)
  26.       }
  27.       function showTel(){
  28.         alert(tel)
  29.       }
  30.       // 返回一个对象,对象中的内容,模板中可以直接使用
  31.       return {name,age,tel,changeName,changeAge,showTel}
  32.     }
  33.   }
  34. </script>
复制代码
2.3【ref 创建:基本类型的响应式数据】



  • 作用:界说响应式变量。
  • 语法:let xxx = ref(初始值)。
  • 返回值:一个RefImpl的实例对象,简称ref对象或ref,ref对象的value属性是响应式的。
  • 注意点:

    • JS中操纵数据必要:xxx.value,但模板中不必要.value,直接利用即可。
    • 对于let name = ref('张三')来说,name不是响应式的,name.value是响应式的。

Person.vue代码如下
  1. <template>
  2.   <div class="person">
  3.     <h2>姓名:{{name}}</h2>
  4.     <h2>年龄:{{age}}</h2>
  5.     <h2>电话:{{tel}}</h2>
  6.     <h2>地址:{{address}}</h2>
  7.     <button @click="changeName">修改姓名</button>
  8.     <button @click="changeAge">修改年龄</button>
  9.     <button @click="AddAge">增加年龄</button>
  10.     <input type="text" v-model="newusername" placeholder="请输入新的姓名"></input>
  11.     <!--绑定属性-->
  12.   </div>
  13. </template>
  14. <script lang="ts" setup name="Person">
  15. import {ref} from "vue";
  16. let name = ref('张三')
  17. let age = ref(18)
  18. let tel = '13888888888'
  19. let address = '北京昌平区宏福苑·宏福科技园'
  20. let newusername = ref('')
  21. //方法
  22. //修改姓名
  23. function changeName(){
  24.   name.value = newusername.value
  25. }
  26. //修改年龄
  27. function changeAge(){
  28.   age.value = 19
  29. }
  30. //增加年龄
  31. function AddAge(){
  32.   age.value = age.value+1
  33. }
  34. </script>
  35. <style>
  36. .person{
  37.   background-color: aqua;
  38.   box-shadow: 0 0 10px;
  39.   border-radius: 10px;
  40.   padding: 20px;
  41. }
  42. button{
  43.   margin: 0 5px;
  44. }
  45. </style>
复制代码
App.vue代码
  1. <template>
  2.   <Person />
  3. </template>
  4. <script lang="ts">
  5. import Person from "@/pagesvue3Code/007_ref创建_基本类型的响应式数据/components/Person.vue"
  6. export default {
  7.   name:'Vue3CodeIndexDemo1',
  8.   components:{
  9.     Person
  10.   }
  11. }
  12. </script>
  13. <style scoped>
  14. </style>
复制代码

2.4. 【reactive 创建:对象类型的响应式数据】



  • 作用:界说一个响应式对象(基本类型不要用它,要用ref,否则报错)
  • 语法:let 响应式对象= reactive(源对象)。
  • 返回值:一个Proxy的实例对象,简称:响应式对象。
  • 注意点:reactive界说的响应式数据是“深层次”的。
  1. <template>
  2.   <div class="person">
  3.     <h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2>
  4.     <h2>游戏列表:</h2>
  5.     <ul>
  6.       <li v-for="g in games" :key="g.id">{{ g.name }}</li>
  7.     </ul>
  8.     <h2>测试:{{obj.a.b.c.d}}</h2>
  9.     <button @click="changeCarPrice">修改汽车价格</button>
  10.     <button @click="changeFirstGame">修改第一游戏</button>
  11.     <button @click="test">测试</button>
  12.   </div>
  13. </template>
  14. <script lang="ts" setup name="Person">
  15. import { reactive } from 'vue'
  16. // 数据
  17. let car = reactive({ brand: '奔驰', price: 100 })
  18. let games = reactive([
  19.   { id: 'ahsgdyfa01', name: '英雄联盟' },
  20.   { id: 'ahsgdyfa02', name: '王者荣耀' },
  21.   { id: 'ahsgdyfa03', name: '原神' }
  22. ])
  23. let obj = reactive({
  24.   a:{
  25.     b:{
  26.       c:{
  27.         d:666
  28.       }
  29.     }
  30.   }
  31. })
  32. function changeCarPrice() {
  33.   car.price += 10
  34. }
  35. function changeFirstGame() {
  36.   games[0].name = '流星蝴蝶剑'
  37. }
  38. function test(){
  39.   obj.a.b.c.d = 999
  40. }
  41. </script>
复制代码
2.5. 【ref 创建:对象类型的响应式数据】



  • 实在ref吸收的数据可以是:基本类型、对象类型。
  • 若ref吸收的是对象类型,内部实在也是调用了reactive函数。
  1. <template>
  2.   <div class="person">
  3.     <h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2>
  4.     <h2>游戏列表:</h2>
  5.     <ul>
  6.       <li v-for="g in games" :key="g.id">{{ g.name }}</li>
  7.     </ul>
  8.     <h2>测试:{{obj.a.b.c.d}}</h2>
  9.     <button @click="changeCarPrice">修改汽车价格</button>
  10.     <button @click="changeFirstGame">修改第一游戏</button>
  11.     <button @click="test">测试</button>
  12.   </div>
  13. </template>
  14. <script lang="ts" setup name="Person">
  15. import { ref } from 'vue'
  16. // 数据
  17. let car = ref({ brand: '奔驰', price: 100 })
  18. let games = ref([
  19.   { id: 'ahsgdyfa01', name: '英雄联盟' },
  20.   { id: 'ahsgdyfa02', name: '王者荣耀' },
  21.   { id: 'ahsgdyfa03', name: '原神' }
  22. ])
  23. let obj = ref({
  24.   a:{
  25.     b:{
  26.       c:{
  27.         d:666
  28.       }
  29.     }
  30.   }
  31. })
  32. console.log(car)
  33. function changeCarPrice() {
  34.   car.value.price += 10
  35. }
  36. function changeFirstGame() {
  37.   games.value[0].name = '流星蝴蝶剑'
  38. }
  39. function test(){
  40.   obj.value.a.b.c.d = 999
  41. }
  42. </script>
复制代码
2.6. 【ref 对比 reactive】

宏观角度看:
   

  • ref用来界说:基本类型数据、对象类型数据;
  • reactive用来界说:对象类型数据。
  

  • 区别:
   

  • ref创建的变量必须利用.value(可以利用volar插件自动添加.value)。
  • reactive重新分配一个新对象,会失去响应式(可以利用Object.assign去整体更换)。
  

  • 利用原则:
   

  • 若必要一个基本类型的响应式数据,必须利用ref。
  • 若必要一个响应式对象,层级不深,ref、reactive都可以。
  • 若必要一个响应式对象,且层级较深,推荐利用reactive。
  2.7. 【toRefs 与 toRef】



  • 作用:将一个响应式对象中的每一个属性,转换为ref对象。
  • 备注:toRefs与toRef功能一致,但toRefs可以批量转换。
  • 语法如下:
  1. <template>
  2.   <div class="person">
  3.     <h2>姓名:{{person.name}}</h2>
  4.     <h2>年龄:{{person.age}}</h2>
  5.     <h2>性别:{{person.gender}}</h2>
  6.     <button @click="changeName">修改名字</button>
  7.     <button @click="changeAge">修改年龄</button>
  8.     <button @click="changeGender">修改性别</button>
  9.   </div>
  10. </template>
  11. <script lang="ts" setup name="Person">
  12.   import {ref,reactive,toRefs,toRef} from 'vue'
  13.   // 数据
  14.   let person = reactive({name:'张三', age:18, gender:'男'})
  15.        
  16.   // 通过toRefs将person对象中的n个属性批量取出,且依然保持响应式的能力
  17.   let {name,gender} =  toRefs(person)
  18.        
  19.   // 通过toRef将person对象中的gender属性取出,且依然保持响应式的能力
  20.   let age = toRef(person,'age')
  21.   // 方法
  22.   function changeName(){
  23.     name.value += '~'
  24.   }
  25.   function changeAge(){
  26.     age.value += 1
  27.   }
  28.   function changeGender(){
  29.     gender.value = '女'
  30.   }
  31. </script>
复制代码
2.8. 【computed】

作用:根据已有数据计算出新数据(和Vue2中的computed作用一致)
在 Vue 3 中,computed 是一个用于声明计算属性的 API。它可以在组合式 API(Composition API)中利用,资助你界说基于其他响应式数据派生出的属性,并自动缓存和更新这些属性的值。与 Vue 2 中的计算属性相似,computed 在 Vue 3 中也起到减少重复计算、进步性能的作用。
  1. import { ref, computed } from 'vue';
  2. export default {
  3.   setup() {
  4.     const count = ref(0);
  5.     // 定义一个计算属性,基于 count 值的变化
  6.     const doubleCount = computed(() => count.value * 2);
  7.     const increment = () => {
  8.       count.value++;
  9.     };
  10.     return {
  11.       count,
  12.       doubleCount,
  13.       increment,
  14.     };
  15.   },
  16. };
复制代码
说明



  • computed 的参数是一个函数,用于返回计算属性的值。
  • 当 count 值发生变革时,doubleCount 会自动重新计算。
  • computed 是懒计算的,只有在被读取时才会重新计算值,并会缓存上一次的计算结果,直到依靠的响应式数据发生变革。
与 watch 的区别

computed 是用于派生新的状态,适用于基于其他响应式数据的计算,而 watch 则用于观察数据变革并触发副作用。
2.9.【watch】



  • 作用:监视数据的变革(和Vue2中的watch作用一致)
  • 特点:Vue3中的watch只能监视以下四种数据:
   

  • ref界说的数据。
  • reactive界说的数据。
  • 函数返回一个值(getter函数)。
  • 一个包罗上述内容的数组。
  我们在Vue3中利用watch的时间,通常会碰到以下几种环境:
* 环境一

监视ref界说的【基本类型】数据:直接写数据名即可,监视的是其value值的改变。
  1. <template>
  2.   <div class="person">
  3.     <h1>情况一:监视【ref】定义的【基本类型】数据</h1>
  4.     <h2>当前求和为:{{sum}}</h2>
  5.     <button @click="changeSum">点我+1</button>
  6.   </div>
  7. </template>
  8. <script lang="ts" setup name="Person">
  9. import {ref,watch} from "vue";
  10. //数据
  11. let sum=ref(0)
  12. //方法
  13. function changeSum(){
  14.   sum.value+=1
  15. }
  16. //监视,情况一:监视【ref】定义的【基本类型】数据
  17. const stopWatch=watch(sum,(newValue,oldValue)=>{
  18.   console.log('watch监听到sum的变化,新的值为:',newValue,oldValue)
  19.   if(newValue >= 10){
  20.     console.log('sum大于10,停止watch')
  21.     stopWatch()
  22.   }
  23. },{immediate:true})
  24. </script>
  25. <style>
  26. .person{
  27.   background-color: aqua;
  28.   box-shadow: 0 0 10px;
  29.   border-radius: 10px;
  30.   padding: 20px;
  31. }
  32. button{
  33.   margin: 0 5px;
  34. }
  35. </style>
复制代码

* 环境二

监视ref界说的【对象类型】数据:直接写数据名,监视的是对象的【地点值】,若想监视对象内部的数据,要手动开启深度监视。
   注意:
  

  • 若修改的是ref界说的对象中的属性,newValue 和 oldValue 都是新值,因为它们是同一个对象。
  • 若修改整个ref界说的对象,newValue 是新值, oldValue 是旧值,因为不是同一个对象了。
  
  1. <template>
  2.   <div class="person">
  3.     <h1>情况二:监视【ref】定义的【对象类型】数据</h1>
  4.     <h2>姓名:{{ person.name }}</h2>
  5.     <h2>年龄:{{ person.age }}</h2>
  6.     <button @click="changeName">修改名字</button>
  7.     <button @click="changeAge">修改年龄</button>
  8.     <button @click="changePerson">修改整个人</button>
  9.   </div>
  10. </template>
  11. <script lang="ts" setup name="Person">
  12.   import {ref,watch} from 'vue'
  13.   // 数据
  14.   let person = ref({
  15.     name:'张三',
  16.     age:18
  17.   })
  18.   // 方法
  19.   function changeName(){
  20.     person.value.name += '~'
  21.   }
  22.   function changeAge(){
  23.     person.value.age += 1
  24.   }
  25.   function changePerson(){
  26.     person.value = {name:'李四',age:90}
  27.   }
  28.   /*
  29.     监视,情况一:监视【ref】定义的【对象类型】数据,监视的是对象的地址值,若想监视对象内部属性的变化,需要手动开启深度监视
  30.     watch的第一个参数是:被监视的数据
  31.     watch的第二个参数是:监视的回调
  32.     watch的第三个参数是:配置对象(deep、immediate等等.....)
  33.   */
  34.   watch(person,(newValue,oldValue)=>{
  35.     console.log('person变化了',newValue,oldValue)
  36.   },{deep:true})
  37.   
  38. </script>
复制代码
* 环境三

监视reactive界说的【对象类型】数据,且默认开启了深度监视。
  1. <template>
  2.   <div class="person">
  3.     <h1>情况一:监视【ref】定义的【基本类型】数据</h1>
  4.     <h2>当前求和为:{{sum}}</h2>
  5.     <button @click="changeSum">点我+1</button>
  6.     <h1>情况三:监视【reactive】定义的【对象类型】数据</h1>
  7.     <h2>当前用户信息为:{{person.name}}</h2>
  8.     <h2>年龄为:{{person.age}}</h2>
  9.     <button @click="changePerson">修改整个人</button>
  10.   </div>
  11. </template>
  12. <script lang="ts" setup name="Person">
  13. import {ref,watch,reactive} from "vue";
  14. //数据
  15. let sum=ref(0)
  16. let person=reactive({name:"张三",age:20})
  17. //方法
  18. function changeSum(){
  19.   sum.value+=1
  20. }
  21. function changePerson(){
  22.   Object.assign(person,{name:'李四',age:80})
  23. }
  24. //监视,情况一:监视【ref】定义的【基本类型】数据
  25. const stopWatch=watch(sum,(newValue,oldValue)=>{
  26.   console.log('watch监听到sum的变化,新的值为:',newValue,oldValue)
  27.   if(newValue >= 10){
  28.     console.log('sum大于10,停止watch')
  29.     stopWatch()
  30.   }
  31. },{immediate:true})
  32. //情况三:监视【reactive】定义的【对象类型】数据
  33. watch(person,(newValue,oldValue)=>{
  34.   console.log('watch监听到person的变化,新的值为:',newValue,oldValue)
  35. })
  36. </script>
  37. <style>
  38. .person{
  39.   background-color: aqua;
  40.   box-shadow: 0 0 10px;
  41.   border-radius: 10px;
  42.   padding: 20px;
  43. }
  44. button{
  45.   margin: 0 5px;
  46. }
  47. </style>
复制代码
* 环境四

监视ref或reactive界说的【对象类型】数据中的某个属性,注意点如下:

  • 若该属性值不是【对象类型】,必要写成函数形式。
  • 若该属性值是依然是【对象类型】,可直接编,也可写成函数,建议写成函数。
结论:监视的要是对象里的属性,那么最好写函数式,注意点:若是对象监视的是地点值,必要关注对象内部,必要手动开启深度监视。
  1. <template>
  2.   <div class="person">
  3.     <h1>情况四:监视【ref】或【reactive】定义的【对象类型】数据中的某个属性</h1>
  4.     <h2>姓名:{{ person.name }}</h2>
  5.     <h2>年龄:{{ person.age }}</h2>
  6.     <h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
  7.     <button @click="changeName">修改名字</button>
  8.     <button @click="changeAge">修改年龄</button>
  9.     <button @click="changeC1">修改第一台车</button>
  10.     <button @click="changeC2">修改第二台车</button>
  11.     <button @click="changeCar">修改整个车</button>
  12.   </div>
  13. </template>
  14. <script lang="ts" setup name="Person">
  15.   import {reactive,watch} from 'vue'
  16.   // 数据
  17.   let person = reactive({
  18.     name:'张三',
  19.     age:18,
  20.     car:{
  21.       c1:'奔驰',
  22.       c2:'宝马'
  23.     }
  24.   })
  25.   // 方法
  26.   function changeName(){
  27.     person.name += '~'
  28.   }
  29.   function changeAge(){
  30.     person.age += 1
  31.   }
  32.   function changeC1(){
  33.     person.car.c1 = '奥迪'
  34.   }
  35.   function changeC2(){
  36.     person.car.c2 = '大众'
  37.   }
  38.   function changeCar(){
  39.     person.car = {c1:'雅迪',c2:'爱玛'}
  40.   }
  41.   // 监视,情况四:监视响应式对象中的某个属性,且该属性是基本类型的,要写成函数式
  42.   /* watch(()=> person.name,(newValue,oldValue)=>{
  43.     console.log('person.name变化了',newValue,oldValue)
  44.   }) */
  45.   // 监视,情况四:监视响应式对象中的某个属性,且该属性是对象类型的,可以直接写,也能写函数,更推荐写函数
  46.   watch(()=>person.car,(newValue,oldValue)=>{
  47.     console.log('person.car变化了',newValue,oldValue)
  48.   },{deep:true})
  49. </script>
复制代码
环境五 监视上述多个数据信息

  1. <template>
  2.   <div class="person">
  3.     <h1>情况五:监视上述的多个数据</h1>
  4.     <h2>姓名:{{ person.name }}</h2>
  5.     <h2>年龄:{{ person.age }}</h2>
  6.     <h2>汽车:{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
  7.     <button @click="changeName">修改名字</button>
  8.     <button @click="changeAge">修改年龄</button>
  9.     <button @click="changeC1">修改第一台车</button>
  10.     <button @click="changeC2">修改第二台车</button>
  11.     <button @click="changeCar">修改整个车</button>
  12.   </div>
  13. </template>
  14. <script lang="ts" setup name="Person">
  15.   import {reactive,watch} from 'vue'
  16.   // 数据
  17.   let person = reactive({
  18.     name:'张三',
  19.     age:18,
  20.     car:{
  21.       c1:'奔驰',
  22.       c2:'宝马'
  23.     }
  24.   })
  25.   // 方法
  26.   function changeName(){
  27.     person.name += '~'
  28.   }
  29.   function changeAge(){
  30.     person.age += 1
  31.   }
  32.   function changeC1(){
  33.     person.car.c1 = '奥迪'
  34.   }
  35.   function changeC2(){
  36.     person.car.c2 = '大众'
  37.   }
  38.   function changeCar(){
  39.     person.car = {c1:'雅迪',c2:'爱玛'}
  40.   }
  41.   // 监视,情况五:监视上述的多个数据
  42.   watch([()=>person.name,person.car],(newValue,oldValue)=>{
  43.     console.log('person.car变化了',newValue,oldValue)
  44.   },{deep:true})
  45. </script>
复制代码
2.10. 【watchEffect】

  watchEffect 是 Vue 3 中提供的一种便捷的响应式函数,用于立即实行并监听内部响应式数据的变革。当依靠的数据变革时,watchEffect 自动重新运行回调函数。与 watch 不同,watchEffect 不必要手动声明详细的依靠,它会自动网络并追踪函数中用到的所有响应式数据。
watchEffect 与 watch 的区别



  • watchEffect 不必要手动指定依靠,得当处置惩罚简单的响应式场景。
  • watch 得当必要精确控制监听哪些依靠,或在回调中利用旧值和新值的场景。
特点


  • 自动网络依靠:watchEffect 不必要指定监听的详细数据,它会自动追踪回调中利用到的响应式数据。
  • 立即实行:watchEffect 在注册时会立即实行一次,然后在依靠更新时重新运行。
  • 适用于简单场景:watchEffect 得当用来追踪多个响应式数据的变革,但不适用于必要访问旧值或多项复杂数据对比的场景(这些环境可以利用 watch)。
  1. const stop = watchEffect(() => {
  2.   console.log("count的值为:", count.value);
  3. });
  4. // 需要时停止
  5. stop();
复制代码
 举一个案例
  1. <template>
  2.   <div class="person">
  3.     <h2>需求:当水温达到60度,或水位达到80cm时,给服务器发请求</h2>
  4.     <h2>当前水温:{{temp}}℃</h2>
  5.     <h2>当前水位:{{height}}cm</h2>
  6.     <button @click="changeTemp">水温+10</button>
  7.     <button @click="changeHeight">水位+10</button>
  8.   </div>
  9. </template>
  10. <script lang="ts" setup name="Person">
  11.   import {ref,watch,watchEffect} from 'vue'
  12.   // 数据
  13.   let temp = ref(10)
  14.   let height = ref(0)
  15.   // 方法
  16.   function changeTemp(){
  17.     temp.value += 10
  18.   }
  19.   function changeHeight(){
  20.     height.value += 10
  21.   }
  22.   // 监视 -- watch实现
  23.   /* watch([temp,height],(value)=>{
  24.     // 从value中获取最新的水温(newTemp)、最新的水位(newHeight)
  25.     let [newTemp,newHeight] = value
  26.     // 逻辑
  27.     if(newTemp >= 60 || newHeight >= 80){
  28.       console.log('给服务器发请求')
  29.     }
  30.   }) */
  31.   // 监视 -- watchEffect实现
  32.   watchEffect(()=>{
  33.     if(temp.value >= 60 || height.value >= 80){
  34.       console.log('给服务器发请求')
  35.     }
  36.   })
  37. </script>
  38. <style scoped>
  39.   .person {
  40.     background-color: skyblue;
  41.     box-shadow: 0 0 10px;
  42.     border-radius: 10px;
  43.     padding: 20px;
  44.   }
  45.   button {
  46.     margin: 0 5px;
  47.   }
  48.   li {
  49.     font-size: 20px;
  50.   }
  51. </style>
复制代码
2.11. 【标签的 ref 属性】

作用:用于注册模板引用。
   

  • 用在普通DOM标签上,获取的是DOM节点。
  • 用在组件标签上,获取的是组件实例对象。
  在 Vue 3 中,可以利用 ref 和 onMounted 来注册模板引用。模板引用可以用来直接访问 DOM 节点或组件实例。详细来说:


  • 用于普通 DOM 标签:可以获取该 DOM 元素的原生节点。
  • 用于组件标签:可以获取该组件的实例,进而访问组件的公开属性和方法。
示例 1:访问普通 DOM 节点

假设我们有一个输入框,必要在组件挂载时获取并聚焦它:
  1. <template>
  2.   <div>
  3.     <input ref="inputRef" type="text" placeholder="聚焦于此" />
  4.   </div>
  5. </template>
  6. <script lang="ts" setup>
  7. import { ref, onMounted } from "vue";
  8. // 使用 ref 注册模板引用
  9. const inputRef = ref<HTMLInputElement | null>(null);
  10. // 在组件挂载后获取并聚焦输入框
  11. onMounted(() => {
  12.   if (inputRef.value) {
  13.     inputRef.value.focus();
  14.   }
  15. });
  16. </script>
复制代码
在这个例子中,inputRef 引用了 input 元素的 DOM 节点。在 onMounted 钩子中,我们可以访问该节点并调用其 focus 方法。
示例 2:访问子组件实例

假设有一个子组件 ChildComponent,提供了一个方法 showAlert。父组件可以通过模板引用调用这个方法。
子组件 ChildComponent.vue

  1. <!-- 父组件App.vue -->
  2. <template>
  3.   <Person ref="ren"/>
  4.   <button @click="test">测试</button>
  5. </template>
  6. <script lang="ts" setup name="App">
  7.   import Person from './components/Person.vue'
  8.   import {ref} from 'vue'
  9.   let ren = ref()
  10.   function test(){
  11.     console.log(ren.value.name)
  12.     console.log(ren.value.age)
  13.   }
  14. </script>
  15. <!-- 子组件Person.vue中要使用defineExpose暴露内容 -->
  16. <script lang="ts" setup name="Person">
  17.   import {ref,defineExpose} from 'vue'
  18.         // 数据
  19.   let name = ref('张三')
  20.   let age = ref(18)
  21.   /****************************/
  22.   /****************************/
  23.   // 使用defineExpose将组件中的数据交给外部
  24.   defineExpose({name,age})
  25. </script>
复制代码
参考文献

【2024最新】vue3的基本利用(超详细)-CSDN博客
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表