当前位置: 首页 > news >正文

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中响应式的原理

对于refreactive是不一样的,ref简单类型是通过:Object.defineProperty()getset,当然啊,ref定义的复杂类型是通过reactiveProxy

reactive是通过Proxy来实现响应式的(上文提到了),并通过Reflect来操作源数据

不管怎么样,总结来说,vue3中新增的就是对于复杂数据类型通过Proxy实现响应式,也就是两个点:

  1. 通过Proxy(代理): 拦截对象中任意属性的变化, 包括:属性的增删、属性值的读写等。
  2. 通过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之前,也就是所有生命周期的最前面,此时thisundefined,也就是说在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})
}

当我们去改计算属性的值的时候,控制台可能会有警告:

在这里插入图片描述
这是因为计算属性默认是只读的,当它所依赖的值改变的时候,它自己会变。如果要想改计算属性,需要用下面的完整写法,传一个对象,里面有gettersettersetter中参数是修改后的新值

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是一个对象,那么默认deepfalse的,如果要深度监视需要手动开启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对于复杂数据类型,内部是借助reactiveProxy实现响应式的,所以这么写的话就相当于是写了一个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函数

  1. watch的套路是:既要指明监视的属性,也要指明监视的回调。

  2. 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&#xff1a;第一章 一、创建Vue3.0工程1.使用vue-cli创建2.使用vite创建 二、Vue3中的响应式1.拉开序幕的setup2.ref函数3.reactive函数4.vue3中响应式的原理&#xff08;1&#xff09;vue2中响应式原理&#xff08;2&#xff09;Vue3中的Proxy 5.reactive和ref的对比6.se…...

Spring中的@Value注解详解

Spring中的Value注解详解 概述 本文配置文件为yml文件 在使用spring框架的项目中&#xff0c;Value是经常使用的注解之一。其功能是将与配置文件中的键对应的值分配给其带注解的属性。在日常使用中&#xff0c;我们常用的功能相对简单。本文使您系统地了解Value的用法。 Value…...

YSL赢麻了?SMI社媒心智品牌榜Top20公布:YSL破局夺魁,国货品牌现后起之秀

全文速览 1.数说故事联合用户说从美妆、彩妆、护肤三板块全新发布《SMI社媒心智品牌榜》。 2.圣罗兰、兰蔻、欧莱雅等法国高端美妆大牌垄断美妆《SMI社媒心智品牌榜》前三甲。 3.彩妆Top20榜单中&#xff0c;底妆产品稳居前列&#xff0c;色彩美妆占据一席之地。 4.护肤TOP…...

链式哈希,一致性哈希,倒排表

在普通的查询中&#xff0c;通过关键码的比较进行查找&#xff0c;而哈希是根据关键码直接定位到数据项 哈希冲突&#xff1a;同一个关键码经过哈希函数后指向同一个记录集 链式哈希 using namespace std; #define M 13 typedef int KeyType; //typedef struct //{ // KeyTyp…...

Python操作XML教程:读取、写入、修改和保存XML文档

目录 导入所需模块解析XML文档获取元素遍历XML文档写入新的元素修改元素的内容和属性删除元素保存修改后的XML文档示例演示python操作xml的常用方法 XML是一种常见的数据交换格式&#xff0c;在许多应用中都被广泛使用。通过掌握Python操作XML的基础知识&#xff0c;您将能够轻…...

Oracle数据库中了locked1勒索病毒,用友nchome配置文件损坏该如何解除

随着互联网技术的不断发展&#xff0c;网络安全问题也越来越受到人们的关注。其中&#xff0c;勒索病毒是一种比较常见的网络安全威胁。最近很多集团企业在使用Oracle数据库的过程中&#xff0c;遭遇到了locked1勒索病毒的攻击&#xff0c;导致企业的用友nchome配置文件损坏&am…...

leecode 数据库: 602. 好友申请 II :谁有最多的好友

数据导入&#xff1a; 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是一个流行的开源监控系统&#xff0c;它可以帮助我们收集、存储和查询应用程序或系统的时间序列数据。在使用Prometheus进行监控时&#xff0c;通常需要根据服务水平指标&#xff08;Service Level Objectives&#xff0c;简称SLO&#xff09;来设置告警规则。 SLO…...

