TypeScript快速上手语法+结合vue3用法
TypeScript快速上手语法+结合vue3用法
前言:
本篇内容不涉及TypeScript安装以及配置,具体安装及配置篇可以看下面目录,本篇只涉及TypeScript语法相关内容,及结合vue3的用法。不讲废话,简单直接直接开撸。
目录
TypeScript的具体安装及配置
TypeScript快速上手语法+结合vue3用法
1、定义原始类型
2、定义object 类型
3.定义数组类型
4.定义元祖类型
5.定义enum 类型
6.定义函数类型
7.定义任意类型
8.隐式类型推断
9.类型断言
10、 接口 interface
11、类 Class
12.类与接口
13.抽象类
14. 泛型 Generics
Vue3+TS基础语法
🧨🧨🧨定义data
🧨🧨🧨定义props
🧨🧨🧨定义methods
vue-router
在setup中使用
🧨🧨🧨 vuex
在setup中使用
模块
🧨🧨🧨 在setup如何定义变量(字符串,对象,数组)
Watch和WatchEffect
Vue3生命周期调用
1、定义原始类型
const a: string = 'foo'
const b: number = 100
const c: boolean = true
const d: void = undefined
const e: null = null
const f: undefined = undefined
const g: symbol = Symlol()
2、定义object 类型
const foo: object = function () {} // [] // {}
const obj: { foo: number,bar: string } = { foo: 123, bar: 'string' }
3.定义数组类型
// 第一种定义方式,元素类型设置为 *number*
const arr1: Array<number> = [1, 2, 3]
// 第二种定义方式,较为常见
const arr2: number[] = [1, 2, 3]// 例子
function sum (...args: number[]) {// 传统做法是要判断传入的参数是否是数字,而TypeScript中只需要像上面这样对参数做一个类型注解,就行了return args.reduce(prev, current) => prev + current, 0)
}sum(1, 2, 3, 'foo') // 这里传入了一个非数字的值就会报错
4.定义元祖类型
const tuple: [number, string] = [18, 'foo']
// const tuple: [number, string] = [18, 18] 类型不匹配,会报错
// const tuple: [number, string] = [18, 'foo', 'xxx'] 数量不匹配,会报错// 访问
const age = tuple[0]
const name = tuple[1]// 解构
const [age, name] = tuple
5.定义enum 类型
// enum 对象的属性可以不用赋值,默认从0开始递增,也可以赋值Draft = 5,后面的就从5开始递增也可以给具体的值,比如 Draft = 'xxx',这样后面的属性都要给具体的值
enum PostStatus {Draft = 0,Unpublished = 1,Published = 2
}const post = {title: 'Hello TypeScript',content: 'TypeScript is a typed superset of JavaScript.',status: PostStatus.Draft // 0 // 1 // 2
}
6.定义函数类型
// 声明式函数
// 参数a和b是number类型,函数返回是string类型,
// 参数后带问号代表是可选参数
// 当参数数量不固定的时候可以使用rest运算符来接受参数,类型是一个值为number的数组
function func1 (a: number, b?: number, ...rest: number[]): string {return 'func1'
}// 函数表达式定义函数
const func2 = function (a: number, b: number): string {return 'func2'
}// 如果把一个函数作为参数传递,类似callback函数。
function fntD(callback: (bl: boolean) => boolean) {callback(true)
}
function callback(bl: boolean): boolean {console.log(bl)return bl
}
const dResult = fntD(callback)
7.定义任意类型
// value 可以接受任意类型
function stringfy (value: any) {return JSON.stringify(value)
}stringify('string')
stringify(10)
stringify(true)// foo 可以任意赋值
let foo: any = 'string'
foo = 100
8.隐式类型推断
// age 赋值为 number 类型
let age = 18 // numberage = 'string' // 会警告错误,因为age是number类型let foo // 没有赋值,就是any类型foo = 100
foo = 'string'
9.类型断言
// 假定这个 nums 来自一个明确的接口
const nums = [110, 120, 119, 112]// 这里TypeScript推断res的类型为 number|undefined
// 因为它并不知道这个i到底在数组中有没有
const res = nums.find(i => i > 0)// 这里就会报错警告
const square = res * res// 如果我们直接 断言 这个 res 就是 number 类型
const num1 = res as number// 这里就不会报错了
const square = res * res
10、 接口 interface
接口用来约定对象的结构,一个对象要实现一个接口,就必须拥有这个接口中所包含的所有成员
interface Post {title: stringcontent: string
}function printPost (post: Post) {console.log(post.title)console.log(post.content)
}printPost({title: 'Hello TypeScript',content: 'A JavaScript superset'
})// 特殊的接口成员 可选成员 只读成员
interface Post{title: stringcontent: stringsubtitle?: string // 加问号就是可选成员readonly summary: string // 加 readonly 就是只读成员
}const hello: Post = {title: 'Hello TypeScript',content: 'A javascript superset',summary: 'a javascript'
}hello.summary = 'other' // 会报错,因为 summary 是只读成员// 动态成员
interface Cache {[prop: string]: string
}const cache: Cache = {}cache.foo = 'value1'
cache.bar = 'value2'
11、类 Class
Class Person {// 在这里赋值,和在构造函数中初始化必须两者选其一name: string // = 'init name' 这里可以直接初始化private age: number // 这里定义 age 为私有属性protected gender: boolean // 受保护的类型readonly national: string // 只读属性,一经初始化,不可更改constructor (name: string, age: number) {// 需要在上面标注出构造函数中属性的类型this.name = namethis.age = agethis.gender = truethis.national = national}sayHi (msg: string): void {console.log(`I am ${this.name}, ${msg}`)console.log(this.age)}
}const tom = new Person('tom', 18)
console.log(tom.name) // tom
console.log(tom.age) // 报错,因为 age 是私有属性,所以访问不到
console.log(tom.gender) // 报错,因为 gender 是受保护的属性,这里访问不到// 在下方新声明一个类 student 继承与 Person
class Student extends Person {constructor (name: string, age: number) {super(name, age)console.log(this.gender) // 这里就一个访问到 受保护的属性 gender
}
12.类与接口
interface Eat {eat (food: string): void
}interface Run {run (distance: number): void
}// Person类,实现了 Eat 和 Run 两个接口
class Person implements Eat, Run {eat (food: string): void {console.log(`优雅的进餐:${food}`)}run (distance: number) {console.log(`直立行走:${distance}`)}
}// Animal类,实现了 Eat 和 Run 两个接口
class Animal implements Eat, Run {eat (food: string): void {console.log(`饥不择食的吃:${food}`)}run (distance: number) {console.log(`爬行:${distance}`)}
}
13.抽象类
abstract 定义抽象类,抽象类只能被继承,不能通过 new 的方式创建实例对象
// 定义一个抽象类 Animal
abstract class Animal {eat (food: string): void {console.log(`饥不择食的吃:${food}`)}// 定义一个抽象方法 run,可以不需要方法体。// 定义了抽象方法之后,子类中必须实现这个抽象方法abstract run (distance: number): void
}class Dog extends Animal {run(distance: number): void {console.log('四脚爬行', distance)}
}const d = new Dog()
d.eat('嘎嘎') // 饥不择食的吃:嘎嘎
d.run(100) // 四脚爬行 100
14. 泛型 Generics
泛型是指在定义接口函数类的时候,没有指定具体的类型,等到我们在使用的时候再去指定具体的类型的这种特征
// 这里声明一个创建 number 类型数组的函数 creatNumberArray
function createNumberArray (length: number, value: number): number[] {// 这里的Array是 any 类型,所以要给它指定一个 Number 类型const arr = Array<number>(length).fill(value)return arr
}// 这里声明一个创建 String 类型数组的函数 createStringArray
function createStringArray (length: number, value: string): string[] {const arr = Array<string>(length).fill(value)return arr
}// 因为上面的两个函数代码有冗余,所以这里我们可以使用 泛型
// 一般我们使用 T 来作为泛型参数的名称,然后把函数中不明确的类型都改为 T 来做代表
function createArray<T> (length: number, value: T): T[] {const arr = Array<T>(length).fill(value)return arr
}// 然后使用泛型的时候 传递 T 的类型
const res = creatArray<string>(3,'foo')// const res = createNumberArray(3, 100)
// res => [100, 100, 100]
==============================分割线=============================
下面是结合vue3的项目写法
Vue3+TS基础语法
🧨🧨🧨定义data
script标签上lang="ts"
定义一个类型type或者接口interface来约束data
可以使用ref或者toRefs来定义响应式数据
使用ref在setup读取的时候需要获取xxx.value,但在template中不需要
使用reactive时,可以用toRefs解构导出,在template就可以直接使用了
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';type Todo = {id: number,name: string,completed: boolean
}export default defineComponent({const data = reactive({todoList: [] as Todo[]})const count = ref(0);console.log(count.value)return {...toRefs(data)}
})
</script>
🧨🧨🧨定义props
props需要使用PropType泛型来约束。
<script lang="ts">
import { defineComponent, PropType} from 'vue';interface UserInfo = {id: number,name: string,age: number
}export default defineComponent({props: {userInfo: {type: Object as PropType<UserInfo>, // 泛型类型required: true}},
})
</script>
复制代码
defineProps 和 defineEmits
注意:defineProps 和 defineEmits 都是只在
为了声明 props 和 emits 选项且具备完整的类型推断,可以使用 defineProps 和 defineEmits API,它们在 <script setup> 中都是自动可用的:
- defineProps 和 defineEmits 都是只在 <script setup> 中才能使用的****编译器宏。他们不需要导入,且会在处理 <script setup> 的时候被编译处理掉。
- defineProps 接收与 props 选项相同的值,defineEmits 也接收 emits 选项相同的值。
- defineProps 和 defineEmits 在选项传入后,会提供恰当的类型推断。
- 传入到 defineProps 和 defineEmits 的选项会从 setup 中提升到模块的范围。因此,传入的选项不能引用在 setup 范围中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块范围内。
父组件
//父组件<script setup lang="ts">import TestPropsPmit from './components/test-props-emit/index.vue';import { ref } from 'vue';// 定义字符串变量const msg = ref('欢迎使用vite!')// 调用事件const handleChange = (params:string) =>{console.log(params);}
</script>
<template><TestPropsPmit :msg="msg" @on-change="handleChange"></TestPropsPmit>
</template>
子组件
//子组件<template><p>{{props.msg}}</p><button @click="handleClick">点击我调用父组件方法</button>
</template>
<script setup lang="ts">const props = defineProps({msg:{type: String,default: () => '默认值'}})const emit = defineEmits(['on-change', 'update'])const handleClick = () =>{emit('on-change', '父组件方法被调用了')}
</script>
子组件暴露属性和方法,给父组件引用
<script setup lang="ts">
function testChild():void{console.log('子组件方法testChild被调用了');
}
const b = ref(2)
// 统一暴露属性
defineExpose({obj:{name: '张三', age: 2300},b,testChild
})
</script>
父组件调用子组件方法和属性
<template><TestPropsEmit ref="propsEmitRef" :msg='msg' @on-change="handleChange"> </TestPropsEmit>
</template>
<script setup lang="ts">import TestPropsEmit from './components/test-props-emit/index.vue';import {ref, onMounted} from 'vue';const msg = ref('欢迎学习vite')const handleChange = (params:string)=>{console.log(params);}const propsEmitRef = ref()onMounted(()=>{console.log(propsEmitRef.value.child);})
</script>
🧨🧨🧨定义methods
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';type Todo = {id: number,name: string,completed: boolean
}export default defineComponent({const data = reactive({todoList: [] as Todo[]})// 约束输入和输出类型const newTodo = (name: string):Todo => {return {id: this.items.length + 1,name,completed: false};}const addTodo = (todo: Todo): void => {data.todoList.push(todo)}return {...toRefs(data),newTodo,addTodo}
})
</script>
vue-router
- createRouter创建router实例
- router的模式分为:
- createWebHistory -- history模式
- createWebHashHistory -- hash模式
- routes的约束类型是RouteRecordRaw
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import Home from '../views/Home.vue';
const routes: Array< RouteRecordRaw > = [{path: '/',name: 'Home',component: Home,},{path: '/about',name: 'About',component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')}
];const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes
});export default router;
扩展路由额外属性
在实际项目开发中,常常会遇到这么一个场景,某一个路由是不需要渲染到侧边栏导航上的,此时我们可以给该路由添加一个hidden属性来实现。
在ts的强类型约束下,添加额外属性就会报错,那么我们就需要扩展RouteRecordRaw类型。
在setup中使用
需要导入useRouter创建一个router实例。
<script lang="ts">
import { useRouter } from 'vue-router';
import { defineComponent } from 'vue';
export default defineComponent({setup () {const router = useRouter();goRoute(path) {router.push({path})}}
})
</script>
🧨🧨🧨 vuex
使用this.$store
import { createStore } from 'vuex';
export type State = {count: number
}export default createStore({state: {count: 0}
});
需要创建一个声明文件vuex.d.ts
// vuex.d.ts
import {ComponentCustomProperties} from 'vue';
import {Store} from 'vuex';
import {State} from './store'
declare module '@vue/runtime-core' {interface ComponentCustomProperties {$store: Store<State>}
}
在setup中使用
- 定义InjecktionKey
- 在安装插件时传入key
- 在使用useStore时传入
import { InjectionKey } from 'vue';
import { createStore, Store } from 'vuex';export type State = {count: number
}
// 创建一个injectionKey
export const key: InjectionKey<Store<State>> = Symbol('key');
// main.ts
import store, { key } from './store';
app.use(store, key);
<script lang="ts">
import { useStore } from 'vuex';
import { key } from '@/store';
export default defineComponent({setup () {const store = useStore(key);const count = computed(() => store.state.count);return {count}}
})
</script>
模块
新增一个todo模块。导入的模块,需要是一个vuex中的interface Module的对象,接收两个泛型约束,第一个是该模块类型,第二个是根模块类型。
// modules/todo.ts
import { Module } from 'vuex';
import { State } from '../index.ts';type Todo = {id: number,name: string,completed: boolean
}const initialState = {todos: [] as Todo[]
};export type TodoState = typeof initialState;export default {namespaced: true,state: initialState,mutations: {addTodo (state, payload: Todo) {state.todos.push(payload);}}
} as Module<TodoState, State>; //Module<S, R> S 该模块类型 R根模块类型
// index.ts
export type State = {count: number,todo?: TodoState // 这里必须是可选,不然state会报错
}export default createStore({state: {count: 0}modules: {todo}
});
使用:
setup () {console.log(store.state.todo?.todos);
}
🧨🧨🧨 在setup如何定义变量(字符串,对象,数组)
<template><h2>{{count}} {{user.name}}</h2><span v-for="(item, index) in arr" :key="index">{{item}}</span><button @click="setName">点击我增加</button>
</template>
<script setup lang="ts">import { ref, reactive } from 'vue';// 字符串变量const count = ref(0)// 对象let user = reactive({name: '张三'})// 数组let arr = reactive(['1', '2', '3'])// 综合定义方案const originData = reactive({count: 0,user:{name: '张三'},arr: ['1', '2', '3']})// 方法const setName = ()=>{count.value++user.name = '李四'}
</script>
Watch和WatchEffect
1、基本使用方法:
<template><p>{{originData.count}} {{originData.user.name}}</p><p v-for="(item, index) in originData.arr" :key="index">{{item}}</p><button @click="incriment">点击我count增加</button>
</template>
<script setup lang="ts">import { ref, reactive, watchEffect, watch } from 'vue';const count = ref(0)const user = reactive({name: '张三'})const arr = reactive([1,2,3,4])// 综合定义方案const originData = reactive({count: 0,user:{name: '张三'},arr:[1,2,3,4]})const incriment = ()=>{originData.count++count.value++originData.user.name = '李四'}// 默认页面更新之前立即执行监听,懒执行开始watchEffect(() => console.log(count.value))// 默认监听数据变化后的值,页面更新后不会立即执行watch(count, (n, o) => {console.log('watch', n, o);})// 监听多个值watch([count, originData.user], (newValues, prevValues) => {console.log(newValues[0], newValues[1].name)})// 立即监听watch([count, originData.user], (newValues, prevValues) => {console.log(newValues[0], newValues[1].name)}, {deep: true, immediate: true})</script>
提示:
watch与 watchEffect 比较,推荐watch监听
watch: 页面更新后不会立即执行,而watchEffect 它会执行;
🧨🧨🧨Vue3生命周期调用
在 setup () 内部调用生命周期钩子:
- 选项式 API Hook inside setup
- beforeCreate Not needed* 不需要
- created Not needed* 不需要
- beforeMount onBeforeMount 挂载之前
- mounted onMounted 页面加载完成时执行
- beforeUpdate onBeforeUpdate
- updated onUpdated
- beforeUnmount onBeforeUnmount
- unmounted onUnmounted 页面销毁时执行
- errorCaptured onErrorCaptured
- renderTracked onRenderTracked
- renderTriggered onRenderTriggered
- activated onActivated
- deactivated onDeactivated
<script setup lang="ts">
import { onMounted, onActivated, onUnmounted, onUpdated, onDeactivated } from 'vue';
// 读取环境变量
const mode = import.meta.env;
// import HeadMenu from '@/components/head-menu/index.vue';onMounted(() => {console.log("组件挂载")})onUnmounted(() => {console.log("组件卸载")})onUpdated(() => {console.log("组件更新")})onActivated(() => {console.log("keepAlive 组件 激活")})onDeactivated(() => {console.log("keepAlive 组件 非激活")})
</script>
加🧨🧨🧨为必用的东西,可以多看看
最后:
待续....精力有限 持续更新中....
相关文章:

