当前位置: 首页 > 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…...

Vue报错 ‘vite‘ 不是内部或外部命令,也不是可运行的程序或批处理文件

报错 vue-project0.0.0 dev vite‘vite’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。解决 第1步. 控制台输入 npm install -g create-vite第2步. 控制台输入 npm install -g vite第3步. 运行就ok啦...

emqx代理订阅主题的方法

需求:需要代理订阅主题 mqtt/MaxVision/# 5.0以上的版本 界面操作添加就可以5.0以下版本 修改emqx.config 文件 首先在EMQX Dashboard(web端)中模块 emqx_mod_subscription 要启用修改配置 #1.切换目录 cd /home/emqx/etc#2.编辑配置文件 emqx.config vim emqx.config#3.修…...

页面关键路径渲染详解

关键路径渲染 浏览器不会等待全部资源都下载完后才进行渲染&#xff0c;而是采用渐进式的渲染方式&#xff0c;本文就介绍一下这种渐进式的渲染方式。 当浏览器获取到用于呈现网页的资源后&#xff0c;通常就会开始渲染网页。那么究竟是在什么时候就会开始渲染&#xff1f; …...

错题集锦之C语言

直接寻址和立即寻址 算法的又穷性是指算法程序的运行时间是有限的 未经赋值的全局变量值不确定 集成测试是为了发现概要设计的错误 自然连接要求两个关系中进行比较的是相同的属性&#xff0c;并且进行等值连接&#xff0c;在结果中还要把重复的属性列去掉 赋值运算符 赋值…...

【2024华为杯数学建模竞赛】E题 解题思路 | 视频特征提取

这高速公路应急车道紧急启用模型 问题 1解题思路解题思路 问题 2解题思路 问题 3解题思路 问题 1 某路段&#xff08;长度约5000m&#xff0c;行车道2应急车道1&#xff09;上有四个视频观测点&#xff08;见示意图1&#xff09;。请基于该路段四个视频数据解决如下问题&#x…...

ubuntu 执行定时任务crontab -e 无法输入的问题

界面显示 GNU nano 4.8 /tmp/crontab.l0A1HJ/crontab # Edit this file to introduce tasks to be run by cron. # # Each task to run has to be defined t…...

快速响应:提升前端页面加载速度技巧的必知策略方案

在本文中&#xff0c;我们将深入探讨导致页面加载缓慢的常见原因&#xff0c;并分享一系列切实可行的优化策略&#xff0c;无论你是刚入门的新手&#xff0c;还是经验丰富的开发者&#xff0c;这些技巧都将帮助你提升网页性能&#xff0c;让你的用户体验畅快无阻。 相信作为前端…...

VUE-CLI配置全局SCSS变量

一.引入node-sass和sass-loader依赖 npm install --save-dev sass-loader node-sass 二. 在项目根目录中创建一个scss变量文件&#xff0c;比如constant.scss&#xff1a; 三.在vue.config.js文件中引入这个变量文件&#xff1a; // vue.config.js module.exports {css: {l…...

前端JavaScript导出excel,并用excel分析数据,使用SheetJS导出excel

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f…...

浅谈内网攻防之道-内网系统凭证钓鱼

你荒废的今日&#xff0c;正是昨日殒身之人祈求的明日。 1、FakeLogonScreen FakeLogonScreen 是用 C# 编写的应用程序&#xff0c;可以模拟 Windows 的登录屏幕来欺骗用户输入&#xff0c;从而盗取凭证 在目标的 session 会话中&#xff0c;指定该程序&#xff1a; 该工具能…...