调用百度API实现图像风格转换

目录 1、作者介绍2、基本概念2.1 人工智能云服务与百度智能云2.2 图像风格转换 3、调用百度API实现图像风格转换3.1 配置百度智能云平台3.2 环境配置3.3 完整代码实现3.4 效果展示3.5 问题与分析 1、作者介绍 张元帮&#xff0c;男&#xff0c;西安工程大学电子信息学院&#…...

5个最好的WooCommerce商城自动化动作来增加销售量

您是否正在寻找简单智能的方法来自动执行任务并增加 WooCommerce 商店的销售额&#xff1f; 通过在线商店中的自动化任务&#xff0c;您可以在发展业务和增加销售额的同时节省时间和金钱。 在本文中&#xff0c;我们将向您展示如何使用 WooCommerce商城自动化来增加销售额。 …...

打开数据结构大门——实现小小顺序表

文章目录 前言顺序表的概念及分类搭建项目&#xff08;Seqlist&#xff09;:apple:搭建一个顺序表结构&&定义所需头文件&&函数:banana:初始化:pear:打印:watermelon:数据个数:smile:检查容量:fireworks:判空:tea:在尾部插入数据:tomato:在尾部删除数据:lemon:在…...

一.RxJava

1.RxJava使用场景 RxJava核心思想 Rx思维:响应式编程,从起点到终点,中途不能断掉,并且可以在中途添加拦截. 生活中的例子: 起点(分发事件,我饿了)->下楼->去餐厅->点餐->终点(吃饭,消费事件) 程序中的例子: 起点(分发事件,点击登录)->登录API->请求服务器-…...

如何使用 VSCode 软件运行C代码

VSCode 的下载和扩展的配置可以参考文章&#xff1a;VSCode 的安装与插件配置。 VSCode 是很好用的编辑器&#xff0c;通过给其配置 MinGW-w64 插件就可以在它上面编译运行C代码了。 在没有配置 MinGW-w64 插件时&#xff0c;在 VSCode 中运行下面的代码后打印如下图所示。 这…...

C# 调用Matlab打包的 DLL文件(傻瓜式操作)

1、准备Matlab代码 2. 打包 在matlab命令行窗口输入deploytool,打开MATLAB Complier,选择Library Compiler 在TYPE中选择.NET Assembly;在EXPORTED FUNCTIONS中选择要打包的文件&#xff1b;可以选择为自己打包的文件自定义NameSpace名称&#xff0c;本例中将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 二、核心代码&#xff08;一&#xff09;逻辑层index.js&#xff08;二&#xff09;渲染层…...

【面试题】中高级前端工程师都需要熟悉的技能--前端缓存

前端缓存 一、前言二、web缓存分类1. HTTP缓存&#xff1a;2. 浏览器缓存&#xff1a;3. Service Worker&#xff1a;4. Web Storage缓存&#xff1a;5. 内存缓存&#xff1a; 三、http缓存详解1、http缓存类型a. 基于有效时间的缓存控制&#xff1a;b. 基于资源标识的缓存&…...

小红书数据分析:首播卖6亿,小红书直播开启新纪元!

5月22日&#xff0c;章小蕙在小红书开启了第一场带货直播。继董洁之后&#xff0c;小红书又迎来一位超级带货KOL。 据千瓜数据显示&#xff0c;相关话题#章小蕙小红书直播#上线不到30天&#xff0c;话题浏览量就高达2814.89万&#xff0c;笔记互动量达22.24万。 图 | 千瓜数据…...

Weex中,关于组件的水平排列竖直排列居中对齐居左对齐居右对齐低部对齐顶部对齐布局对齐说明

容器内子组件排列方向 子组件竖直方向排列&#xff08;默认&#xff09; 子组件水平方向排列 <style> .container {flex-direction: row;direction: ltr; } </style>子组件在父组件容器中的对齐方式 我们主要使用两个属性实现子组件在父组件的对齐方式&#xff…...

服务(第二十八篇)rsync

配置rsync源服务器&#xff1a; #建立/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 的功能和行为&#xff0c;并且可以在多个组件之间共享代码和逻辑。插件可以用于添加全局组件、指令、混入、过滤器等&#xff0c;并且可以在应用程序启动时自动安装。 1. 创建插件 创建插件需要…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...