转战VUE3学习

news2024/11/23 12:49:07

安装好vue3后,开始新的项目吧!

npm init vue@latest

1.组合式API

在以前vue2的项目里,使用的选项式API将各种不同逻辑的代码分散到像data、methods等不同的对象里。如果想看某一方面的逻辑,鼠标滚轮都要磨出火星了!

而升级到vue3之后组合式API就解决了这一难题。
在这里插入图片描述

1.1拉开序幕的setup

setup是所有组合式API表演的舞台。组件中所用到的数据、方法,均要配置在setup中。

//setup其实是一个函数
export default {
	name : 'APP',
	setup : function(){
	}
}
//函数可简写
export default {
	name : 'APP',
	setup(){
	}
}
//添加数据和方法
export default {
	name : 'APP',
	setup(){
		//数据
		let name = '张三'
		let age = 18
		//方法
		function sayHello(){
			alert("我是${name},我已经${age}岁了")
		}
	}
}

setup有返回值,有两种返回值:
(1)若返回对象,则对象中的属性、方法在模板中可以直接使用。(重点)
(2)若返回渲染函数,则可以自定义渲染的内容。(了解)

<template>
	<h1>姓名:{{ name }}</h1>
	<h1>年龄:{{ age }}</h1>
	<button @click="sayHello">说话</button>
</template>
<script>
export default {
	name : 'APP',
	setup(){
		//数据
		let name = '张三'
		let age = 18
		//方法
		function sayHello(){
			alert("我是${name},我已经${age}岁了")
		}
		//setup返回对象    return {name:name,age:age}   
		return {name,age,sayHello} //setup返回对象的简写形式(常用)
		//返回渲染函数
		//return () => h('h1','您好')
	}
}
</script>

1.2 兼容vue2

在vue3中其实也可以继续用vue2的写法。
在vue2的配置中可以读取vue3的配置,但是vue3的配置中不能读取vue2的配置。

<template>
	<h1>姓名:{{ name }}</h1>
	<h1>年龄:{{ age }}</h1>
	<h1>性别:{{ sex }}</h1>
	<button @click="sayHello">说话</button>
	<button @click="sayWelcome">欢迎</button>
</template>
<script>
export default {
	name : 'APP',
	data(){
		return {
			sex:'男'
		}
	},
	methods : {
		sayWelcome(){
			alert('欢迎')
		}
	},
	setup(){
		//数据
		let name = '张三'
		let age = 18
		//方法
		function sayHello(){
			alert("我是${name},我已经${age}岁了")
		}
		return {name,age,sayHello} 
	}
}
</script>

但是不建议vue3与vue2的配置混用!

1.3 ref函数

在之前setup中写的数据,并不是响应式的。当修改数据时,在模板中的数据没有相应的变化。因此,需要通过一个函数ref来讲数据变成响应式的。

<template>
	<h1>姓名:{{ name }}</h1>
	<h1>年龄:{{ age }}</h1>
	<button @click="changeInfo">修改个人信息</button>
</template>
<script>
export default {
	name : 'APP',
	setup(){
		//数据
		let name = '张三'
		let age = 18
		//方法
		function changeInfo(){
			name = '李四'
			age = 48
			console.log(name,age) //数据修改了,但是没响应到模板中
		}
		return {name,age,changeInfo} 
	}
}
</script>

现在引入ref函数,将初始化的字面量用ref函数包裹起来。

<script>
import {ref} from 'vue'
export default {
	name : 'APP',
	setup(){
		//数据
		let name = ref('张三')
		let age = ref(18)
		//方法
		function changeInfo(){
			// name = '李四'
			// age = 48
			console.log(name,age) //数据修改了,但是没响应到模板中
		}
		return {name,age,changeInfo} 
	}
}
</script>

用ref函数包裹的数据实际上是RefImpl的引用实现对象。
在这里插入图片描述
修改数据的方式需要使用value来修改。但是在模板中不用.value访问数据,因为vue3自动解析RefImpl对象的值了。

<template>
	<h1>姓名:{{ name }}</h1>
	<h1>年龄:{{ age }}</h1>
	<button @click="changeInfo">修改个人信息</button>
</template>
<script>
import {ref} from 'vue'
export default {
	name : 'APP',
	setup(){
		//数据
		let name = ref('张三')
		let age = ref(18)
		//方法
		function changeInfo(){
			name.value = '李四'
			age.value = 48
		}
		return {name,age,changeInfo} 
	}
}
</script>

当用ref函数包裹对象时,也需要value才能访问内部的值。

