React Router-v6.25.1

以下例子是根据vite+react+ts构建的,使用路由前先安装好这些环境!!!!

1、路由的简单使用

首先要创建一个浏览器路由器并配置我们的第一个路由。这将为我们的 Web 应用启用客户端路由。

main.jsx文件是入口点。打开它,我们将把 React Router 放到页面上。

import * as React from "react";
import * as ReactDOM from "react-dom/client";
import {createBrowserRouter,RouterProvider,
} from "react-router-dom";
import "./index.css";const router = createBrowserRouter([{path: "/",element: <div>Hello world!</div>,},
]);ReactDOM.createRoot(document.getElementById("root")).render(<React.StrictMode><RouterProvider router={router} /></React.StrictMode>
);

我们通常将第一个路由称为“根路由”,因为其余路由将在其中呈现。它将作为 UI 的根布局,随着我们进一步深入,我们将拥有嵌套布局。

正常访问的页面因该是:

如果访问不存在的路由页面将是如下:

 2、创建根路径和错误页面

2.1、创建根布局组件(src/routes/root.tsx)

export default function Root() {return (<><div id="sidebar"><h1>React Router Contacts</h1><div><form id="search-form" role="search"><inputid="q"aria-label="Search contacts"placeholder="Search"type="search"name="q"/><divid="search-spinner"aria-hiddenhidden={true}/><divclassName="sr-only"aria-live="polite"></div></form><form method="post"><button type="submit">New</button></form></div><nav><ul><li><a href={`/contacts/1`}>Your Name</a></li><li><a href={`/contacts/2`}>Your Friend</a></li></ul></nav></div><div id="detail"></div></>);
}

目前还没有任何特定于 React Router 的内容,因此请随意复制/粘贴所有内容。

注意:其实一般是挂在app上的,实际开发中应该是app作为根路由的!!!

2.2、设置<Root>为根路由element

import React from 'react'
import ReactDOM from 'react-dom/client'
import Root from './routes/root'
import {createBrowserRouter,RouterProvider,
} from 'react-router-dom'const router = createBrowserRouter([{path: "/",element: <Root></Root>,},
]);ReactDOM.createRoot(document.getElementById('root')!).render(<React.StrictMode><RouterProvider router={router} /></React.StrictMode>,
)

2.3、创建错误页面组件挂载

路径:src/error/error-page.tsx

import { useRouteError } from "react-router-dom";export default function ErrorPage() {const error = useRouteError();console.error(error);return (<div id="error-page"><h1>Oops!</h1><p>Sorry, an unexpected error has occurred.</p><p><i>{error.statusText || error.message}</i></p></div>);
}

将设置<ErrorPage>为errorElement根路由

import React from 'react'
import ReactDOM from 'react-dom/client'
import Root from './routes/root'
import {createBrowserRouter,RouterProvider,
} from 'react-router-dom'
import ErrorPage from './error/error-page'const router = createBrowserRouter([{path: "/",element: <Root></Root>,errorElement: <ErrorPage></ErrorPage>,},
]);ReactDOM.createRoot(document.getElementById('root')!).render(<React.StrictMode><RouterProvider router={router} /></React.StrictMode>,
)

当你访问不存的地址的时候就跳转到错误页:

3、添加其他组件路由

src/routes/contact.jsx

import { Form } from "react-router-dom";export default function Contact() {const contact = {first: "Your",last: "Name",avatar: "https://robohash.org/you.png?size=200x200",twitter: "your_handle",notes: "Some notes",favorite: true,};return (<div id="contact"><div><imgkey={contact.avatar}src={contact.avatar ||`https://robohash.org/${contact.id}.png?size=200x200`}/></div><div><h1>{contact.first || contact.last ? (<>{contact.first} {contact.last}</>) : (<i>No Name</i>)}{" "}<Favorite contact={contact} /></h1>{contact.twitter && (<p><atarget="_blank"href={`https://twitter.com/${contact.twitter}`}>{contact.twitter}</a></p>)}{contact.notes && <p>{contact.notes}</p>}<div><Form action="edit"><button type="submit">Edit</button></Form><Formmethod="post"action="destroy"onSubmit={(event) => {if (!confirm("Please confirm you want to delete this record.")) {event.preventDefault();}}}><button type="submit">Delete</button></Form></div></div></div>);
}function Favorite({ contact }) {const favorite = contact.favorite;return (<Form method="post"><buttonname="favorite"value={favorite ? "false" : "true"}aria-label={favorite? "Remove from favorites": "Add to favorites"}>{favorite ? "★" : "☆"}</button></Form>);
}

