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

TS React 项目中使用TypeScript

在 React 项目中使用 TS

  1. 创建新项目
  1. 在现有项目中添加 TS

创建新项目

  • 命令:npx create-react-app my-app --template typescript
  • 说明:在命令行中,添加 --template typescript 表示创建支持 TS 的项目
  • 项目目录的变化:
    1. 在项目根目录中多了一个文件:tsconfig.json
      • TS 的配置文件
    1. 在 src 目录中,文件的后缀有变化,由原来的 .js 变为 .ts.tsx
      • .ts ts 文件的后缀名
      • .tsx 是在 TS 中使用 React 组件时,需要使用该后缀
    1. 在 src 目录中,多了 react-app-env.d.ts 文件
      • .d.ts 类型声明文件,用来指定类型

基本使用

创建类组件

在vscode中通过tsrcc快速创建类组件

import React, { Component } from 'react'type Props = {}type State = {}export default class App extends Component<Props, State> {state = {}render() {return (<div>App</div>)}
}

其中泛型Props指外部数据的数据类型

State指内部数据的数据类型。

创建函数组件

定义函数组件第一种方式:

在vscode中通过tsrfc快速创建函数组件

import React from 'react'type Props = {}export default function Header({}: Props) {return (<div>Header</div>)
}

Props:指外部数据的数据类型

第二种方式:

import { FC } from 'react';type Props = {}// FC:函数组件
const Nav: FC<Props> = function() {return <div></div>
}

外部数据

简单的数据类型定义
import React, { Component } from 'react'type Props = {msg: string
}type State = {}export default class Footer extends Component<Props, State> {state = {}render() {return (<div>消息: {this.props.msg}</div>)}
}

复杂数据类型定义

定义复杂数据类型后,可以导出数据类型方便其他组件引入使用。

import React, { Component } from 'react'export interface User {name: string,age: number
}export type UserList = User[];type Props = {msg: string,user: User,userList: UserList
}type State = {}export default class Footer extends Component<Props, State> {state = {}render() {return (<div>消息: {this.props.msg}<br />姓名:{this.props.user.name}年龄:{this.props.user.age}</div>)}
}

在父组件引入数据类型使用

import React, { Component } from 'react'
import Footer, { User, UserList } from './components/Footer'type Props = {}type State = {}const user: User = {name: '张三', age: 20}
const userList: UserList = [{name: '李四', age: 30}];export default class App extends Component<Props, State> {state = {}render() {return (<div><Footer msg={'消息'} user={user} userList={userList} /></div>)}
}

内部数据

类组件的内部数据State

内部数据通过泛型传入State数据类型。后续使用中提示更加友好。

import React, { Component } from 'react'type Props = {
}type State = {address: string
}export default class Footer extends Component<Props, State> {state = {address: '红旗河沟'}changeAddr = () => {this.setState({address: '渝北区'})}render() {return (<div>地址:{this.state.address}<button onClick={this.changeAddr}>修改地址</button></div>)}
}

函数组件的内部数据State

在函数组件中通过useState创建内部数据

在创建某些复杂数据时,要注意显示去传入state的泛型数据类型,否则数据类型很容容易报错。

import React, { useEffect } from 'react'
import { useState } from 'react';type Props = {}interface User {name: string, age: number}export default function Header(props: Props) {let [count, setCount] = useState(0);let [user, setUser] = useState<User>({} as any);let [userList, setUserList] = useState<User[]>([]);function changeCount() {setCount(10);}function changeUserList() {setUserList([{name: '张三',age: 20}]);}return (<div>count:{count}<button onClick={changeCount}>修改count</button><br />姓名:{user.name}年龄:{user.age}<button onClick={changeUserList}>修改userList</button></div>)
}

对父子通信进行类型限定

首先让脚手架支持TypeScript,可以在安装脚手架的时候进行配置即可,命令如下。

npx create-react-app react-ts-study --template typescript

然后就是创建两个组件,并且完成props通信。