<template>
	<h1>姓名:{{ name }}</h1>
	<h1>年龄:{{ age }}</h1>
	<button @click="changeInfo">修改个人信息</button>
</template>
<script>
import {ref} from 'vue'
export default {
	name : 'APP',
	setup(){
		//数据
		let name = ref('张三')
		let age = ref(18) 
		let job = ref({
			type : '前端工程师',
			salary : '30k' 
		})
		//方法
		function changeInfo(){
			job.value.type = '李四'
			job.value.salary = '60k'
		}
		return {name,age,changeInfo} 
	}
}
</script>

但是,按道理RefImpl内部的值应该也是RefImpl的对象,但是实际上我们发现内部用的是Proxy对象。其实ref包裹对象类型数据时,借用了reactive函数。
在这里插入图片描述

总结:

  • 作用:定义一个响应式的数据
  • 语法:const xxx = ref(initValue)
  • 创建一个包含响应式数据的引用对象(ref对象)
  • js中操作数据:xxx.value 模板中读取数据:不需要.value,直接
    <div>{{xxx}}<div>
  • 接收的数据可以是基本类型,也可以是对象类型。
  • 基本类型的数据的响应式是靠Object.defineProperty()的get与set完成的。

1.4 reactive函数

在vue中,reactive函数(响应)的作用定义一个对象类型的响应式数据。(基本类型不用它,要用ref函数)

<script>
import {ref, reactive} from 'vue'
export default {
	name : 'APP',
	setup(){
		//数据
		let number = reactive(666)
		//方法
		function changeInfo(){
			console.log(number)
		}
		return {name,age,changeInfo} 
	}
}
</script>

若将reactive直接用于基本数据类型就会报错。
在这里插入图片描述
因此

<template>
	<h1>姓名:{{ name }}</h1>
	<h1>年龄:{{ age }}</h1>
	<button @click="changeInfo">修改个人信息</button>
</template>
<script>
import {ref} from 'vue'
export default {
	name : 'APP',
	setup(){
		//数据
		let name = ref('张三')
		let age = ref(18) 
		let job = reactive({
			type : '前端工程师',
			salary : '30k' 
		})
		//方法
		function changeInfo(){
			console.log(job)
		}
		return {name,age,changeInfo} 
	}
}
</script>

可以看到,reactive将对象类型的数据封装为Proxy对象。
在这里插入图片描述
使用reactive的好处:
支持修改深层属性
支持修改数组

<script>
import {ref} from 'vue'
export default {
	name : 'APP',
	setup(){
		//数据
		let name = ref('张三')
		let age = ref(18) 
		let job = reactive({
			type : '前端工程师',
			salary : '30k' ,
			a:{
				b:{
					c:666
				}
			}
		})
		let hobby = reactive(['抽烟','喝酒','烫头'])
		//方法
		function changeInfo(){
			job.a.b.c = 999 //reactive支持修改深层属性
			hobby[0] = '学习'  //reactive支持修改数组			
		}
		return {name,age,changeInfo} 
	}
}
</script>

reactive与ref的对比

(1)ref访问属性需要使用value,reactive访问属性不需要使用value
(2)ref定义基本数据类型,reactive定义对象类型
(3)ref的响应式原理是通过Object.defineProperty()实现的,reactive通过Proxy对象实现的。

//数据
let name = ref('张三')
let age = ref(18) 
//方法
function changeInfo(){
	name.value = '李四'		
	age.value = 44
}
//数据
let person= reactive({name:'张三',age:18})
//方法
function changeInfo(){
	person.name = '李四'		
	person.age = 44
}

1.5 setup的注意点

(1)setup函数的执行比beforeCreate函数要早
(2)setup函数里的this是undefined,这意味着setup里不能用this
(3)setup只能收到两个参数,分别是props用来接受父组件传给该组件的属性,以及context用来保存上下文信息。

<script>
import {ref} from 'vue'
export default {
	name : 'APP',
	beforeCreate(){
		console.log('---beforeCreate---')	
	},
	setup(){
		console.log('---setup---',this)	
		return {} 
	}
}
</script>

在这里插入图片描述
props传输

<script>
export default {
	name : 'APP',
	props: ['msg','school'], //必须声明props才能接受属性
	beforeCreate(){
		console.log('---beforeCreate---')	
	},
	setup(props){ //通过props可以访问父组件传过来的值
		console.log(props)	
		console.log(props.msg)
		console.log(props.school)
		return {} 
	}
}
</script>

上下文context