导入联系人组件并创建新路线

import React from 'react'
import ReactDOM from 'react-dom/client'
// import Root from './routes/root'
import App from './App'
import {createBrowserRouter,RouterProvider,
} from 'react-router-dom'
import ErrorPage from './error/error-page'
import Contact from './routes/contact'const router = createBrowserRouter([{path: "/",element: <App></App>,errorElement: <ErrorPage></ErrorPage>,},{path: "/contact/:contactId",element: <Contact></Contact>,},
]);ReactDOM.createRoot(document.getElementById('root')!).render(<React.StrictMode><RouterProvider router={router} /></React.StrictMode>,
)

现在访问:http://localhost:3000/contact/1,就是跳转的新页面啦!!!

虽然可以跳转,但是,它不在我们的根布局中😠,继续往下走!!!

4、嵌套路由

我们希望联系人组件像这样在布局内部呈现<Root>

我们通过将联系路由设为根路由的子路由来实现这一点。

👉将联系人路由移至根路由的子路由-children

const router = createBrowserRouter([{path: "/",element: <App />,errorElement: <ErrorPage />,children: [{path: "contacts/:contactId",element: <Contact />,},],},
]);

此时操作点击Name的时候如下:

点击前:

点击后:

很明显,虽然url地址变了,但是页面结构只是增多了,原来的ui结构仍然存在,我们将这样的操作称为子组件跳转,可以理解为局部跳转展示!!!!

5、客户端路由(a改成Link的使用)

您可能已经注意到了,也可能没有,但是当我们单击侧边栏中的链接时,浏览器正在对下一个 URL 执行完整文档请求,而不是使用 React Router。

客户端路由允许我们的应用更新 URL,而无需从服务器请求另一个文档。相反,应用可以立即呈现新的 UI。让我们用 来实现它<Link>。

👉将侧边栏更改<a href><Link to>

import { Outlet,Link } from "react-router-dom";
export default function Root() {return (<><div id="sidebar"><h1>React Router Contacts</h1><div><form id="search-form" role="search"><inputid="q"aria-label="Search contacts"placeholder="Search"type="search"name="q"/><divid="search-spinner"aria-hiddenhidden={true}/><divclassName="sr-only"aria-live="polite"></div></form><form method="post"><button type="submit">New</button></form></div><nav><ul><li><Link to={`contacts/1`}>Your Name</Link></li><li><Link to={`contacts/2`}>Your Friend</Link></li></ul></nav></div><div id="detail"><Outlet /></div></>);}

您可以在浏览器开发者工具中打开网络选项卡,看到它不再请求文档。(其实是因为a链接的问他,详细的问题可以去了解a链接为什么会请求刷新)

6、加载数据中(loader)

URL 段、布局和数据通常结合在一起(三重?)。我们已经可以在这个应用中看到它了:

URL 段成分数据
/<Root>聯絡人清單
联系人/:id<Contact>个人联系方式

由于这种自然的耦合,React Router 具有数据约定,可以轻松地将数据放入路由组件中。

我们将使用两个 API 来加载数据,loader和useLoaderData。首先,我们将在根模块中创建并导出加载器函数,然后将其连接到路由。最后,我们将访问和呈现数据。

loader 函数是一个异步函数,用于在组件渲染前获取数据。它通常被用来预加载数据,比如从服务器上获取数据,然后将这些数据传递给组件,使得组件可以在首次渲染时就拥有所有必要的数据。

👉从以下位置导出加载器root.jsx

