uniapp入门到进阶(必备知识扩展-1) - vue3你不知道的那些事
ztj100 2024-11-26 11:15 12 浏览 0 评论
一、组合式API
1、setup函数:组件中所有数据、方法、钩子函数等存放的容器,返回值有两个:
在beforeCreate之前调用,没有this
setup函数有两参数 setup(props,context)
props外部传入、内部声明接受的属性,值为对象;
context 包含
1、 attrs外部传入,props未声明,相当于this.$attrs;
2、slots收到的插槽相当于this.$slots,
3、emit 函数,相当于this.$emit
返回对象:则对象内的属性、方法可在模板直接使用;
若返回渲染模板函数,我们可以自定义渲染的内容
例如:
<script lang="ts">
import { h } from 'vue'
exportt default {
name:'myApp',
setup(props,context){
//属性
const name = '胖奶奶与胖小伙'
//方法
const Hi = (name:string):voild =>{
console.log('Hi'+name)
}
//必须返回在模版才可以用,返回对象
return {
name,
Hi
}
//返回渲染函数,需要我们引入 h
return () => {
return h('span','我是渲染函数')
}
}
}
</script>
2、ref,reactive的使用
<script lang="ts">
//引入ref 、reactive
import { ref, reactive } from 'vue'
exportt default {
name:'myApp',
setup(){
//声明响应数据 name
//`基本类型数据`,不存在数据劫持
const name = ref('胖奶奶与胖小伙')
//修改 name .value不可缺少 ,模板中使用不用 `.value`
name.value = '我改变了'
//获取 name
console.log(name.value)
//reactive,Proxy代理对象数据劫持实现响应式
//1、对象类型数据
//**`处理一个响应式的对象数据` 注意无法处理基本类型数据**
const msgList = reactive({
name:'',
job:'挖矿小伙'
})
//修改数据
msgList.name = '胖奶奶与胖小伙'
//获取数据job
console.log(msgList.job)
//2、数组数据
const study = reactive(['语文','数学','体育'] )
//修改 语文
study[0] = '政治'
//获取 数学
console.log(study[1])
}
}
</script>
3、理解vue3响应式实现原理
在vue2中:存在的问题及解决方案,新增、删除数据或直接下标修改数组,页面无法更新
<script lang="ts">
import vue from 'vue'
exportt default {
name:'myApp',
data(){
return {
userMsg:{
name:'胖奶奶与胖小伙',
age:18
}
}
},
methods(){
//在userMsg添加一个学历
addEdu(){
//该写发不生效
this.userMsg.edu = '小学'
//正确写法
this.$set(this.userMsg,'edu','小学')
//or
vue.set(this.userMsg,'edu','小学')
},
delName(){
//该写发不生效
delete this.userMsg.name
//正确写法
this.$delete('this.userMsg','name')
//or
vue.set(this.userMsg,'name','胖奶奶与胖小伙')
}
}
}
</script>
在vue3中响应式实现的原理,解决了Vue2存在的问题
<script lang="ts">
//原始数据
let userMsg = {
name:'胖奶奶与胖小伙',
age:18
}
//vue2响应式模拟,无法捕获添加,删除
let uMsg = {}
Object.defineProperty(uMsg,'name',{
get(){
return userMsg.name
},
set(){
console.log('数据改变了')
userMsg.name = ''
}
})
//vue3响应式原理
//映射userMsg,从而代理userMsg,Proxy可以捕获`增、删、改、查`
//Proxy代理对象
const uMsg = new Proxy(userMsg,{
//获取
get(target,propName){
//可以实现响应式
// return target[propName]
//vue3底层实现通过反射对象 Reflect修改原对象属性
return Reflect.get(target,propName)
},
//修改、添加
set(target,propName,value){
console.log('数据改变了')
//可以实现响应式
//userMsg.name = ''
//vue3底层实现通过反射对象 Reflect修改原对象属性
Reflect.set(target,propName,value)
}
//删除
deleteProperty(target,propName){
//可以实现响应式
// return delete target[propName] //捕获删除
//vue3底层实现通过反射对象 Reflect修改原对象属性
return Reflect.deleteProperty(target,propName) //捕获删除
},
})
</script>
ref和reactive区别:
ref定义基本类型数据,也可定义对象、数组类型数据,但内部会通过reactive转换为代理对象, ref通过Object.defineProperty的get()、set()实现响应式,操作数据需要.value,模版不需要,可直接使用 reactive只能定义对象、数组类型数据,通过Proxy数据劫持,并通过反射对象 Reflect 修改原对象属性实现响应式,读取操作数据不需要.value
4、计算属性、监听
<script lang="ts">
//引入ref 、reactive、
import { ref, reactive, computed} from 'vue'
exportt default {
name:'myApp',
//vue2中,开发中不建议vue2、vue3混用
computed:{
changeName(){
return this.msgList.name + '520'
}
},
setup(){
const msgList = reactive({
name:'',
job:'挖矿小伙'
})
//vue3 中计算属性 —— 简写模式 不考虑修改
msgList.changeName = computed(() => {
return msgList.name + '520'
})
//完整模式,读写
msgList.changeName = computed({
//获取
get(){
return msgList.name + '520'
},
//修改
set(value){
msgList.name = value
}
})
return {
msgList
}
}
}
</script>
wacth
<script lang="ts">
import { ref, reactive, computed, watch, watchEffect} from 'vue'
exportt default {
name:'myApp',
//vue2中,开发中不建议vue2、vue3混用
watch:{
//简写
total(newValue, oldValue){
console.log(newValue)
},
//完整写法
total:{
deep:true,
immediate:true,
handler(newValue, oldValue){
console.log(newValue)
}
}
},
setup(){
const total =ref(0)
const name = '小胖'
const msgList = reactive({
person:{
a{
name:'小胖'
}
},
name:'',
job:'挖矿小伙'
})
/*****vue3中
*
*注意,可调用多个 watch**
*注意,ref 基本数据类型不需要 `.value`
*
******/
//1、vue3 中监视 `ref` 数据
watch(total,(newValue, oldValue) => {
console.log(newValue)
},{ immediate:true })
//2、vue3 中监视多个 `ref` 数据
watch([total,name],(newValue, oldValue) => {
console.log(newValue)
},{ immediate:true })
//3、vue3 中监视多个 `reactive` 数据
watch(msgList,(newValue, oldValue) => {
console.log(newValue)
},{ immediate:true })
//4、vue3 中监视 **多个 `reactive` 某个数据** 强制开启深度监视
watch(() => msgList.name,(newValue, oldValue) => {
console.log(newValue)
},{ immediate:true })
//5、vue3 中监视 **多个 `reactive` 某些数据**
watch([() => msgList.name,() => msgList.job],(newValue, oldValue) => {
console.log(newValue)
},{ immediate:true })
//6、vue3 中监视 `reactive` 特殊情况监视某个深度对象 需要开启深度监视
watch([() => msgList.person,() => msgList.job],(newValue, oldValue) => {
console.log(newValue)
},{ immediate:true ,deep:true})
/******
*
* watchEffect 默认开启immediate
* 可以分别监视需要的属性, 用谁监视谁
* 有点类似 computed
*
******/
watchEffect(() => {
const a = total.value
console.log(a )
})
return {
total,
name,
msgList
}
}
}
</script>
5、生命周期
??注意:vue3 提供了组合式API生命周期钩子
1、没有提供beforeCreate() created()组合API钩子,同等于 setup(); 2、更改了两个命名钩子beforeUnmount() 、 unmount();3、使用中需要引入
6、hook函数,作用封装组合式API,组件化
对功能化组件进行抽离,一般以use开头命名,例如在hook下创建 useDataTime.ts
// 时间戳转换
const dataTimes = (result):string => {
const date = new Date(result);
let y = date.getFullYear();
let MM = date.getMonth() + 1;
MM = MM < 10 ? ('0' + MM) : MM;
let d = date.getDate();
d = d < 10 ? ('0' + d) : d;
let h = date.getHours();
h = h < 10 ? ('0' + h) : h;
let m = date.getMinutes();
m = m < 10 ? ('0' + m) : m;
let s = date.getSeconds();
s = s < 10 ? ('0' + s) : s;
return y + '-' + MM + '-' + d
}
export default dataTimes
7、其他组合API
toRe和toRefs,把一个普通数据转换成响应式数据
<script lang="ts">
import { ref, reactive, toRe, toRefs} from 'vue'
exportt default {
name:'myApp',
setup(){
const msgList = reactive({
name:'',
age:20,
job:'挖矿小伙'
})
return {
msgList,//是响应式
msgList.name,//不是响应式
msgList.age,//不是响应式
name:ref(msgList,'name'),//转换成ref响应式,但不改变原是数据
name:toRef(msgList,'name'),//toRef引用原数据
...toRefs(msgList)//toRefs把所有数据变成响应式
}
}
}
</script>
shallowRef 和 shallowReactive,浅层响应式,只考虑第一层数据;
readonly 和 shallowreadonly ,只读;
toRow 和 markRow,原始的数据
<script lang="ts">
import { ref, reactive,shallowRef,shallowreactive, readonly, shallowReadonly} from 'vue'
exportt default {
name:'myApp',
setup(){
/******
*
* shallowreactive 只处理对象最外层响应式
* shallowRef 只处理基本类型数据响应式,无法处理对象类型,一般数据只改变一次使用
*
******/
const msgList = reactive({
name:'',
age:20,
job:{
salary:80000,
des:''
},
list:{}
})
const a = shallowRef(3)
const a = shallowreactive({
name:'',
age:20,
job:{
salary:80000,
des:''
}
})
//把 `msgList` 响应式改为只读
msgList = readonly(msgList)
msgList = shallowReadonly(msgList) //浅层次
//输出最原始数据
const starts = () => {
//数据中转,还原原数据,toRow只能处理reactive数据类型
const a = toRow(msgList) //无法对a进行操作
console.loog(a)
//markRow 标为普通对象
let list = {
x:1,
y:2
}
msgList.list = markRow(list)
}
return {
msgList,
}
}
}
</script>
customRef自定义响应式
/***
*
* `customRef()` 预期接收一个工厂函数作为参数,这个工厂函数接受 `track` 和 `trigger`两个函数作为参数,
* 并返回一个带有 `get` 和 `set` 方法的对象。
*
* 一般来说,`track()` 应该在 `get()` 方法中调用,而 `trigger()` 应该在 `set()` 中调用。然而事
* 实上,你对何时调用、是否应该调用他们有完全的控制权。
*
*
***/
import { customRef } from 'vue'
export function useDebouncedRef(value, delay = 200) {
let timeout
return customRef((track, trigger) => {
return {
get() {
track()
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}
})
}
组件中使用:
<template>
<input v-model="text" />
</template>
<script setup lang="ts">
import { useDebouncedRef } from './debouncedRef'
const text = useDebouncedRef('hello')
</script>
组件件通讯,provide 和 inject
<------- 父组件 ------->
<template>
<h3>我是父组件</h3>
<Child/>
</template>
//父组件 provide 提供
<script lang="ts">
import { ref, reactive, toRe, toRefs, provide} from 'vue'
import 'Child' from './components/Child.vue'
components:{
Child
},
exportt default {
name:'myApp',
setup(){
const msgList = reactive({
name:'',
age:20,
job:'挖矿小伙'
})
provide('msgList',msgList)
return {
..toRefs(msgList)
}
}
}
</script>
<------- 子组件 ------->
<template>
<h3>我是子组件</h3>
<span></span>
</template>
//子组件 props 提供
<script lang="ts">
import { ref, reactive, toRe, toRefs,} from 'vue'
components:{
son
},
exportt default {
name:'child',
setup(props,ctx){
console.log(props)
}
}
</script>
<------- 后代组件 ------->
//后代组件 inject 提供
<script lang="ts">
import { ref, reactive, toRe, toRefs, inject} from 'vue'
components:{
son
},
exportt default {
name:'child',
setup(){
const msgList = reactive({
name:'',
age:20,
job:'挖矿小伙'
})
let msgList = inject('msgList')
return {
msgList
}
}
}
</script>
判断是否是响应式数据,isRef()、isReactive() isReadonly() isProxy()是否为真即可
Fragment虚拟跟组件、Teleport传送门组件、Suspense 异步组件
欢迎收藏、点赞!
相关推荐
- 如何将数据仓库迁移到阿里云 AnalyticDB for PostgreSQL
-
阿里云AnalyticDBforPostgreSQL(以下简称ADBPG,即原HybridDBforPostgreSQL)为基于PostgreSQL内核的MPP架构的实时数据仓库服务,可以...
- Python数据分析:探索性分析
-
写在前面如果你忘记了前面的文章,可以看看加深印象:Python数据处理...
- C++基础语法梳理:算法丨十大排序算法(二)
-
本期是C++基础语法分享的第十六节,今天给大家来梳理一下十大排序算法后五个!归并排序...
- C 语言的标准库有哪些
-
C语言的标准库并不是一个单一的实体,而是由一系列头文件(headerfiles)组成的集合。每个头文件声明了一组相关的函数、宏、类型和常量。程序员通过在代码中使用#include<...
- [深度学习] ncnn安装和调用基础教程
-
1介绍ncnn是腾讯开发的一个为手机端极致优化的高性能神经网络前向计算框架,无第三方依赖,跨平台,但是通常都需要protobuf和opencv。ncnn目前已在腾讯多款应用中使用,如QQ,Qzon...
- 用rust实现经典的冒泡排序和快速排序
-
1.假设待排序数组如下letmutarr=[5,3,8,4,2,7,1];...
- ncnn+PPYOLOv2首次结合!全网最详细代码解读来了
-
编辑:好困LRS【新智元导读】今天给大家安利一个宝藏仓库miemiedetection,该仓库集合了PPYOLO、PPYOLOv2、PPYOLOE三个算法pytorch实现三合一,其中的PPYOL...
- C++特性使用建议
-
1.引用参数使用引用替代指针且所有不变的引用参数必须加上const。在C语言中,如果函数需要修改变量的值,参数必须为指针,如...
- Qt4/5升级到Qt6吐血经验总结V202308
-
00:直观总结增加了很多轮子,同时原有模块拆分的也更细致,估计为了方便拓展个管理。把一些过度封装的东西移除了(比如同样的功能有多个函数),保证了只有一个函数执行该功能。把一些Qt5中兼容Qt4的方法废...
- 到底什么是C++11新特性,请看下文
-
C++11是一个比较大的更新,引入了很多新特性,以下是对这些特性的详细解释,帮助您快速理解C++11的内容1.自动类型推导(auto和decltype)...
- 掌握C++11这些特性,代码简洁性、安全性和性能轻松跃升!
-
C++11(又称C++0x)是C++编程语言的一次重大更新,引入了许多新特性,显著提升了代码简洁性、安全性和性能。以下是主要特性的分类介绍及示例:一、核心语言特性1.自动类型推导(auto)编译器自...
- 经典算法——凸包算法
-
凸包算法(ConvexHull)一、概念与问题描述凸包是指在平面上给定一组点,找到包含这些点的最小面积或最小周长的凸多边形。这个多边形没有任何内凹部分,即从一个多边形内的任意一点画一条线到多边形边界...
- 一起学习c++11——c++11中的新增的容器
-
c++11新增的容器1:array当时的初衷是希望提供一个在栈上分配的,定长数组,而且可以使用stl中的模板算法。array的用法如下:#include<string>#includ...
- C++ 编程中的一些最佳实践
-
1.遵循代码简洁原则尽量避免冗余代码,通过模块化设计、清晰的命名和良好的结构,让代码更易于阅读和维护...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- node卸载 (33)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- exceptionininitializererror (33)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)