<script>
export default {
	name : 'APP',
	props: ['msg','school'],
	beforeCreate(){
		console.log('---beforeCreate---')	
	},
	setup(props,context){
		console.log(context)	
		return {} 
	}
}
</script>

context里面是一个expose对象,它包含attrsemitslots对象。

其中,attrs对象接收遗漏的props中未声明的属性。(相当于vue2中的$attrs)

emit对象接收分发的自定义事件。(相当于vue2中的$emit)

slots对象接收传入包裹的slot中未声明的DOM节点。(相当于vue2中 的$slots)

在这里插入图片描述

//App.vue
<template>
	<Demo @hello="handleHello"></Demo>
</template>
<script>
import {Demo} from './compnents/Demo'
export default {
	name : 'App',
	setup(){
		//方法
		function handleHello(value){
			alert('触发了Hello事件,我收到的参数是${value}')
		}
		return {handleHello} 
	}
}
</script>
//Demo.vue
<template>
	<button @click="test">测试触发一下Demo组件的hello事件</button>
</template>
<script>
import {ref} from 'vue'
export default {
	name : 'App',
	props:['msg'],
	emits:['hello'], //vue3中应该声明将触发的hello事件,否则会有警告
	setup(props,context){
		function test(){
			context.emit('hello',666) //不能用this,必须用context触发外部事件
		}
		return {test} 
	}
}
</script>

2. computed计算属性

在vue2中,计算属性是由其他属性派生出来的属性。在vue3中,计算属性写在setup中,并且需要再引入

<!-- vue2写法 -->
<template>
	姓: <input type="text" v-model="person.firstName">
	<br>
	名: <input type="text" v-model="person.lastName">
	<br>
	<span>全名: {{ fullName}}</span>
</template>
<script>
import {reactive} from 'vue'
export default {
	name : 'App',
	//计算属性
	computed: {
		fullName(){
			return this.person.firstName + '-' + this.person.lastName
		}
	},
	setup(props,context){
		let person = reactive({
			firstName : '张',
			lastName : '三'
		})
		return {person} 
	}
}
</script>

vue3写法

<!-- vue3写法 -->
<template>
	姓: <input type="text" v-model="person.firstName">
	<br>
	名: <input type="text" v-model="person.lastName">
	<br>
	<span>全名: {{ fullName}}</span>
</template>
<script>
import {reactive,computed} from 'vue'
export default {
	name : 'App',
	setup(props,context){
		let person = reactive({
			firstName : '张',
			lastName : '三'
		})
		//计算属性,由于fullName是person派生出的属性,建议放在person对象里新增
		person.fullName = computed(()=>{
			return person.firstName + "-" + person.lastName
		}
		)
		return {person} 
	}
}
</script>

上述代码中,computed是简写形式,只能读,不能修改。因此需要改成下面的完整形式

<!-- vue3写法 -->
<template>
	姓: <input type="text" v-model="person.firstName">
	<br>
	名: <input type="text" v-model="person.lastName">
	<br>
	全名: <input type="text" v-model="person.fullName">
</template>
<script>
import {reactive,computed} from 'vue'
export default {
	name : 'App',
	setup(props,context){
		let person = reactive({
			firstName : '张',
			lastName : '三'
		})
		//计算属性,完整形式,同时考虑读写
		person.fullName = computed({
			get(){
				return person.firstName + "-" + person.lastName
			},
			set(value){
				const nameAttr = value.split('-')
				person.firstName = nameAttr[0]
				person.lastName= nameAttr[1]
			}
		})
		return {person} 
	}
}
</script>

3. watch监视函数

在vue3中watch监视函数的用法如下:

<template>
	<span>{{sum}}</span>
	<button @click="sum++">点我加1</button>	