import { Outlet, Link } from "react-router-dom";
import { getContacts } from "./contact";export async function loader() {const contacts = await getContacts();return { contacts };
}

 👉在路由上配置 loader

/* other imports */
import Root, { loader as rootLoader } from "./routes/root";const router = createBrowserRouter([{path: "/",element: <APP />,errorElement: <ErrorPage />,loader: rootLoader,children: [{path: "contacts/:contactId",element: <Contact />,},],},
]);

👉访问并呈现数据 root.tsx

import {Outlet,Link,useLoaderData,
} from "react-router-dom";
import { getContacts } from "../contacts";/* other code */export default function Root() {const { contacts } = useLoaderData();return (<><div id="sidebar"><h1>React Router Contacts</h1>{/* other code */}<nav>{contacts.length ? (<ul>{contacts.map((contact) => (<li key={contact.id}><Link to={`contacts/${contact.id}`}>{contact.first || contact.last ? (<>{contact.first} {contact.last}</>) : (<i>No Name</i>)}{" "}{contact.favorite && <span>★</span>}</Link></li>))}</ul>) : (<p><i>No contacts</i></p>)}</nav>{/* other code */}</div></>);
}

就是这样!React Router 现在会自动将数据与您的 UI 保持同步。我们目前还没有任何数据,因此您可能会得到一个空白列表,如下所示:


 7、更新数据(action)

我们刚刚创建的编辑路由已经呈现了一个表单。要更新记录,我们需要做的就是将操作连接到路由。表单将发布到操作,数据将自动重新验证。

src/routes/edit.tsx

👉向编辑模块添加操作

import {Form,useLoaderData,redirect,
} from "react-router-dom";
import { updateContact } from "../contacts";export async function action({ request, params }) {const formData = await request.formData();const updates = Object.fromEntries(formData);await updateContact(params.contactId, updates);return redirect(`/contacts/${params.contactId}`);
}

👉将操作连接到路线 main.ts

/* existing code */
import EditContact, {action as editAction,
} from "./routes/edit";const router = createBrowserRouter([{path: "/",element: <Root />,errorElement: <ErrorPage />,loader: rootLoader,action: rootAction,children: [{path: "contacts/:contactId",element: <Contact />,loader: contactLoader,},{path: "contacts/:contactId/edit",element: <EditContact />,loader: contactLoader,action: editAction,},],},
]);/* existing code */

填写表格,点击保存,然后你就会看到类似这样的内容!(除了看起来更舒服,而且可能没有那么毛茸茸的。)

注意:其实就是action里面的回调方法,它会在表单提交时被调用,而不是在页面加载时。 action 函数接收一个 ActionFunctionArgs 类型的参数,这个参数包含了请求方法、请求体、URL 参数等信息。action 函数应该返回一个 Promise,这个 Promise 会解析成一个对象,这个对象可以包含状态码和数据,它们将被用来构建响应。

特别注意:action 和 loader 是独立的概念,它们可以同时存在或只存在其中一个。action 主要用于处理表单提交,而 loader 用于在页面加载时预取数据。

8、动态路由

其实之前的案例已经使用过了,这里再详细讲一下,所谓的动态路由就是一个模块展示不同的内容,比如根据id展示不同的信息等操作:

路由配置:

chotacts就是动态路由:通过<Link to={`contacts/1`}>Your Name</Link>方式就可以访问了

const router = createBrowserRouter([{path: "/",element: <App />,errorElement: <ErrorPage />,children: [{path: "contacts/:contactId",element: <Contact />,},],},
]);

注意:contactIdURL 段。冒号 ( :) 具有特殊含义,将其转换为“动态段”。动态段将匹配 URL 中该位置的动态(变化)值,例如联系人 ID。我们将 URL 中的这些值称为“URL 参数”,或简称为“params”。

9、路由重定向

现在我们知道了如何重定向,让我们更新创建新联系人的操作以重定向到编辑页面:

👉重定向到新记录的编辑页面 root.tsx