TypeScript快速上手语法+结合vue3用法
TypeScript快速上手语法结合vue3用法 前言: 本篇内容不涉及TypeScript安装以及配置,具体安装及配置篇可以看下面目录,本篇只涉及TypeScript语法相关内容,及结合vue3的用法。不讲废话,简单直接直接开撸。 目录 Type…...

一,下载iPerf3最新源代码
本文目录普通下载方式:git下载方式:普通下载方式: 如果你只是要阅读源代码,不涉及到编译安装修改源代码,那么可以简单的通过此方式下载代码。如果你希望编译安装修改源代码,那么建议通过git来进行源代码的…...
keithley6487/吉时利6487皮安表
产品概览 5-1/2 位 Keithley 6487 皮安表/电压源改进了屡获殊荣的 Keithley 6485 皮安表的测量能力,并增加了高分辨率 500V 电源。它提供更高的精度和更快的上升时间,以及与电容设备一起使用的阻尼功能。这款经济高效的仪器具有八个电流测量范围和高速自…...
sql命令大全
一:基本命令 1.数据库连接 mysql -h 主机名 -u root -p2.添加用户 insert into user (host,user,password,select_priv,insert_priv,update_priv) values (localhost,guest,password(guest123),Y,Y,Y);3.创建用户 create user usernamehost identified by passw…...
Ubuntu 定时执行脚本
一、关于crontab cron是一个Linux定时执行工具,可以在无需人工干预的情况下运行作业。在Ubuntu中,cron是被默认安装并启动的。 二、例子 直接上例子,来看看怎么用。 需求:定时每天8点,自动执行保存在/root目录下he…...