import React from 'react'
interface WelcomeProps {msg?: stringcount?: numberlist: string[]info: { username: string; age: number }status?: 'loading' | 'success' | 'error'
}function Welcome(props: WelcomeProps) {const { count = 0 } = props;return (<div><h2>hello Welcome, {count}</h2></div>)
}
export default function App() {return (<div><h2>01_react-ts</h2><Welcome msg="hello" count={123} list={['a', 'b', 'c']} info={{username: 'xiaoming', age: 20}} /><Welcome list={['a', 'b', 'c']} info={{username: 'xiaoming', age: 20}} /><Welcome status="loading" list={['a', 'b', 'c']} info={{username: 'xiaoming', age: 20}} /></div>)
}

下面来看一下函数表达式写法的情况下,如何指定props的类型,可通过内置的FC类型来进行实现。

const Welcome: React.FC<WelcomeProps> = (props) => {return (<div><h2>hello Welcome</h2></div>)
}

children与event限制

children的类型限制

父子通信时候的内容分发进行限制。

import React from 'react'
interface WelcomeProps {children?: React.ReactNode
}
function Welcome(props: WelcomeProps) {return (<div><h2>hello Welcome, {props.children}</h2></div>)
}
export default function App() {return (<div><h2>02_react-ts</h2><Welcome /><Welcome>aaaaa</Welcome></div>)
}

我们把children属性作为可选参数,这样当<Welcome>组件进行内容分发和不进行内容分发都是可以的。

event限制

event在React中主要通过内置的ev: React.MouseEvent<HTMLButtonElement>来进行限定。

import React from 'react'
interface WelcomeProps {children?: React.ReactNodehandleMsg?: (ev: React.MouseEvent<HTMLButtonElement>)=> void
}
function Welcome(props: WelcomeProps) {const handleChange = (ev: React.ChangeEvent<HTMLInputElement>) => {console.log(ev.target.value)}return (<div><h2>hello Welcome, {props.children}</h2><button onClick={props.handleMsg}>点击</button><input type="text" onChange={handleChange} /></div>)
}
export default function App() {return (<div><h2>02_react-ts</h2><Welcome /><Welcome handleMsg={(ev)=>{}}>aaaaa</Welcome></div>)
}

props.children问题

在tsx中props中要访问children,那么应该使用PropsWithChildren去定义props数据类型

import React, { useEffect } from 'react'
import { useState, PropsWithChildren } from 'react';type Props = {}export default function Header(props: PropsWithChildren<Props>) {return (<div{props.children}</div>)
}

PropsWithChildren是一个数据类型,接口泛型Props数据类型,然后得到一个注入了children数据类型的Props数据类型。

通过FC创建的函数组件的props也没有children属性,也需要使用PropsWithChildren去定义

import { FC, PropsWithChildren } from 'react';type Props = {}// FC:函数组件
const Nav: FC<PropsWithChildren<Props>> = function(props) {return <div>{props.children}</div>
}

style与component限制

style限制

当我们进行style样式通信的时候,也是可以指定类型,防止样式传递的时候不复合规范。

import React from 'react'
interface HeaderProps {username: string
}
interface WelcomeProps {style: React.CSSProperties
}
function Welcome(props: WelcomeProps) {return (<div><h2>hello Welcome</h2></div>)
}
export default function App() {return (<div><h2>03_react-ts</h2><Welcome style={{'border': '1px red solid', display: 'none'}} /></div>)
}

主要通过React.CSSProperties来指定样式的类型,这样当传递的样式属性或者值不符合规范的时候,就不会产生TS的提示。

component限制

如果组件进行通信的时候,也可以进行类型的限制。

import React from 'react'
interface HeaderProps {username: string
}
interface WelcomeProps {style: React.CSSPropertiescomponent: React.ComponentType<HeaderProps>
}
function Welcome(props: WelcomeProps) {return (<div><h2>hello Welcome</h2><props.component username="xiaoming"></props.component></div>)
}
function Header(props: HeaderProps) {return (<div>hello Header</div>)
}
export default function App() {return (<div><h2>03_react-ts</h2><Welcome style={{'border': '1px red solid', display: 'none'}} component={Header} /></div>)
}

