Vue3 学习笔记 —— (一)深入理解组合式 API

2023-11-16


Author:Gorit
Date:2021/4/24
Refer:网易云课堂
2021年发表博文: 17/30

Vue3 学习

学习文档
如果是第一次接触 Vue3,可以看这个 Vue3 初体验

零、Vue3.0 与 Vue2.x 的性能对比

  1. 框架内部做了大量的性能优化,包括虚拟 DOM,编译模板、Proxy 的新数据监听,更小的打包文件等
  2. 新的组合式 API (composition-api),更适合大型项目的编写方式
  3. 对 TypeScript 支持更好,去除繁琐的 this 操作,更强大的类型推导

一、搭建环境

  1. node 8.9.0 以上
  2. 安装好 npm
  3. 安装 vue
  4. 安装 Vue Cli4 脚手架

二、创建项目

  1. vue create vue3-demo

  1. 其他的选择默认配置即可
  2. 安装 yarn :cnpm i yarn -g (提升安装速度)
  3. 测试:yarn --versin

项目结构介绍

  • package.json 项目全局管理
  • node_modules 项目依赖包,占用大量空间
  • public 入口文件
  • src:main.js 为入口文件,项目代码在这里编写

三、Vue3 Composition API

Vue3 是向下兼容 Vue2 API 的,但是 Vue3 中提供了一种全新的 Composition API

3.1 ref() or setup() ? reactive()

setup() 作为 Vue3.0 的入口函数

reactive() 作声明式渲染,用来响应数据

ref() 显示响应式数据,配合 reactve()

3.1.1 非响应式数据显示 (reactive)

直接返回数据

<template>
	<div>直接返回 state【非响应式的数据】:{{count}}</div>
</template>

<script>
	// 如果是 Vue2 项目,想要用 Vue3 的语法,需要安装 @vue/composition-api	
	// import { xxx } from '@vue/composition-api'
	import {
		reactive
	} from 'vue'
	export default {
		name: 'App',
		// Vue3.0 的入口函数,编写 Vue3 代码,beforeCreate之前进行触发, 需要 return
		setup() { 
			 const state = reactive({
			 	count: 0
			 });
			// 不具备数据响应式的效果,1s 后数据没有任何变化
			 setTimeout(()=> {
			 	state.count++;
			 },1000)
			 return state;
		}
	}
</script>

3.1.2 响应式数据显示 (reactive)

通过对象的形式

<template>
	<div>返回 state 对象 【响应式数据】{{state.count}}</div>
</template>

<script>
	import {
		reactive
	} from 'vue'
	export default {
		name: 'App',
		// Vue3.0 的入口函数,编写 Vue3 代码,beforeCreate之前进行触发, 需要 return
		setup() { 
			// 具备数据响应式, 返回对象
			const state = reactive({
				count: 0
			});
			setTimeout(()=> {
				state.count++;
			},1000)
			return { state };
            
            // 对返回的结果 解构,这样数据就可以只显示 {{ count }} 就可以了
             // return {
			//	count: state.count
			//}
		}
	}
</script>

3.1.3 响应式数据展示(整合 ref() )

<template>
	<img alt="Vue logo" src="./assets/logo.png">
	<div>ref 实现响应式对象 {{ count }}</div>
</template>

<script>
	import {
		ref
	} from 'vue'
	export default {
		name: 'App',
		setup() { 
			// 使用 ref() 实现响应式数据
			const count = ref(0); // 这样 count 就实现了响应式的效果
			setInterval(()=> {
				count.value++;
			},1000)
			return {
				count
			};
		}
	}
</script>

因此,我们既要响应式,又要展示数据,折中的方案是直接使用 ref

3.1.4 小案例:实现一个计数器

<template>
	<img alt="Vue logo" src="./assets/logo.png">
	<div class="my-app">
		<!-- Vue3 无法直接拿到值 -->
		<h3>{{counter}}</h3>
		<button @click="increment(1)">increment</button>
		<button @click="decrement(1)">decrement</button>
	</div>
</template>