import {Outlet,Link,useLoaderData,Form,redirect,
} from "react-router-dom";
import { getContacts, createContact } from "../contacts";export async function action() {const contact = await createContact();return redirect(`/contacts/${contact.id}/edit`);
}

现在,当我们点击“新建”时,我们应该进入编辑页面:

👉添加一些记录

我将使用第一届 Remix 大会的杰出演讲者阵容 😁

10、活动链接样式

现在我们有了一堆记录,但我们不清楚侧边栏中显示的是哪一条。我们可以用它NavLink来修复这个问题。

👉使用NavLink侧边栏中的 root.tsx

import {Outlet,NavLink,useLoaderData,Form,redirect,
} from "react-router-dom";export default function Root() {return (<><div id="sidebar">{/* other code */}<nav>{contacts.length ? (<ul>{contacts.map((contact) => (<li key={contact.id}><NavLinkto={`contacts/${contact.id}`}className={({ isActive, isPending }) =>isActive? "active": isPending? "pending": ""}>{/* other code */}</NavLink></li>))}</ul>) : (<p>{/* other code */}</p>)}</nav></div></>);
}

请注意,我们正在将一个函数传递给className。当用户位于 中的 URL 时NavLinkisActive则为真。当它即将激活时(数据仍在加载),则为isPending真。这使我们能够轻松指示用户所在的位置,以及对已点击但仍在等待数据加载的链接提供即时反馈。

NavLink 是 react-router-dom 库中的一个组件,用于创建具有激活高亮效果的导航链接。当用户浏览到与 NavLink 配置的 to 属性相匹配的路由时,NavLink 可以自动应用特定的样式或类名,以指示当前的导航位置。

NavLink 提供了以下主要属性:

  • to: 指定链接的目标地址。
  • className: 默认的 CSS 类名,始终应用在链接上。
  • activeClassName: 当链接与当前路由匹配时应用的 CSS 类名。
  • activeStyle: 直接应用在链接上的内联样式,当链接与当前路由匹配时生效。
  • exact: 如果设置为 true,则只有当完整路径与 to 属性完全匹配时,链接才会被视为“激活”状态。否则,任何包含 to 属性路径的部分匹配也会激活链接。
  • end: 如果设置为 true,并且 to 属性是一个索引路由(即没有子路由的父路由),那么即使 to 不完全匹配,链接也会被视为“激活”。这与 exact 属性相反。

下面是一个简单的 NavLink 使用示例:

import { NavLink } from 'react-router-dom';function Navigation() {return (<nav><ul><li><NavLink to="/" exact activeClassName="selected">Home</NavLink></li><li><NavLink to="/about" activeClassName="selected">About</NavLink></li><li><NavLink to="/contact" activeClassName="selected">Contact</NavLink></li></ul></nav>);
}

在这个例子中,当用户位于首页 (/) 时,“Home”链接将获得 selected 类名,从而应用相应的样式。同样地,当用户在 “About” 或 “Contact” 页面时,相应的链接也将获得高亮显示。

NavLink 是创建响应式和用户友好的导航菜单的理想选择,因为它可以自动处理链接的激活状态,无需手动编写逻辑来检查当前的路由。


11、全局待处理 UI

当用户浏览应用程序时,React Router 会保留旧页面,因为正在加载下一页的数据。您可能已经注意到,当您在列表之间单击时,应用程序感觉有点无响应。让我们为用户提供一些反馈,以便应用程序不会感觉无响应。

React Router 在后台管理所有状态,并揭示构建动态 Web 应用所需的部分内容。在本例中,我们将使用钩子useNavigation。

👉useNavigation添加全局待处理 UI-routes/roots.tsx

import {// existing codeuseNavigation,
} from "react-router-dom";// existing codeexport default function Root() {const { contacts } = useLoaderData();const navigation = useNavigation();return (<><div id="sidebar">{/* existing code */}</div><divid="detail"className={navigation.state === "loading" ? "loading" : ""}><Outlet /></div></>);
}

useNavigation返回当前导航状态: 可以是以下之一"idle" | "submitting" | "loading"