主要通过React.ComponentType<>来指定组件的类型,那么一旦不符合指定的接口类型,就会报错。
 

use函数限制

在React函数组件中,主要就是对use函数进行类型的注解。常见的注解use函数如下:

  • useState -> 联合类型、对象字面量类型
  • useEffect -> 自动类型推断
  • useRef -> 泛型标签类型
import React, { useEffect, useState, useRef } from 'react'
interface WelcomeProps {
}
function Welcome(props: WelcomeProps) {return (<div><h2>hello Welcome</h2></div>)
}
type Info = {username: string; age: number}
export default function App() {//const [count, setCount] = useState(0)const [count, setCount] = useState<number|string>(0)const [list, setList] = useState<string[]>([])//const [info, setInfo] = useState<{username: string; age: number}|null>(null)const [info, setInfo] = useState<Info>({} as Info)const myRef = useRef<HTMLButtonElement>(null)useEffect(()=>{console.log( myRef.current?.innerHTML )  // 可选链(类型保护)//console.log( myRef.current!.innerHTML )  // 非空断言(慎用)   return ()=>{}}, [])const handleClick = () => {setCount(1)setList(['a', 'b'])}return (<div><h2>04_react-ts</h2><button onClick={handleClick} ref={myRef}>点击</button>{ info.username }, { info.age }<Welcome />      </div>)
}

useState和useRef都是通过泛型的方式进行类型注解,useEffect主要利用自动类型推断来完成。

类组件类型限制

类组件在React中并不是重点,但是也要了解怎么对类组件进行类型的限制。

import React, { Component } from 'react'
interface WelcomeProps {msg: stringcount: number
}
interface WelcomeState {username: string
}
class Welcome extends Component<WelcomeProps, WelcomeState> {state = {username: 'xiaoming'}render() {return (<div>hello Welcome {this.state.username}</div>)}
}
export default function App() {return (<div><h2>05_react-ts</h2><Welcome msg="hello" count={123} />      </div>)
}

主要就是给继承的类Component传递泛型,Props和State,这样可以实现父子通信的数据进行类型限制,又可以对内部的state进行类型限制。
 

路由如何使用TS进行开发

react-router-dom类型限制

React路由与TS配合常见的使用为以下这些操作:

  • RouteObject 内置类型,限制路由表
  • React.createElement() 进行组件编写
  • 扩展 meta 元信息
// /router/index.ts
import { createBrowserRouter } from 'react-router-dom'
import type { RouteObject } from 'react-router-dom'
import App from '../App';
import Index from '../views/Index/Index';
import User from '../views/User/User';
import Login from '../views/Login/Login';
import React from 'react';
declare module 'react-router' {interface NonIndexRouteObject {meta?: { title: string }}interface IndexRouteObject {meta?: { title: string }}
}
export const routes: RouteObject[] = [{path: '/',element: React.createElement(App),meta: { title: '/' },children: [{path: 'index',element: React.createElement(Index),meta: { title: 'index' }},{path: 'user',element: React.createElement(User),meta: { title: 'user' }},{path: 'login',element: React.createElement(Login)}]}
];
const router = createBrowserRouter(routes);
export default router;

状态管理如何使用TS进行开发

Redux Toolkit限制类型

Redux状态管理与TS配合常见的使用为以下这些操作:

  • 得到全局state类型: ReturnType<typeof store.getState>
  • 限定payload类型: PayloadAction