<script>
	import { ref } from 'vue'
	/**
	 * Options API Vue2 Class
	 * Composition API Vue3 Function
	 */
	export default {
		name: 'App',
		setup() {
			const counter = ref(1000)
			// console.log(counter.value)
			const increment = () => {
				counter.value += 1;
			}
			
			const decrement = () => {
				counter.value -= 1;
			}
			// 必须 return,外部才能拿到值
			return { counter, increment,decrement }
		}
	}
</script>

3.2 toRefs() ? toRef()

在上面的代码中,我们使用 ref() 和 reactive() 分别可以实现响应式的数据,我们是否可以两者一起使用呢?

3.2.1 ref() 和 reactive() 连用

<template>
	<img alt="Vue logo" src="./assets/logo.png">
	<div>ref() 和 reactive() 实现响应式对象 {{ count }}</div>
</template>

<script>
	// 如果是 Vue2 项目,想要用 Vue3 的语法,需要安装 @vue/composition-api	
	// import { xxx } from '@vue/composition-api'
	import {
		ref,
		reactive
	} from 'vue'
	export default {
		name: 'App',
		setup() { 
			// ---------------------------- ref 和 reactive 连用
			const count = ref(0);
			const state = reactive({
				count
			})
			setInterval(()=> {
				state.count++;
			},1000)
			return {
				count
			};
		}
	}
</script>

3.2.2 使用 toRefs() 和 reactive()

<template>
	<img alt="Vue logo" src="./assets/logo.png">
	<div>实现响应式对象 {{ count }}</div>
</template>

<script>
	import {
		reactive,
		toRefs
	} from 'vue'
	export default {
		name: 'App',
		setup() { 
			// ---------------------------- //使用 toRefs() 将 reactive 转换为 Ref
			const state = reactive({
				count: 0
			});
			
			const { count } = toRefs(state); // toRefs() 作用:将普通类型数据,转换为 Ref 响应式数据
			setInterval(()=> {
				state.count++;
			},1000)
			return {
				count
			};
		}
	}
</script>

3.2.3 使用 toRef() 和 reactive()

<template>
	<img alt="Vue logo" src="./assets/logo.png">
	<div>实现响应式对象 {{ count }}</div>
</template>

<script>
	import {
		reactive,
		toRefs
	} from 'vue'
	export default {
		name: 'App',
		setup() { 
			// ---------------------------- //使用 toRefs() 将 reactive 转换为 Ref
			const state = reactive({
				count: 0
			});
			
			const  count  = toRef(state, 'count'); // toRef() 作用:将普通类型数据,转换为 Ref 响应式数据,指定单个数据转换
			setInterval(()=> {
				state.count++;
			},1000)
			return {
				count
			};
            // toRefs === {}
		}
	}
</script>

ref 和 reactive 分别是两种响应式数据的变量风格,具体看个人情况使用

3.3 computed 计算属性

3.3.1 配合 ref() 使用 实现响应式

<template>
	<img alt="Vue logo" src="./assets/logo.png">
	<div>
		{{count}} , {{double}}
	</div>
</template>

<script>
	import {
		ref,
		computed
	} from 'vue'
	export default {
		name: 'App',
		setup() { 
			// 使用计算属性
			const count = ref(1)
			const double = computed(()=>count.value * 2)
			setTimeout(()=>{
				count.value++
			},1000)
			return {
				count,double
			}
		}
	}
</script>

3.3.2 配合 toRefs() 和 reactive() 实现响应式

<template>
	<img alt="Vue logo" src="./assets/logo.png">
	<div>
		{{count}} , {{double}}
	</div>
</template>

<script>
	import {
		reactive,
         toRefs,
		computed
	} from 'vue'
	export default {
		name: 'App',
		setup() { 
			const state = reactive({
				count: 1,
				double: computed(()=>state.count * 2)
			})
			setTimeout(()=>{
				state.count++
			},1000)
			return toRefs(state)
		}
	}
</script>

3.4 定义函数

3.4.1 函数与 watch

<template>
	<img alt="Vue logo" src="./assets/logo.png">
	<div>
		事件:{{count}}
	</div>
	<button @click="add">添加</button>