</template>
<script>
import {ref,watch} from 'vue'
export default {
	name : 'App',
	setup(props,context){
		let sum = ref(0)
		let person = reactive({
			name: '张三',
			age: 18,
			job:{
				salary:20
			}
		})
		//情况一:监听ref所定义的一个响应式数据
		watch(sum,(newValue,oldValue)=>{
			console.log('sum变了',newValue,oldValue)
		})
		//情况二:监视ref所定义的多个响应式数据,第一个参数配置成数组
		watch([sum,msg],(newValue,oldValue)=>{
			console.log('sum或msg变了',newValue,oldValue)
		})
		//情况三:希望可以立马执行watch的监视,而不用等变化后,
		//解决方式:第三个参数可以填配置信息,
		watch(sum,(newValue,oldValue)=>{
			console.log('sum变了',newValue,oldValue)
		},{immediate:true,deep:true})
		//情况四:监听reactive所定义的一个响应式数据
		//1.注意vue3这里有个bug,无法监控到oldValue的值
		//2.注意vue3中reactive绑定了深度监视,配置deep无法关闭深层监视
		watch(person,(newValue,oldValue)=>{
			console.log('person变了',newValue,oldValue)
		},{deep:false})
		//情况五:监听reactive对象中的某个属性,需要写匿名函数
		watch(()=>person.name,(newValue,oldValue)=>{
			console.log('person变了',newValue,oldValue)
		})
		//情况六:监听reactive对象中的某些属性,需要封装在数组中
		watch([()=>person.name,()=>person.age],(newValue,oldValue)=>{
			console.log('person的name和age变了',newValue,oldValue)
		})
		//特殊七:若监视的reactive对象中的某个对象,则必须开启deep深层监视的配置。
		watch(()=>person.job,(newValue,oldValue)=>{
			console.log('person的job变了',newValue,oldValue)
		},{deep:false})
		return {sum} 
	}
}
</script>

watchEffect函数

watchEffect函数可以智能判断属性的变化,不用指明监视哪个属性,监视的回调中用到哪个属性,就监视哪个属性。
类似于computed函数,不过watchEffect更注重过程,所以不用写返回值。

<script>
import {ref,watch} from 'vue'
export default {
	name : 'App',
	setup(props,context){
		let sum = ref(0)
		let person = reactive({
			name: '张三',
			age: 18,
			job:{
				salary:20
			}
		})
		watchEffect(()=>{
			const x1 = sum.value //用到哪个属性,就监测哪个
			console.log('watchEffect执行的回调执行了')
		})
		return {sum} 
	}
}
</script>

4. vue3里的声明周期

//待续…

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LLM的工程实践思考

陆奇博士的主题演讲《新范式 新时代 新机会》非常震撼人心。我远程参加了深圳站和北京站两场演讲&#xff0c;深受感触。虽然了解大模型的机制和原理以了解新的范式非常重要&#xff0c;但是“行胜于言”&#xff0c;基于大模型的众多应用都需要工程技术才能落地。然而&#xf…

Ndk c++层 crash问题分析

首先你要从设备上拿到墓碑文件&#xff1a;tombstone&#xff0c;这里面会记录系统崩溃时的信息。位置在/data/tombstones目录下&#xff08;Logcat中也会有相应的信息&#xff09;&#xff0c;文件的确就像墓碑一样记录了死亡了的进程的基本信息&#xff08;例如进程的进程号&…

FlashAttention和PagedAttention

FlashAttention FlashAttention一般指的是FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness这篇&#xff0c;当然Transformer Quality in Linear Time这篇里非要说FLASH Fast Linear Attention with a Single Head&#xff0c;命名有点无语&…

JavaScript数据存储方式

内置对象 js内部提供的对象&#xff0c;包含各种属性和方法给开发者调用 document.write() console.log() Math Math对象是js提供的一个 “数学”对象&#xff0c;提供了一系列做数学运算的方法 max找最大值Math.max(3,8,5,4) 返回8min找最小值Math.min(3,8,5,4) 返回4ab…

printf不一样的玩法

Printf不一样的玩法 ❝ 在使用linux终端命令的时候&#xff0c;我们可以看到像more命令&#xff0c;它的显示方式与一般的字符串不同&#xff0c;是用了反显。同样&#xff0c;linux C下printf还有很多其他不常见的格式化输出形式。本文主要为你盘点这些形式。 ❞ 先看下效果&a…

MySQL:单行函数(全面详解)

MySQL&#xff1a;单行函数 前言一、函数的理解1、什么是函数2、不同DBMS函数的差异3、MySQL的内置函数及分类 二、数值函数1、基本函数2、角度与弧度互换函数3、三角函数4、指数与对数5、进制间的转换 三、字符串函数四、日期和时间函数1、获取日期、时间2、日期与时间戳的转换…

Bpmn.js流程建模结合业务整合工作流(二)