// /store/index.ts
import { configureStore } from '@reduxjs/toolkit'
import userReducer from './modules/user';
import { useDispatch } from 'react-redux'
const store = configureStore({reducer: {user: userReducer}
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
export const useAppDispatch: () => AppDispatch = useDispatch
export default store;
// /store/modules/user.ts
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
export const loginAction = createAsyncThunk('users/loginAction',async (userId: number) => {const response = await new Promise((resolve)=>{resolve('response data')})return response}
)
const userSlice = createSlice({name: 'user',initialState: {name: 'xiaoming'},reducers: {change(state, action: PayloadAction<string>){state.name = action.payload}}
})
export const { change } = userSlice.actions
export default userSlice.reducer

tsconfig的介绍

  • tsconfig.json是typescript项目的配置文件,用于配置typescript
  • tsconfig.json配置文件可以通过 tsc --init 生成
  • 说明:所有的配置项都可以通过鼠标移入的方式,来查看配置项的解释说明。
  • tsconfig 文档链接
{// 编译选项"compilerOptions": {// 生成代码的语言版本:将我们写的 TS 代码编译成哪个版本的 JS 代码// 命令行: tsc --target es5 11-测试TS配置文件.ts"target": "es5",// 指定要包含在编译中的 library"lib": ["dom", "dom.iterable", "esnext"],// 允许 ts 编译器编译 js 文件"allowJs": true,// 跳过类型声明文件的类型检查"skipLibCheck": true,// es 模块 互操作,屏蔽 ESModule 和 CommonJS 之间的差异"esModuleInterop": true,// 允许通过 import x from 'y' 即使模块没有显式指定 default 导出"allowSyntheticDefaultImports": true,// 开启严格模式"strict": true,// 对文件名称强制区分大小写"forceConsistentCasingInFileNames": true,// 为 switch 语句启用错误报告"noFallthroughCasesInSwitch": true,// 生成代码的模块化标准"module": "esnext",// 模块解析(查找)策略"moduleResolution": "node",// 允许导入扩展名为.json的模块"resolveJsonModule": true,// 是否将没有 import/export 的文件视为旧(全局而非模块化)脚本文件"isolatedModules": true,// 编译时不生成任何文件(只进行类型检查)"noEmit": true,// 指定将 JSX 编译成什么形式"jsx": "react-jsx"},// 指定允许 ts 处理的目录"include": ["src"]
}

typescript声明文件

今天几乎所有的 JavaScript 应用都会引入许多第三方库来完成任务需求。

这些第三方库不管是否是用 TS 编写的,最终都要编译成 JS 代码,才能发布给开发者使用。

我们知道是 TS 提供了类型,才有了代码提示和类型保护等机制。

但在项目开发中使用第三方库时,你会发现它们几乎都有相应的 TS 类型,这些类型是怎么来的呢? 类型声明文件

  • 类型声明文件:用来为已存在的 JS 库提供类型信息

这样在 TS 项目中使用这些库时,就像用 TS 一样,都会有代码提示、类型保护等机制了。

  1. TS 的两种文件类型
  1. 类型声明文件的使用说明

TS 中的两种文件类型

  • TS 中有两种文件类型:1 .ts 文件 2 .d.ts 文件
  • .ts 文件:
    1. 既包含类型信息又可执行代码
    2. 可以被编译为 .js 文件,然后,执行代码
    3. 用途:编写程序代码的地方
  • .d.ts 文件:
    1. 只包含类型信息的类型声明文件
    2. 不会生成 .js 文件,仅用于提供类型信息,在.d.ts文件中不允许出现可执行的代码,只用于提供类型
    3. 用途:为 JS 提供类型信息
  • 总结:.ts 是 implementation(代码实现文件);.d.ts 是 declaration(类型声明文件)
  • 如果要为 JS 库提供类型信息,要使用 .d.ts 文件

类型声明文件的使用说明

  • 在使用 TS 开发项目时,类型声明文件的使用包括以下两种方式:
    1. 使用已有的类型声明文件
    2. 创建自己的类型声明文件

使用已有的类型声明文件

  1. 内置类型声明文件
  1. 第三方库的类型声明文件
  1. 自己提供的

内置类型声明文件

  • TS 为 JS 运行时可用的所有标准化内置 API 都提供了声明文件
  • 比如,在使用数组时,数组所有方法都会有相应的代码提示以及类型信息:
const strs = ['a', 'b', 'c']
// 鼠标放在 forEach 上查看类型
strs.forEach
  • 实际上这都是 TS 提供的内置类型声明文件
  • 可以通过 Ctrl + 鼠标左键(Mac:Command + 鼠标左键)来查看内置类型声明文件内容
  • 比如,查看 forEach 方法的类型声明,在 VSCode 中会自动跳转到 lib.es5.d.ts 类型声明文件中
  • 当然,像 window、document 等 BOM、DOM API 也都有相应的类型声明(lib.dom.d.ts)

第三方库的类型声明文件

  • 目前,几乎所有常用的第三方库都有相应的类型声明文件
  • 第三方库的类型声明文件有两种存在形式:1 库自带类型声明文件 2 由 DefinitelyTyped 提供。

  1. 库自带类型声明文件:比如,axios
    • 查看 node_modules/axios 目录

解释:这种情况下,正常导入该库,TS 就会自动加载库自己的类型声明文件,以提供该库的类型声明。

  1. 由 DefinitelyTyped 提供
  • DefinitelyTyped 是一个 github 仓库,用来提供高质量 TypeScript 类型声明
  • DefinitelyTyped 链接
  • 可以通过 npm/yarn 来下载该仓库提供的 TS 类型声明包,这些包的名称格式为:@types/*
  • 比如,@types/react、@types/lodash 等
  • 说明:在实际项目开发时,如果你使用的第三方库没有自带的声明文件,VSCode 会给出明确的提示

import _ from 'lodash'// 在 VSCode 中,查看 'lodash' 前面的提示
  • 解释:当安装 @types/* 类型声明包后,TS 也会自动加载该类声明包,以提供该库的类型声明
  • 补充:TS 官方文档提供了一个页面,可以来查询 @types/* 库
  • @types/* 库

创建自己的类型声明文件

  1. 项目内共享类型
  1. 为已有 JS 文件提供类型声明

项目内共享类型

  • 如果多个 .ts 文件中都用到同一个类型,此时可以创建 .d.ts 文件提供该类型,实现类型共享。
  • 操作步骤:
    1. 创建 index.d.ts 类型声明文件。
    2. 创建需要共享的类型,并使用 export 导出(TS 中的类型也可以使用 import/export 实现模块化功能)。
    3. 在需要使用共享类型的 .ts 文件中,通过 import 导入即可(.d.ts 后缀导入时,直接省略)。

为已有 JS 文件提供类型声明

  1. 在将 JS 项目迁移到 TS 项目时,为了让已有的 .js 文件有类型声明。
  1. 成为库作者,创建库给其他人使用。

  • 注意:类型声明文件的编写与模块化方式相关,不同的模块化方式有不同的写法。但由于历史原因,JS 模块化的发展 经历过多种变化(AMD、CommonJS、UMD、ESModule 等),而 TS 支持各种模块化形式的类型声明。这就导致 ,类型声明文件相关内容又多又杂。
  • 演示:基于最新的 ESModule(import/export)来为已有 .js 文件,创建类型声明文件。

类型声明文件的使用说明

  • 说明:TS 项目中也可以使用 .js 文件。
  • 说明:在导入 .js 文件时,TS 会自动加载与 .js 同名的 .d.ts 文件,以提供类型声明。
  • declare 关键字:用于类型声明,为其他地方(比如,.js 文件)已存在的变量声明类型,而不是创建一个新的变量。
    1. 对于 type、interface 等这些明确就是 TS 类型的(只能在 TS 中使用的),可以省略 declare 关键字。
    2. 对于 let、function 等具有双重含义(在 JS、TS 中都能用),应该使用 declare 关键字,明确指定此处用于类型声明。
let count = 10
let songName = '痴心绝对'
let position = {x: 0,y: 0
}function add(x, y) {return x + y
}function changeDirection(direction) {console.log(direction)
}const fomartPoint = point => {console.log('当前坐标:', point)
}export { count, songName, position, add, changeDirection, fomartPoint }

定义类型声明文件

declare let count:numberdeclare let songName: stringinterface Position {x: number,y: number
}declare let position: Positiondeclare function add (x :number, y: number) : numbertype Direction = 'left' | 'right' | 'top' | 'bottom'declare function changeDirection (direction: Direction): voidtype FomartPoint = (point: Position) => voiddeclare const fomartPoint: FomartPointexport {count, songName, position, add, changeDirection, FomartPoint, fomartPoint
}

相关文章:

TS React 项目中使用TypeScript

在 React 项目中使用 TS 创建新项目 在现有项目中添加 TS 创建新项目 命令&#xff1a;npx create-react-app my-app --template typescript 说明&#xff1a;在命令行中&#xff0c;添加 --template typescript 表示创建支持 TS 的项目 项目目录的变化&#xff1a; 在项目…...

【JavaEE】IP协议 应用层协议

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 &#x1f576;️一.IP地址 IP协议&#xff08;Internet Protocol&#xff09;是TCP/IP协议族中最核心的协议之一&#xff0c;它定义了数据包在网络中传输的标准…...

CRM如何助力科技服务机构突破业务瓶颈?

在当今知识经济时代&#xff0c;科技服务机构面临着复杂的业务环境和多样化的客户需求。客户管理系统&#xff08;CRM&#xff09;在这个领域的应用正逐渐成为机构提升运营效率、优化客户服务的关键。 科技服务行业的业务特点 知识产权代理行业具有高度的专业性和复杂性。其业…...

牛啊,GitHub 代理加速图文教程

大家好&#xff0c;众所周知&#xff0c;GitHub 在国内访问速度堪忧&#xff0c;经常出现访问不了的情况&#xff0c;如果我们去 clone 代码&#xff0c;网速非常差。今天教大家如何给 GitHub 进行加速。 要用到我开发的开源项目 Cloudflare Workers Proxy&#xff0c;它是一个…...

基于扣子(Coze)打造第一个智能体——个性化对话机器人

文章目录 一&#xff0c;智能体体验二&#xff0c;动手打造一个自己的智能体1&#xff0c;主页点击创建机器人1.1 创建一个新的机器人1.2 修订Bot基础信息1.3 工具编排信息修订人设和回复逻辑、增补开场白等 2&#xff0c;使用插件优化机器人3&#xff0c;使用工作流优化机器人…...

算法-深度拷贝链表(138)

深度拷贝一个链表可以分以下几个步骤&#xff1a; 步骤 1&#xff1a;插入新节点 目标&#xff1a;在每个节点后面插入一个复制的节点。步骤&#xff1a; 遍历整个链表。对于每个节点 current&#xff0c;创建一个新节点 newNode&#xff0c;其值为 current.val。将 newNode …...

【Kubernetes】常见面试题汇总(十四)

目录 42.简述 Kubernetes 如何保证集群的安全性&#xff1f; 43.简述 Kubernetes 准入机制&#xff1f; 42.简述 Kubernetes 如何保证集群的安全性&#xff1f; Kubernetes 通过一系列机制来实现集群的安全控制&#xff0c;主要有如下不同的维度&#xff1a; &#xff08;1&…...

灵当CRM系统index.php存在SQL注入漏洞

文章目录 免责申明漏洞描述搜索语法漏洞复现nuclei修复建议 免责申明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 漏洞描述 灵当CRM系统是一款功能全面、易于使用的客户关系管理&#xff08;C…...

详解QT元对象系统用法

文章目录 元枚举 QMetaEnum元方法 QMetaMethod元对象构建 QMetaObjectBuilder元属性 QMetaProperty定义元对象属性获取属性信息与信号和槽结合QML属性访问动态属性元类型 QMetaTypeQt的元对象系统是Qt框架中的一个核心特性,它为Qt应用程序提供了一种动态类型信息机制。这种机制…...

【Python】从基础到进阶(八):文件操作与上下文管理

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、Python文件操作基础1. 打开文件2. 读取文件3. 写入文件4. 文件指针定位 三、上下文管理1. 使用with管理文件2. 自定义上下文管理器 四、文件操作的最佳实践五、案例&#xff1a;日志文件管理1. 需求分析2. 实现…...

c#:System.Text.Json 的使用四(如何忽略[JsonPropertyName])

环境&#xff1a; .net 6.0vs2022 系列篇&#xff1a; 《c#&#xff1a;System.Text.Json 的使用一》 《c#&#xff1a;System.Text.Json 的使用二》 《c#&#xff1a;System.Text.Json 的使用三&#xff08;从Newtonsoft迁移&#xff09;》 《c#&#xff1a;System.Text.Json…...

【CPU】CPU的物理核、逻辑核、超线程判断及L1、L2、L3缓存、CacheLine和CPU的TBL说明

CPU物理核及L1、L2、L3及缓存 CPU缓存 CPU 缓存是一种用于存储临时数据以提高计算机程序性能的内存层次结构。它通常分为三个层次&#xff1a;L1&#xff08;一级&#xff09;、L2&#xff08;二级&#xff09;和L3&#xff08;三级&#xff09;缓存。缓存大小是CPU的重…...

NET WPF使用组件库HandyControl

一、背景 WPF原生控件提供的API功能不够强大&#xff0c;设置一般的功能都需要进行很复杂的配置和实现。 1.1 原生按钮控件 例如&#xff0c;原生控件<Button/> 默认效果是这样的&#xff1a; MainWindow.xaml代码&#xff1a; <Window x:Class"wpf_demo.Mai…...

计算机毕业设计之:教学平台微信小程序(

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…...

VMware Fusion虚拟机Mac版 安装Win10系统教程

Mac分享吧 文章目录 Win10安装完成&#xff0c;软件打开效果一、VMware安装Windows10虚拟机1️⃣&#xff1a;准备镜像2️⃣&#xff1a;创建虚拟机3️⃣&#xff1a;虚拟机设置4️⃣&#xff1a;安装虚拟机&#xff08;步骤和Win11安装步骤类似&#xff0c;此处相同步骤处没换…...

头戴式蓝牙耳机性价比高的有哪些?四款高能性价比机型对比推荐

在当今科技日新月异的时代&#xff0c;头戴式蓝牙耳机已经成为了我们日常生活中不可或缺的一部分&#xff0c;无论是通勤路上、健身房内还是家中休闲时&#xff0c;一副优质的头戴式蓝牙耳机都能为我们带来沉浸式的听觉体验&#xff0c;那么头戴式蓝牙耳机性价比高的有哪些&…...

Linux:make,Makefile

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《Linux&#xff1a;make&#xff0c;Makefile》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 如果本篇文章对你有帮助&#xff0c;还请各位点点赞&…...

基于代理的分布式身份管理方案

目的是使用分布式的联合计算分发去替换掉区块链中原有的类第三方可信中心的证书机制&#xff0c;更加去中心化。 GS-TBK Group Signatures with Time-bound Keys. CS-TBK 算法 Complete subtree With Time-bound Keys&#xff0c;该算法是用来辅助检测用户的签名是否有效&…...

VSCode开发ros程序无法智能提示的解决方法(一)

VSCode开发ros程序无法智能提示的解决方法&#xff08;一&#xff09; 问题解决 问题 在Ubuntu下使用vscode开发ros程序&#xff0c;无法进行智能提示。 解决 将 intelli Sense Engine 设置为 Tag Parser 即可。...

grep命令如何实现正则表达式搜索?

grep 命令支持使用正则表达式&#xff08;Regular Expression&#xff0c;简称 regex&#xff09;进行搜索 以下是一些使用正则表达式的基本示例&#xff1a; 搜索包含 “example” 的行&#xff1a; grep "example" file.txt搜索以 “abc” 开头的行&#xff1a; g…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

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

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

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...