Python带你制作一个属于自己的多功能音乐播放器
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 就是用Python做一个简易的音乐播放器,废话不多说,咱们直接开干 当然,今天做这个肯定不是最简单的,最简单的音乐播放器,9行代码足以 完整源码等直接在文末名片领…...

Redis 被问麻了...
Redis是面试中绕不过的槛,只要在简历中写了用过Redis,肯定逃不过。今天我们就来模拟一下面试官在Redis这个话题上是如何一步一步深入,全面考察候选人对于Redis的掌握情况。 小张: 面试官,你好。我是来参加面试的。 …...

使用JavaScript+Selenium玩转Web应用自动化测试
自动化测试 在软件开发过程中, 测试是功能验收的必要过程, 这个过程往往有测试人员参与, 提前编写测试用例, 然后再手动对测试用例进行测试, 测试用例都通过之后则可以认为该功能通过验收. 但是软件中多个功能之间往往存在关联或依赖关系, 某一个功能的新增或修改可能或影响到…...

[架构之路-119]-《软考-系统架构设计师》-计算机体系结构 -1- 基本原理(体系结构、指令系统与流水线、层次存储)
第9章 计算机体系结构9.1 什么是计算机体系结构计算机系统结构(Computer Architecture)也称为计算机体系结构,它是由计算机结构外特性,内特性,微外特性组成的。经典的计算机系统结构的定义是指计算机系统多级层次结构中…...