在我们的例子中,"loading"如果我们不处于空闲状态,我们会向应用程序的主要部分添加一个类。然后,CSS 会在短暂延迟后添加一个漂亮的淡入淡出效果(以避免快速加载时 UI 闪烁)。不过,您可以做任何您想做的事情,比如在顶部显示一个旋转器或加载栏。

请注意,我们的数据模型 ( src/contacts.js) 具有客户端缓存,因此第二次导航到同一联系人的速度很快。此行为不是React Router,它会重新加载更改路线的数据,无论您之前是否去过那里。但是,它确实避免在导航期间调用不变路线(如列表)的加载器。

12、取消按钮

在编辑页面上,我们有一个取消按钮,但它目前还没有任何作用。我们希望它能发挥与浏览器后退按钮相同的作用。

我们需要按钮上的点击处理程序以及useNavigateReact Router。

👉使用以下代码添加取消按钮点击处理程序useNavigate

import {Form,useLoaderData,redirect,useNavigate,
} from "react-router-dom";export default function EditContact() {const { contact } = useLoaderData();const navigate = useNavigate();return (<Form method="post" id="contact-form">{/* existing code */}<p><button type="submit">Save</button><buttontype="button"onClick={() => {navigate(-1);}}>Cancel</button></p></Form>);
}

现在,当用户点击“取消”时,他们将被送回浏览器历史记录中的一个条目。

event.preventDefault🧐 为什么按钮上没有?

尽管看似多余,但这<button type="button">是阻止按钮提交其表单的 HTML 方式。

还有两个功能要实现。我们已经进入最后冲刺阶段!

13、URL 搜索参数和 GET 提交

到目前为止,我们所有的交互式 UI 要么是更改 URL 的链接,要么是将数据发布到操作的表单。搜索字段很有趣,因为它是两者的混合:它是一个表单,但它只更改 URL,而不会更改数据。

现在它只是一个普通的 HTML <form>,而不是 React Router <Form>。让我们看看浏览器默认对它做了什么:

👉在搜索栏中输入姓名,然后按回车键

请注意,浏览器的 URL 现在以URLSearchParams的形式包含您的查询:

http://127.0.0.1:5173/?q=ryan

如果我们查看搜索表单,它看起来像这样:

<form id="search-form" role="search"><inputid="q"aria-label="Search contacts"placeholder="Search"type="search"name="q"/><div id="search-spinner" aria-hidden hidden={true} /><div className="sr-only" aria-live="polite"></div>
</form>

正如我们之前所见,浏览器可以通过name其输入元素的属性序列化表单。此输入的名称是q,这就是 URL 为的原因?q=。如果我们将其命名为,则searchURL 将是?search=

请注意,此表单与我们使用过的其他表单不同,它没有<form method="post">。默认值为method"get"这意味着当浏览器创建下一个文档的请求时,它不会将表单数据放入请求 POST 主体中,而是放入URLSearchParamsGET 请求的。


14、使用客户端路由进行 GET 提交

让我们使用客户端路由来提交此表单并过滤我们现有加载器中的列表。

👉更改<form><Form>

<Form id="search-form" role="search"><inputid="q"aria-label="Search contacts"placeholder="Search"type="search"name="q"/><div id="search-spinner" aria-hidden hidden={true} /><div className="sr-only" aria-live="polite"></div>
</Form>

👉如果有 URLSearchParams,则过滤列表

export async function loader({ request }) {const url = new URL(request.url);const q = url.searchParams.get("q");const contacts = await getContacts(q);return { contacts };
}

因为这是 GET 而不是 POST,所以 React Router不会调用action。提交 GET 表单与单击链接相同:只有 URL 会发生变化。这就是为什么我们为过滤添加的代码位于 中loader,而不是action此路由的 中。

这也意味着这是正常的页面导航。您可以点击后退按钮返回到原来的位置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/50164.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字看板:跨行业需求下的创新与升级

在当今这个数据驱动的时代&#xff0c;数字看板作为信息展示与决策支持的重要工具&#xff0c;正逐步渗透到各行各业之中。从智慧城市到智能制造&#xff0c;从金融分析到医疗健康&#xff0c;数字看板以其直观、动态、高效的特点&#xff0c;成为了连接数据与决策者的桥梁。本…