上一篇文章讲述了bpmn.js的基本搭建使用过程,下面介绍工具栏的按钮使用 以及右侧属性如何绑定到节点保存的 保存方法 /** 保存xml */async save() {await this.getNewXML() //获取最新的xmlawait this.getRootElement() //获取流程基本信息 节点信息const params = {name: th…

SSM+校园网上订餐系统 毕业设计-附源码211510

校园网上订餐系统的设计与实现 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对校园网上订…

API 接口协作,swagger不再是第一选择了

目录 一、前言 1.1. 场景一、后端视角&#xff1a; 1.2. 场景二、前端视角&#xff1a; 1.3. 场景三、测试视角&#xff1a; 二、Apifox 2.1 场景一、后端视角&#xff1a; 漂亮的接口文档 2.2 场景二、前端视角&#xff1a; 2.3 场景三、测试视角&#xff1a; 三、总…

SOAP教程

参考 SOAP 教程 1、介绍 SOAP 中文解释为&#xff1a;简单对象访问协议。 SOAP 是一种简单的基于 XML 的协议&#xff0c;它使应用程序通过 HTTP 来交换信息。 SOAP 是基于 XML 的简易协议&#xff0c;可使应用程序在 HTTP 之上进行信息交换。或者更简单地说&#xff1a;SOAP…

ASP.NET Core Web API之Token验证

在实际开发中&#xff0c;我们经常需要对外提供接口以便客户获取数据&#xff0c;由于数据属于私密信息&#xff0c;并不能随意供其他人访问&#xff0c;所以就需要验证客户身份。那么如何才能验证客户的身份呢&#xff1f;今天以一个简单的小例子&#xff0c;简述ASP.NET Core…

一、枚举类型——使用枚举类型分发

如果将 RoShamBo1.java 直接转换为基于枚举的实现版本&#xff0c;则会出现问题。因为枚举实例并不是类型&#xff0c;所以无法重载 eval() 方法&#xff0c;你无法将枚举实例作为参数类型。不过&#xff0c;还有别的方法可以利用枚举来实现多路分发。 一种方法是通过构造方法…

实战:SonarQube平台安装配置-2023.6.24(安装成功)(docker方式)

实战&#xff1a;SonarQube平台安装配置-2023.6.24(安装成功)(docker方式) 目录 推荐文章 https://www.yuque.com/xyy-onlyone/aevhhf?# 《玩转Typora》 实验环境 sonarqube:9.9.0-community (docker方式部署) SonarScanner 4.8.0.2856 (部署在宿主机上)实验软件 链接&…

开关电源-PFC驱动电路的工作原理

PFC驱动电路的工作原理 由于PFC的控制地和MOS管组成的双向开关的源极不共地&#xff0c;因此需要解决开关管浮地驱动问题。 图2 驱动电路图 电路图说明&#xff1a; PFCPWM是DSP的PWM信号&#xff1b;VCC_4V和AGND是DSP侧的电源和控制地&#xff1b;Vccp_14V和AGND_DRV是MO…

echarts 的 一个图表容器,使用grid存放多个折线图,并配置x轴联动

效果图 配置参数 // prettier-ignore const data [["2000-06-05", 116], ["2000-06-06", 129], ["2000-06-07", 135], ["2000-06-08", 86], ["2000-06-09", 73], ["2000-06-10", 85], ["2000-06-11",…

开关电源- 用PFC拓扑电路对比

用PFC拓扑电路对比 最基本的有桥boost PFC电路 有桥boostPFC电路是最基本的电路&#xff0c;就不叙述了。 双Boost无桥PFC 双boost无桥拓扑的优点是使用功率元件比较少, 两个管子可以一起驱动, 这简化了驱动电路的设计, 同时让直接使用传统APFC的控制芯片成为可能.但是这种拓扑…

3.41 - haas506与esp8266-01s的串口通信(TCP透传)

haas506与esp8266-01s的串口通信 PC端调试wifi模块1.接线(与电脑通信)2.模式案例3.指令演示 开发板与wifi模块通信1.接线(TTL串口通信)2.代码测试 PC端调试wifi模块 esp8266-01s 1.接线(与电脑通信) 与电脑通信时引脚连接&#xff0c;wifi模块需要稳定3.3v供电&#xff0c;…

一个618项目的复盘总结反思

一、前言 618期间上线一个活动项目。但上线不顺利&#xff0c;当天就出现了性能问题&#xff0c;接口超时&#xff0c;用户无法打开网页&#xff0c;最后不得的临时下线。花了三天两夜&#xff0c;重构了后台核心代码&#xff0c;才让活动进行下去。 回头看了一下自己的时间记…

【零基础入门学习Python---Python条件和循环语句】

&#x1f680; Python &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

OpenCV下载、环境变量配置

https://sourceforge.net/projects/opencvlibrary/files/ 选择合适的版本下载即可 这里使用opencv-3.1.0.exe执行 将需要bin目录加入到环境变量Path D:\opencv\31\opencv\build\x64\vc14\bin #include<opencv2/opencv.hpp> #include <iostream> using namespace …