【离线数仓-8-数据仓库开发DWD层-交易域相关事实表】
离线数仓-8-数据仓库开发DWD层-交易域相关事实表离线数仓-8-数据仓库开发DWD层-交易域相关事实表一、DWD层设计要点二、交易域相关事实表1.交易域加购事务事实表1.加购事务事实表 前期梳理2.加购事务事实表 DDL表设计分析3.加购事务事实表 加载数据分析1.首日全量加购的数据加载…...

你知道Java架构师学习路线该怎么走吗?你所缺少的是学习方法以及完整规划!
怎么成为一名Java架构师?都需要掌握哪些技术?Java架构师,首先要是一个高级Java攻城狮,熟练使用各种框架,并知道它们实现的原理。jvm虚拟机原理、调优,懂得jvm能让你写出性能更好的代码;池技术,什…...

华为OD机试用Python实现 -【查找树中的元素 or 查找二叉树节点】(2023-Q1 新题)
华为OD机试题 华为OD机试300题大纲查找树中的元素 or 查找二叉树节点题目描述输入描述输出描述说明示例一输入输出示例二输入输出Python 代码实现代码编写思路华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 O…...

MyBatis——创建与使用
概念 当我们使用传统的jdbc进行数据库与程序的连接时,每一个操作都需要写一条sql语句,并且没法调试和修改 jdbc连接数据库流程: 创建数据库连接池DataSource获取数据库连接Connection执行带占位符的sql语句通过Connection创建操作对象Stat…...