Linux系列--shell编程一

一、Linux系统结构 一、内核层 内核是Linux系统的核心部分&#xff0c;它负责管理系统各种硬件设备、文件系统、内存管理和进程管理等核心任务。Linux内核设计了良好的模块化结构&#xff0c;可以动态地加载和卸载内核模块&#xff0c;这使得内核可以兼容各种不同的硬件设备和…

基于联咏 NT98692芯片赋能边缘计算IP摄像机与XVR监控系统解决方案

联咏 NT98692 是一款新世代整合度极高的 SoC&#xff0c;具有高影像品质、低位元率、低功耗&#xff0c;针对 8Kp30 边缘运算 IP 摄影机与后端监控系统 XVR 应用。此 SoC 整合了 ARM Quad Cortex A73 CPU 核心、新一代 ISP 和 AI ISP、H.265/H.264 视讯压缩编解码器、DSP、高效…

C++ primer plus 第16章string 类和标准模板库, 函数符概念

C primer plus 第16章string 类和标准模板库, 函数符概念 C primer plus 第16章string 类和标准模板库, 函数符概念 文章目录 C primer plus 第16章string 类和标准模板库, 函数符概念16.5.1 函数符概念程序清单16.15 functor.cpp 16.5.1 函数符概念 正如 STL定义了容器和迭代…

数据结构和算法入门

1.了解数据结构和算法 1.1 二分查找 二分查找&#xff08;Binary Search&#xff09;是一种在有序数组中查找特定元素的搜索算法。它的基本思想是将数组分成两半&#xff0c;然后比较目标值与中间元素的大小关系&#xff0c;从而确定应该在左半部分还是右半部分继续查找。这个…

基于 HTML+ECharts 实现智慧安防数据可视化大屏(含源码)

构建智慧安防数据可视化大屏&#xff1a;基于 HTML 和 ECharts 的实现 随着科技的不断进步&#xff0c;智慧安防系统已经成为保障公共安全的重要工具。通过数据可视化&#xff0c;安防管理人员可以实时监控关键区域的安全状况、人员流动以及设备状态&#xff0c;从而提高应急响…

XSS攻击与CSRF攻击

XSS攻击 XSS&#xff08;Cross Site Scripting&#xff0c;跨站脚本攻击&#xff09;&#xff0c;是指攻击者利用站点的漏洞&#xff0c;在表单提交时&#xff0c;在表单内容中加入一些恶意脚本&#xff0c;当其他正常用户浏览页面&#xff0c;而页面中刚好出现攻击者的恶意脚…

ffmpeg更改视频的帧率

note 视频帧率调整 帧率(fps-frame per second) 例如&#xff1a;原来帧率为30&#xff0c;调整后为1 现象&#xff1a;原来是每秒有30张图像&#xff0c;调整后每秒1张图像&#xff0c;看着图像很慢 实现&#xff1a;在每秒的时间区间里&#xff0c;取一张图像…

【数据结构】手把手教你单链表(c语言)(附源码)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;数据结构 目录 前言 1.单链表的概念与结构 2.单链表的结构定义 3.单链表的实现 3.1 单链表的方法声明 3.2 单链表方法实现 3.2.1 打印链表 3.2.2 创建新…

四、GD32 MCU 常见外设介绍(8)SPI 模块介绍

串行外设接口&#xff08;Serial Peripheral Interface&#xff0c;缩写为 SPI&#xff09; 提供了基于SPI 协议的数据发送和接收功能&#xff0c; 可以工作于主机或从机模式。 SPI 接口支持具有硬件 CRC 计算和校验的全双工和单工模式。 8.1.SPI 基础知识 SPI 物理层 SPI接…

基于dcm4chee搭建的PACS系统讲解(三)服务端使用Rest API获取study等数据

