网站首页 > 技术文章 正文
一、组合式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 异步组件
欢迎收藏、点赞!
猜你喜欢
- 2024-11-03 「大促最后1天」带你了解家庭的生命周期
- 2024-11-03 uniapp-权限处理(uniapp弹出通知权限)
- 2024-11-03 万能前端框架uni app初探03:底部导航开发
- 2024-11-03 uniapp开发安卓应用踩坑记(uniapp开发项目)
- 2024-11-03 uniapp 触底加载更多数据的方法(uniapp上拉加载更多)
- 2024-11-03 《微信小程序开发从入门到实战》学习二十七
- 2024-11-03 uni-app plus.runtime.arguments 获取参数
- 2024-11-03 遵义小红椒 带你进 uni-app 入坑指南
- 2024-11-03 uni-app从入门到进阶 系统完成项目实战
- 2024-11-03 4、类京东商城小程序_分类导航区域实现
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)