Vue3(一):创建vue3工程、setup、vue3响应式原理、computed和watch
Vue3:第一章
- 一、创建Vue3.0工程
- 1.使用vue-cli创建
- 2.使用vite创建
- 二、Vue3中的响应式
- 1.拉开序幕的setup
- 2.ref函数
- 3.reactive函数
- 4.vue3中响应式的原理
- (1)vue2中响应式原理
- (2)Vue3中的Proxy
- 5.reactive和ref的对比
- 6.setup的两个注意点
- (1)执行时机
- (2)setup的参数
- 三、计算属性和监视
- 1.computed函数
- 2.watch函数
- (1)第一个参数怎么写
- (2)第一个参数到底写不写.value
- 3.watchEffect函数
一、创建Vue3.0工程
1.使用vue-cli创建
官方文档:https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create
// 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
// 安装或者升级你的@vue/cli
npm install -g @vue/cli
// 创建
vue create vue_test
// 启动
cd vue_test
npm run serve
2.使用vite创建
官方文档:https://v3.cn.vuejs.org/guide/installation.html#vite
vite官网:https://vitejs.cn
// 创建工程
npm init vite-app <project-name>
// 进入工程目录
cd <project-name>
// 安装依赖
npm install
// 运行
npm run dev
二、Vue3中的响应式
1.拉开序幕的setup
之前我们在vue2中都是多个配置项组合在一起(选项式API),在vue3中,换了一种方式,那就是Composition API(组合式API),而setup则是组合式API表演的舞台,组件中所有的数据和方法都写在setup函数中。
这个setup函数其实有两种返回值:1、返回一个对象 2、返回一个渲染函数,用的最多的就是返回一个对象,把用到的所有属性、方法都返回出去,方便在模板中使用(当然,现在有了setup语法糖,后面再说)
export default {name: 'App',setup() {const name = 'zzy'const age = 18return {name,age,}//返回一个渲染函数//return () => h(h1, 'zzy')}
}
注意:不要把setup和vue2中的选项式API混用,因为setup中访问不到vue2中的属性方法(但2可访问3),如果混用的话,有重名setup优先。
还有,setup前不要加async,因为返回值会变成promise,而不是我们return的那些属性和方法
2.ref函数
作用:定义响应式的数据。
import { ref } from 'vue'
const count = ref(0)
上面代码创建了一个包含响应式数据的引用对象(RefImp对象)
在js中操作数据:count.value
在模板中读取数据:<div> {{count}} </div>(这里会自动读取value属性)
其实ref可以接受的数据不只是基本数据类型,复杂数据类型也可以,只不过比较麻烦,操作时都要.value
const person = ref({name: 'zzy', age: 18})
person.value.name = 'dantin'
基本数据类型和负责数据类型实现响应式的方式不同,前者依然是Object.defineProperty()的get与set,后者则在内部求助了reactive函数
3.reactive函数
作用:定义一个对象类型的响应式数据(基本类型不要用reactive,要用ref)
import { reactive } from 'vue'
const person = reactive({name: 'zzy', age: 18})
person.name = 'ht'
接收一个对象或数组,返回一个代理对象(Proxy对象),且这里的监视式深层次监视
4.vue3中响应式的原理
对于ref和reactive是不一样的,ref简单类型是通过:Object.defineProperty()的get与set,当然啊,ref定义的复杂类型是通过reactive的Proxy,
而reactive是通过Proxy来实现响应式的(上文提到了),并通过Reflect来操作源数据
不管怎么样,总结来说,vue3中新增的就是对于复杂数据类型通过Proxy实现响应式,也就是两个点:
- 通过
Proxy(代理): 拦截对象中任意属性的变化, 包括:属性的增删、属性值的读写等。 - 通过
Reflect(反射): 对源对象的属性进行上述操作。
(1)vue2中响应式原理
我们知道vue2中是通过Object.defineProperty()对对象类型数据进行劫持并添加getter和setter来监视数据的,对于数组是重写了更新数组的方法。复习vue2监视数据的原理
vue2监视数据存在两个问题:
1、直接新增属性、删除属性, 界面不会更新。2、直接通过下标修改数组, 界面不会自动更新。
(2)Vue3中的Proxy
在vue3中,**解决了vue2中的两个问题。下面是模拟实现vue3中响应式的原理:
const person = {name: 'zzy',age: 18
}const p = new Proxy(person, {get(target, propName) {console.log(target)console.log(`有人读person中的${propName}`)return target[propName]},set(target, propName, value) {console.log(`有人改person中的${propName},修改后的值为:${value}`)target[propName] = value},deleteProperty(target, propName) {console.log(`有人删除了person中的${propName}`)return delete target[propName]}
})

再严谨一些,用Reflect来进行增删改查,这也是框架的做法,其实本质上没什么太大的区别,只是Reflect可以避免一些报错吧,不然还要用try-catch去捕获?这里不用太纠结,其实就是为了让框架更加的友好(少一些报错)
const person = {name: 'zzy',age: 18
}const p = new Proxy(person, {//查get(target, propName) {console.log(target)console.log(`有人读person中的${propName}`)// return target[propName]return Reflect.get(target, propName)},//增&改set(target, propName, value) {console.log(`有人改person中的${propName},修改后的值为:${value}`)// target[propName] = valueReflect.set(target, propName, value)},//删deleteProperty(target, propName) {console.log(`有人删除了person中的${propName}`)// return delete target[propName]return Reflect.deleteProperty(target, propName)}
})
5.reactive和ref的对比
1、定义数据类别不同
ref用于定义基本数据类型(也可以定义复杂类型)
reactive用于定义对象或数组类型
2、原理不同
ref是通过:`Object.defineProperty()`的get与set,当然啊,复杂类型是通过reactive的Proxy
reactive是通过Proxy来实现响应式的(上文提到了),并通过Reflect来操作源数据
3、使用方式不同
ref定义的数据,操作时需要.value,模板读取不需要.value
reactive定义的数据,操作和读取都不需要.value
6.setup的两个注意点
(1)执行时机
setup函数的执行时机是beforeCreate之前,也就是所有生命周期的最前面,此时this是undefined,也就是说在setup中是绝对不能通过this访问组件实例的。
(2)setup的参数
setup接收两个参数:(props,context)
props是一个对象,包含:组件外部传递过来,且组件内部声明接收了的属性。
context是一个对象,包含三个属性,分别是attrs、slots、emit
第一个attrs相当于this.$attrs,值为对象,包含组件外部传递过来,但没有在props配置中声明的属性
第二个slots相当于this.$slots,包含收到的插槽的内容。
第三个emit相当于this.$emit,用来触发组件的自定义事件。
props: ['name', 'age']
setup(props, context) {console.log(props) // Proxy{name:'zzy',age:18}:组件外部传递过来,且组件内部声明接收了的属性。console.log(context.attrs)//相当于this.$attrsconsole.log(context.slots)相当于this.$slotsconsole.log(context.emit)//相当于this.$emit
}
三、计算属性和监视
1.computed函数
和vue2中功能是一样的,只不过变成了一个函数,而且要手动引入。默认写法是传一个回调
import {computed} from 'vue'setup(){...//计算属性——简写(只读readonly)let fullName = computed(()=>{return person.firstName + '-' + person.lastName})
}
当我们去改计算属性的值的时候,控制台可能会有警告:

这是因为计算属性默认是只读的,当它所依赖的值改变的时候,它自己会变。如果要想改计算属性,需要用下面的完整写法,传一个对象,里面有getter和setter,setter中参数是修改后的新值
import {computed} from 'vue'setup(){...//计算属性——完整(包括读和写)let fullName = computed({get(){return person.firstName + '-' + person.lastName},set(value){const nameArr = value.split('-')person.firstName = nameArr[0]person.lastName = nameArr[1]}})
}
2.watch函数
其实watch在vue3中和vue2中功能是一样的,就是写法不一样。
先准备一些数据吧:
import { ref, reactive } from 'vue'
const sum = ref(0)
const msg = ref('hello')
const person = reactive({name: 'dantin'age: 18job: {type: 'code'salary: '1000k'}
})
(1)第一个参数怎么写
情况一:监视ref定义的响应式数据
watch(sum,(newValue,oldValue)=>{console.log('sum变化了',newValue,oldValue)
},{immediate:true})
情况二:监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{console.log('sum或msg变化了',newValue,oldValue)//new和old也是监听值构成的数组
})
情况三:监视reactive定义的响应式数据
这里有两个坑,第一个是reactive定义的数据,监视时回调中无法获得oldValue!oldValue和new一样
第二个坑是,监视reactive定义的数据,默认开启的deep:true,且deep不能改成false
watch(person,(newValue,oldValue)=>{console.log('person变化了',newValue,oldValue)
},{immediate:true,deep:false}) //此处的deep配置不再奏效
情况四:监视reactive定义的响应式数据中的某个属性
这里要注意,第一个参数必须写成箭头函数,如果直接写person.job,那么就相当于写了个死的值,这样是监视不到的。还有就是如果job是一个对象,那么默认deep是false的,如果要深度监视需要手动开启deep:true(deep配置有效)
watch(()=>person.job,(newValue,oldValue)=>{console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
情况五:监视reactive定义的响应式数据中的某些属性
如果这种情况的话和上面类似,不同的是第一个参数写成数组,且每个元素是箭头函数,返回的new和old值也是相对应的值构成的数组。
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
(2)第一个参数到底写不写.value
如果我们把person换成是一个ref定义的呢?那么监视的时候写不写.value?
import { ref, reactive } from 'vue'
const sum = ref(0)
const msg = ref('hello')
const person = ref({name: 'dantin'age: 18job: {type: 'code'salary: '1000k'}
})
答案是:要写的,因为ref对于复杂数据类型,内部是借助reactive的Proxy实现响应式的,所以这么写的话就相当于是写了一个reactive定义的响应式数据,在监视时也就具有了对应的坑(见上文情况三)
watch(person.value,(newValue,oldValue)=>{console.log('person变化了',newValue,oldValue)
},{immediate:true,deep:false}) //此处的deep配置不奏效
除此之外还有一种办法,那就是深度监视person(它是一个RefImpl对象),这样就能监视到其中的value及更深层的变化。这是因为如果直接监视person不读取.value,那么监视的是RefImpl对象,只有其中value的地址变的时候才能监视到,value里面的东西变化是监视不到的,所以要开deep
watch(person,(newValue,oldValue)=>{console.log('person变化了',newValue,oldValue)
},{immediate:true,deep:true})
那为什么简单数据类型不需要.value呢?其实和上面的情况四是一样的,如果简单数据类型直接.value,那么监视的就是一个写死的值。不.value的话,监视的是一个响应式的RefImpl对象,当里面value变化的时候是可以监视到的(这块儿感觉懵懵的,回头看源码吧)
watch(sum,(newValue,oldValue)=>{console.log('sum变化了',newValue,oldValue)
})
如果非要.value,请使用箭头函数动态读取,每次sum变化都会执行回调读取最新的值
watch(() => sum.value,(newValue,oldValue)=>{console.log('sum变化了',newValue,oldValue)
})
3.watchEffect函数
-
watch的套路是:既要指明监视的属性,也要指明监视的回调。
-
watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
watchEffect有点像computed,但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect的回调一上来会先执行一次
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{const x1 = sum.valueconst x2 = person.ageconsole.log('watchEffect配置的回调执行了')
})
其实感觉这玩意儿就是在模仿React中的useEffect
相关文章:
Vue3(一):创建vue3工程、setup、vue3响应式原理、computed和watch
Vue3:第一章 一、创建Vue3.0工程1.使用vue-cli创建2.使用vite创建 二、Vue3中的响应式1.拉开序幕的setup2.ref函数3.reactive函数4.vue3中响应式的原理(1)vue2中响应式原理(2)Vue3中的Proxy 5.reactive和ref的对比6.se…...
Spring中的@Value注解详解
Spring中的Value注解详解 概述 本文配置文件为yml文件 在使用spring框架的项目中,Value是经常使用的注解之一。其功能是将与配置文件中的键对应的值分配给其带注解的属性。在日常使用中,我们常用的功能相对简单。本文使您系统地了解Value的用法。 Value…...
YSL赢麻了?SMI社媒心智品牌榜Top20公布:YSL破局夺魁,国货品牌现后起之秀
全文速览 1.数说故事联合用户说从美妆、彩妆、护肤三板块全新发布《SMI社媒心智品牌榜》。 2.圣罗兰、兰蔻、欧莱雅等法国高端美妆大牌垄断美妆《SMI社媒心智品牌榜》前三甲。 3.彩妆Top20榜单中,底妆产品稳居前列,色彩美妆占据一席之地。 4.护肤TOP…...
链式哈希,一致性哈希,倒排表
在普通的查询中,通过关键码的比较进行查找,而哈希是根据关键码直接定位到数据项 哈希冲突:同一个关键码经过哈希函数后指向同一个记录集 链式哈希 using namespace std; #define M 13 typedef int KeyType; //typedef struct //{ // KeyTyp…...
Python操作XML教程:读取、写入、修改和保存XML文档
目录 导入所需模块解析XML文档获取元素遍历XML文档写入新的元素修改元素的内容和属性删除元素保存修改后的XML文档示例演示python操作xml的常用方法 XML是一种常见的数据交换格式,在许多应用中都被广泛使用。通过掌握Python操作XML的基础知识,您将能够轻…...
Oracle数据库中了locked1勒索病毒,用友nchome配置文件损坏该如何解除
随着互联网技术的不断发展,网络安全问题也越来越受到人们的关注。其中,勒索病毒是一种比较常见的网络安全威胁。最近很多集团企业在使用Oracle数据库的过程中,遭遇到了locked1勒索病毒的攻击,导致企业的用友nchome配置文件损坏&am…...
leecode 数据库: 602. 好友申请 II :谁有最多的好友
数据导入: Create table If Not Exists RequestAccepted (requester_id int not null, accepter_id int null, accept_date date null); Truncate table RequestAccepted; insert into RequestAccepted (requester_id, accepter_id, accept_date) values (1, 2, 20…...
基于 Prometheus 的 SLO告警实战
Prometheus是一个流行的开源监控系统,它可以帮助我们收集、存储和查询应用程序或系统的时间序列数据。在使用Prometheus进行监控时,通常需要根据服务水平指标(Service Level Objectives,简称SLO)来设置告警规则。 SLO…...
调用百度API实现图像风格转换
目录 1、作者介绍2、基本概念2.1 人工智能云服务与百度智能云2.2 图像风格转换 3、调用百度API实现图像风格转换3.1 配置百度智能云平台3.2 环境配置3.3 完整代码实现3.4 效果展示3.5 问题与分析 1、作者介绍 张元帮,男,西安工程大学电子信息学院&#…...
5个最好的WooCommerce商城自动化动作来增加销售量
您是否正在寻找简单智能的方法来自动执行任务并增加 WooCommerce 商店的销售额? 通过在线商店中的自动化任务,您可以在发展业务和增加销售额的同时节省时间和金钱。 在本文中,我们将向您展示如何使用 WooCommerce商城自动化来增加销售额。 …...
打开数据结构大门——实现小小顺序表
文章目录 前言顺序表的概念及分类搭建项目(Seqlist):apple:搭建一个顺序表结构&&定义所需头文件&&函数:banana:初始化:pear:打印:watermelon:数据个数:smile:检查容量:fireworks:判空:tea:在尾部插入数据:tomato:在尾部删除数据:lemon:在…...
一.RxJava
1.RxJava使用场景 RxJava核心思想 Rx思维:响应式编程,从起点到终点,中途不能断掉,并且可以在中途添加拦截. 生活中的例子: 起点(分发事件,我饿了)->下楼->去餐厅->点餐->终点(吃饭,消费事件) 程序中的例子: 起点(分发事件,点击登录)->登录API->请求服务器-…...
如何使用 VSCode 软件运行C代码
VSCode 的下载和扩展的配置可以参考文章:VSCode 的安装与插件配置。 VSCode 是很好用的编辑器,通过给其配置 MinGW-w64 插件就可以在它上面编译运行C代码了。 在没有配置 MinGW-w64 插件时,在 VSCode 中运行下面的代码后打印如下图所示。 这…...
C# 调用Matlab打包的 DLL文件(傻瓜式操作)
1、准备Matlab代码 2. 打包 在matlab命令行窗口输入deploytool,打开MATLAB Complier,选择Library Compiler 在TYPE中选择.NET Assembly;在EXPORTED FUNCTIONS中选择要打包的文件;可以选择为自己打包的文件自定义NameSpace名称,本例中将NameSpace定义为…...
微信小程序学习实录3(环境部署、百度地图微信小程序、单击更换图标、弹窗信息、导航、支持腾讯百度高德地图调起)
百度地图微信小程序 一、环境部署1.need to be declared in the requiredPrivateInfos2.api.map.baidu.com 不在以下 request 合法域名3.width and heigth of marker id 9 are required 二、核心代码(一)逻辑层index.js(二)渲染层…...
【面试题】中高级前端工程师都需要熟悉的技能--前端缓存
前端缓存 一、前言二、web缓存分类1. HTTP缓存:2. 浏览器缓存:3. Service Worker:4. Web Storage缓存:5. 内存缓存: 三、http缓存详解1、http缓存类型a. 基于有效时间的缓存控制:b. 基于资源标识的缓存&…...
小红书数据分析:首播卖6亿,小红书直播开启新纪元!
5月22日,章小蕙在小红书开启了第一场带货直播。继董洁之后,小红书又迎来一位超级带货KOL。 据千瓜数据显示,相关话题#章小蕙小红书直播#上线不到30天,话题浏览量就高达2814.89万,笔记互动量达22.24万。 图 | 千瓜数据…...
Weex中,关于组件的水平排列竖直排列居中对齐居左对齐居右对齐低部对齐顶部对齐布局对齐说明
容器内子组件排列方向 子组件竖直方向排列(默认) 子组件水平方向排列 <style> .container {flex-direction: row;direction: ltr; } </style>子组件在父组件容器中的对齐方式 我们主要使用两个属性实现子组件在父组件的对齐方式ÿ…...
服务(第二十八篇)rsync
配置rsync源服务器: #建立/etc/rsyncd.conf 配置文件 vim /etc/rsyncd.conf #添加以下配置项 uid root gid root use chroot yes #禁锢在源目录 address 192.168.80.10 …...
Vue 3 第二十五章:插件(Plugins)
文章目录 1. 创建插件2. 使用插件3. 插件选项 Vue 3 的插件系统允许我们扩展 Vue 的功能和行为,并且可以在多个组件之间共享代码和逻辑。插件可以用于添加全局组件、指令、混入、过滤器等,并且可以在应用程序启动时自动安装。 1. 创建插件 创建插件需要…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