文章目录 DICOMWeb Support模块主要数据结构ER查询信息基本信息metadata信息统计信息 实践查询API及参数解析API返回的json数组定义VRObjectNodeObjectMapper解析显示指定tag并解析 后记 前期预研的PACS系统&#xff0c;近期要在项目中上线了。因为PACS系统采用无权限认证&…

qt--电子相册

一、项目要求 设计一个电子相册&#xff0c;点击上一张&#xff0c;切换到上一张图片&#xff0c;点击下一张&#xff0c;切换到下一张图片。 要求&#xff1a;图片的展示可以循环&#xff08;QList<QString>&#xff09; 要求&#xff1a;界面美观 二、项目代码 本质是通…

概率论--矩估计

目录 简介 矩估计法的基本步骤 延伸 矩估计法在大样本情况下的准确性和有效性如何评估&#xff1f; 在实际应用中&#xff0c;矩估计法的局限性有哪些具体例子&#xff1f; 如何处理矩估计法在某些情况下可能出现的不合理解或无法唯一确定参数的问题&#xff1f; …

vue3前端开发-小兔鲜项目-form表单的统一校验

vue3前端开发-小兔鲜项目-form表单的统一校验&#xff01;实际上&#xff0c;为了安全起见&#xff0c;用户输入的表单信息&#xff0c;要满足我们的业务需求&#xff0c;参数类型等种种标准之后&#xff0c;才会允许用户向服务器发送登录请求。为此&#xff0c;有必要进行一次…

gstreamer使用cairo实现视频OSD叠加

前言 gstreamer中视频叠加OSD有很多种方式&#xff0c;比如textoverlay添加文字&#xff0c;gdkpixbufoverlay添加图片&#xff0c;clockoverlay或timeoverlay插件显示时间&#xff0c;pango插件进行复杂文本渲染&#xff0c;使用cairo插件绘制图形或者文字。 今天使用最后一…

【React】详解样式控制:从基础到进阶应用的全面指南

文章目录 一、内联样式1. 什么是内联样式&#xff1f;2. 内联样式的定义3. 基本示例4. 动态内联样式 二、CSS模块1. 什么是CSS模块&#xff1f;2. CSS模块的定义3. 基本示例4. 动态应用样式 三、CSS-in-JS1. 什么是CSS-in-JS&#xff1f;2. styled-components的定义3. 基本示例…

ADS 使用教程(二十八)Working with FEM Mesh Field Data in ADS

ADS 使用教程&#xff08;二十七&#xff09;Getting Started with Full 3D FEM Simulation in ADS 在这一节中&#xff0c;我们来谈论一下在ADS中处理有限元法&#xff08;FEM&#xff09;网格和场数据的步骤。 在上一节中&#xff0c;我们进行了FEM仿真&#xff0c;并保存了…

在 MinIO 使用 SVE 将 ARM 带入人工智能数据基础设施领域

MinIO 性能如此之高的原因之一是&#xff0c;我们做了其他人不会或不能做的细粒度工作。从 SIMD 加速到 AVX-512 优化&#xff0c;我们已经完成了艰巨的任务。ARM CPU 架构的最新发展&#xff0c;特别是可扩展矢量扩展 &#xff08;SVE&#xff09;&#xff0c;为我们提供了比前…

《Cross-Modal Dynamic Transfer Learning for Multimodal Emotion Recognition》

Multi-modal系列论文研读目录 文章目录 Multi-modal系列论文研读目录1.ABSTRACT2.INDEX TERMS3.INTRODUCTION4.RELATED WORKSA. MULTIMODAL EMOTION RECOGNITION 多模态情感识别1) CONVENTIONAL FUSION METHODS 常规融合方法2) TRANSFORMER-BASED FUSION METHODS 基于变压器的融…

2023河南萌新联赛第(二)场 南阳理工学院

A. 国际旅行Ⅰ 题目&#xff1a; 思路&#xff1a; 因为题意上每个国家可以相互到达&#xff0c;所以只需要排序&#xff0c;输出第k小的值就可以了。 AC代码&#xff1a; #include<bits/stdc.h> #define int long long #define IOS ios::sync_with_stdio(0);cin.tie…