</template>

<script>
	import {
		ref,
       	 watch
	} from 'vue'
	export default {
		name: 'App',
		setup() { 
			// =============== 事件
			const count = ref(1)
			const add = () => { // 事件方法
				count.value++;
			}
            // 配合侦听器
			watch(count ,(count, prevCount) => {
				console.log(count, prevCount)
			})
			return {count, add}
		}
	}
</script>

3.4.2 Vue3.0 函数与生命周期函数

文档

新的生命周期函数钩子要在 setup() 中使用

  1. onMounted
  2. onUpdated
  3. onUnmounted
export default {
  setup() {
    // mounted
    onMounted(() => {
      console.log('Component is mounted!')
    })
  }
}

四、Vue3 组件化(拆分+传值+注册)

这里主要是回顾 组件化编程

拆分的方式同 Vue2,注册 + 引入
组件拆分的案例我们沿用上面的计数器来实现 (参考 3.1.4 小节的内容)

4.1 组件拆分

预览效果:
在这里插入图片描述
编码如下:

  1. 定义一个新的 vue 文件,命名为 CounterView.vue 文件
  2. 使用 props 接受父组件 App.vue 穿过来的值
<template>
  <div>
      我是子组件 CounterView
      {{counter}}
  </div>
</template>

<script>
export default {
    name: 'CounterView',
    // props: ['counter']  vue2 一般都是这么写的
   	// 下面的这种写法会更加规范
    props: {
        counter: {
            type: Number,
            required: true,
            default: 500
        }
    }
}
</script>
  1. 修改父组件 App.vue,改为引用 CounterView.vue ,并注册为组件
<template>
  <div>
    <img alt="Vue logo" src="./assets/logo.png" />  
    <!-- 属性绑定 -->
    <counter-view :counter="counter"/>
    <button @click="increament(1)">增加</button>
    <button @click="increament(-1)">减少</button>
  </div>
</template>

<script>
import { ref } from "vue";
import CounterView from '@/components/CounterView.vue'
export default {
  name: "App",
  components: {
    CounterView
  },
  setup() {
    const counter = ref(1000);
    console.log(counter.value);
    // 定义函数
    const increament = (num) => {
      counter.value += num;
    };
    return { counter,increament };
  },
};
</script>

<style>
</style>

4.2 事件拆分