【涨薪技术】0到1学会性能测试 —— 参数化关联
前言 上一次推文我们分享了性能测试工作原理、事务、检查点!今天给大家带来性能测试参数化,检查点知识!后续文章都会系统分享干货,带大家从0到1学会性能测试,另外还有教程等同步资料,文末免费获取~ 01、性…...

go进阶(2) -深入理解Channel实现原理
Go的并发模型已经在https://guisu.blog.csdn.net/article/details/129107148 详细说明。 1、channel使用详解 1、channel概述 Go的CSP并发模型,是通过goroutine和channel来实现的。 channel是Go语言中各个并发结构体(goroutine)之前的通信机制。 通俗的讲…...

数组(二)-- LeetCode[303][304] 区域和检索 - 数组不可变
1 区域和检索 - 数组不可变 1.1 题目描述 题目链接:https://leetcode.cn/problems/range-sum-query-immutable/ 1.2 思路分析 最朴素的想法是存储数组 nums 的值,每次调用 sumRange 时,通过循环的方法计算数组 nums 从下标 iii 到下标 jjj …...

22-基于分时电价条件下家庭能量管理策略研究MATLAB程序
参考文献:《基于分时电价和蓄电池实时控制策略的家庭能量系统优化》参考部分模型《计及舒适度的家庭能量管理系统优化控制策略》参考部分模型主要内容:主要做的是家庭能量管理模型,首先构建了电动汽车、空调、热水器以及烘干机等若干家庭用户…...

“XXX.app 已损坏,打不开。您应该将它移到废纸篓”,Mac应用程序无法打开或文件损坏的处理方法(2)
1. 检查状态 在sip系统完整性关闭前,我们先检查是否启用了SIP系统完整性保护。打开终端输入以下命令【csrutil status】并回车: 你会看到以下信息中的一个,用来指示SIP状态。已关闭 disabled: System Integrity Protection status: disabl…...

flask入门-3.Flask操作数据库
3. Flask操作数据库 1. 连接数据库 首先下载 MySQL数据库 其次下载对应的包: pip install pymysql pip install flask-sqlalchemy在 app.py 中进行连接测试 from flask import Flask, request, render_template from flask_sqlalchemy import SQLAlchemyhostname "1…...

STM32 使用microros与ROS2通信
本文主要介绍如何在STM32中使用microros与ROS2进行通信,在ROS1中标准的库是rosserial,在ROS2中则是microros,目前网上的资料也有一部分了,但是都没有提供完整可验证的demo,本文将根据提供的demo一步步给大家进行演示。1、首先如果你用的不是S…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...