这里我们在上面的基础上,将 setup() 中定义的事件,拆分至另一个新的 vue 文件
首先我们需要补充一些前置概念:

  1. 在 setup() 中是没有 this 关键字的
  2. setup() 是可以接受两个参数的 (props, context),然后我们打印接受到的值如下
    在这里插入图片描述
  3. cotext 中,可以看到 emit 关键字,是不是很熟悉,vue2 中我们要子组件传事件给父组件,用的是 this.$emit("事件名称", '值"), 在 Vue3 中也会用到类似的,后面会有具体的演示
  4. 编码如下:

在子组件完成事件注册

<template>
  <div>
    <button @click="increament(1)">增加</button>
    <button @click="increament(-1)">减少</button>
  </div>
</template>

<script>
export default {
    name: 'CounterController',
    setup(props,ctx) { 
	   console.log(props, ctx)    	// 这里打印的就是我们刚刚上面看到的
       const increament = (num) => {
            // ctx.emit 等价于 vue2 中 this.$emit("xxx",xxx)。 在 vue3 中 setup() 函数是没有 this 的概念的
            ctx.emit("onIncreament",num) // 完成事件注册,将操作的逻辑交给父组件来完成
        }
        return {increament}
    },
}
</script>

在父组件完成事件调用

<template>
  <div>
    <img alt="Vue logo" src="./assets/logo.png" />  
    <!-- 属性绑定 -->
    <counter-view :counter="counter"/>
    <!-- <button @click="increament(1)">增加</button>
    <button @click="increament(-1)">减少</button> -->
    <!-- 子组件事件注册完毕后,交给父组件进行触发, 处理的函数需要传 $event 就可以实现和上面一样的效果了 -->
    <counter-controller @onIncreament="increament($event)" />
  </div>
</template>

<script>
import { ref } from "vue";
import CounterView from '@/components/CounterView.vue'
import CounterController from '@/components/CounterController.vue'
export default {
  name: "App",
  components: {
    CounterView,
    CounterController
  },
  setup() {
    const counter = ref(1000);
    // 定义函数
    const increament = (num) => {
      counter.value += num;
    };
    return { counter,increament };
  },
};
</script>

五、总结

我们来回顾一下所学内容

  1. setup(props, context), setup() 是代码的入口
  2. 响应式 API:reactive() 、ref()、toRef()、toRefs()
  3. 计算属性 computed 和 watch 侦听器的使用
  4. 组件化思想
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue3 学习笔记 —— (一)深入理解组合式 API 的相关文章

  • mmdetection 报错 cats = self.dataset['categories'] KeyError: 'categories'

    如上图 报错 原因 coco训练集中没有categories字段 即数据集的标注json文件不对 解决方案 请参照coco数据集格式
  • 【华为OD统一考试A卷

    华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为OD统一考试 A卷 和OD统一考试 B卷 你收到的链接上面会标注A卷还是B卷 请注意 根据反馈 目前大部分收到的都是
  • PCL MeanShift点云聚类(C++详细过程版)

    目录 一 算法原理 1 原理概述 2 实现流程 3 参考文献 二 代码实现 三 结果展示 四 测试数据 本文由CSDN点云侠原创 爬虫网站请自重原文链接 一 算法原理 1 原理概述 均值漂移算法是一种非参数聚类技术 它不需要预先知道聚类的数

随机推荐

  • HTML、PHP实战:搭建一个网页登录页面。

    一 实验环境 MySQL5 7 26 FTP0 9 60 Apache2 4 39 我这里用的是PHPstudy小皮一键搭建的 数据库 二 登录页面 登录页面前端代码 文件名 denglu html
  • 人工智能学习笔记(一)Agent

    智能agent 开篇前言 agent的分类 1 简单反射agent 2 基于状态的反射agent 3 基于目标的agent 4 基于效用的agent 5 学习agent Exploration vs Exploitation 开篇前言 这段
  • 一文读懂什么是DHCP以及DHCP的功能特点

    随着企业中网络结构的日益复杂 接入终端的急剧增加 传统的IP分配方式已经无法满足日常工作需求 DHCP的出现有效解决了IP地址分配难题 本文中科三方针对什么是DHCP以及DHCP的功能特点做下介绍 什么是DHCP DHCP 全称Dynami
  • Python+Excel筛选未提交人员

    起因 学校给了表格让我们班长统计信息 可以用腾讯大大的TIM协作办公 让大家自己填 感觉方便了很多 然而 信息一旦变多而且顺序又没有固定 到后期想要知道未填信息的同学 这就难受了 只能找到班级名单 一个一个对照着找出未提交人员 日后此类事情
  • OCR入门教程系列(一):OCR基础导论

    作者简介 CSDN 阿里云人工智能领域博客专家 新星计划计算机视觉导师 百度飞桨PPDE 专注大数据与AI知识分享 公众号 GoAI的学习小屋 免费分享书籍 简历 导图等 更有交流群分享宝藏资料 关注公众号回复 加群 或 链接 加群 专栏推
  • 【LVGL学习笔记】image图像相关接口

    数据结构如下 Data of image typedef struct lv obj t obj const void src 图像源 指向数组 文件或符号的指针 lv point t offset lv coord t w 宽度 lv c
  • 计算机硬盘模式,硬盘三种模式的含义-电脑自学网

    硬盘三种模式的含义 NORMAL 普通模式 是最早的IDE方式 以此方式访问BIOS和IDE控制器对参数不做任何转换 该模式支持的最大柱面数为1024 最大磁头数为16 最大扇区为63 每个扇区字节数为512 因此这种模式所支持的硬盘最大容
  • Open3D点云处理算法最全合集

    Open3D点云处理算法最全合集 致力于搜集可运行 可视化较好的Open3D算法 持续更新中 1 Open3D 点云读取及可视化 离群点去除 2 Open3D 点云体素格下采样 3 Open3D 点云KdTree建立 3种近邻搜索及结果可视
  • 系统开发与运行

    系统开发与运行 系统分析与设计 需求分析 需求工程 结构化分析与设计 测试基础知识 系统运行与维护 软件架构介绍 系统分析概述 系统分析是一种问题求解技术 它将一个系统分解成各个组成部分 目的是研究各个部分如何工作 交互 以实现其系统目标
  • set_new_handler(0)是什么意思?有什么用?

    出自 STL源码剖析 第45页中有一行代码set new handler 0 源代码 inline T allocate ptrdiff t size T std set new handler 0 T tmp T operator new
  • C#中File FileInfo 和Directory DirectoryInfo 类的区别

    老师在讲C 文件操作的时候讲的个类 功能类似 但用法有区别 他们都存在于systerm IO命名空间下 File和Directory的方法都是静态方法 FileInfo和DirectoryInfo的方法都是普通方法 老师建议是如果你要在某个
  • Python之PyAudio使用

    PyAudio 播放 录音 回放 回调方法播放 非阻塞回调 PyAudio 使用这个可以进行录音 播放 生成wav文件等等 播放 coding utf 8 引入库 import pyaudio import wave import sys
  • aiohttp 异步http请求-12.aiohttp 请求生命周期(和requests库有什么不一样?)

    前言 aiohttp 请求生命周期对比requests库使用的区别 aiohttp 客户端 API 当你第一次使用 aiohttp 时 你会注意到一个简单的 HTTP 请求不是一次执行的 而是最多三个步骤 async with aiohtt
  • dac0832三角波c语言程序,单片机控制DAC0832输出正弦波三角波汇编程序

    org 0000h LJMP MAIN ORG 0003H LJMP L0 MAIN MOV R2 0aH 调幅倍数 MOV R4 01H 增减选择 MOV R5 01H pp SETB EA SETB EX0 延时计数个数 MOV A 0
  • 渗透系列之排序处产生的SQL注入问题

    1 在日常的测试过程中 发现系统的排序功能最容易产生sql注入 我们需要重点关注业务系统的排序功能 一般功能点对应这类字段 sortField sortOrder order orderby等 举个排序的SQL注入案例 发现系统的一个查询功
  • 2017-2018-1 20155227 《信息安全系统设计基础》第十三周学习总结

    2017 2018 1 20155227 信息安全系统设计基础 第十三周学习总结 找出全书你认为最重要的一章 深入重新学习一下 要求 期末占10分 完成这一章所有习题 详细总结本章要点 给你的结对学习搭档讲解你的总结并获取反馈 我选择教材第
  • 冯乐乐之六,基础光照模型

    需要理清的概念 兰伯特 半兰伯特 冯模型 布林冯模型 高光反射specular 代表物体表面反射光线 漫反射diffuse 代表吸收然后散射出表面的光线 环境光ambient 自发光emissive 漫反射 漫反射从任何方向看都是一致的 漫
  • 科学推理~

    科学推理 物理 1 力学 重力 重力并不是指向地心的 只有赤道可以 弹力 重点 判断弹力方向 相互作用力 摩擦力 静摩擦力 滑动摩擦力 注意 最大静摩擦力默认等于滑动摩擦力 压强 固体压强 液体压强 连通器 气体压强 气体对外做功 T 下降
  • 计算机图形学OpenGLC++实现: 橡皮筋技术实现折线和矩形的鼠标实现(附源码)

    废话不多说 直接开始 下列是会使用到的函数简单介绍 初始化背景 void Initial void 改变窗口大小 void ChangeSize int w int h 菜单响应函数 chooseWay int value 清除当前已经画的
  • Vue3 学习笔记 —— (一)深入理解组合式 API

    Vue3 学习笔记梳理 Vue3 学习 零 Vue3 0 与 Vue2 x 的性能对比 一 搭建环境 二 创建项目 三 Vue3 Composition API 3 1 ref or setup reactive 3 1 1 非响应式数据显