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.rhkb.cn/news/385793.html

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

相关文章

什么是大型语言模型 (LLM)

本章探讨下&#xff0c;人工智能如何彻底改变我们理解和与语言互动的方式 大型语言模型 (LLM) 代表了人工智能的突破&#xff0c;它采用具有广泛参数的神经网络技术进行高级语言处理。 本文探讨了 LLM 的演变、架构、应用和挑战&#xff0c;重点关注其在自然语言处理 (NLP) 领…

Unity XR Interaction Toolkit设置或监听手柄按键事件(三)

提示&#xff1a;文章有错误的地方&#xff0c;还望诸位大神不吝指教&#xff01; 文章目录 前言一、XRI Default Input Actions1.导入官方案例2.设置控制器绑定&#xff0c;如手柄、主/辅助按钮、操纵杆等1.要设置控制器绑定&#xff0c;如左右手 手柄、主/辅助按钮、操纵杆等…

UART编程框架详解

1. UART介绍 UART&#xff1a;通用异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter)&#xff0c;简称串口。 调试&#xff1a;移植u-boot、内核时&#xff0c;主要使用串口查看打印信息 外接各种模块 1.1 硬件知识_UART硬件介绍 UART的全称是Unive…

微信小程序教程001:小程序简介

文章目录 学习目标小程序简介1、小程序和普通网页开发的区别2、注册小程序账号3、获取小程序的AppID4、安装开发者工具4.1 了解开发者工具4.2 下载开发工具 5、设置开发者工具外观 学习目标 如何创建小程序项目小程序项目的基本组成结构小程序页面由几部分组成小程序常见的组件…

小模型狂飙!6家巨头争相发布小模型,Andrej Karpathy:大语言模型的尺寸竞争正在倒退...

过去一周&#xff0c;可谓是小模型战场最疯狂的一周&#xff0c;商业巨头改变赛道&#xff0c;向大模型say byebye~。 OpenAI、Apple、Mistral等“百花齐放”&#xff0c;纷纷带着自家性能优越的轻量化小模型入场。 小模型(SLM)&#xff0c;是相对于大语言模型&#xff08;LLM…

sql注入详解【从数据库架构分析】

文章目录 简介数据库的架构sql注入概念正常语句正常回显页面在页面中使用sql语句 跨库查询sql文件读写影响条件复现读写的路径的问题 sql注入请求分类sql注入请求类型sql注入请求方式&#xff1a;sql注入数据请求格式 数据库的增删改查数据库查询数据库添加数据库删除数据库修改…

拓扑排序+dp(消除主观臆断)

这题一开始写错的原因就是搞错了&#xff0c;处于西边的节点的编号不一定小&#xff0c;不能直接dp&#xff0c;要先进行拓扑排序 写到一般我才发现&#xff0c;其实可以一边dp&#xff0c;一边进行dp #define _CRT_SECURE_NO_WARNINGS #include<bits/stdc.h> using name…

GPT-4o mini 震撼登场:开发者的新机遇与挑战

GPT-4o mini 震撼登场&#xff1a;开发者的新机遇与挑战 一、引言二、GPT-4o mini 模型的卓越性能三、极具竞争力的价格优势四、开发者的探索与实践五、提升开发效率和创新能力的策略六、面临的挑战与应对措施七、未来展望八、总结 在科技的浪潮中&#xff0c;OpenAI 最新推出的…

论文快过(图像配准|Coarse_LoFTR_TRT)|适用于移动端的LoFTR算法的改进分析 1060显卡上45fps

项目地址&#xff1a;https://github.com/Kolkir/Coarse_LoFTR_TRT 创建时间&#xff1a;2022年 相关训练数据&#xff1a;BlendedMVS LoFTR [19]是一种有效的深度学习方法&#xff0c;可以在图像对上寻找合适的局部特征匹配。本文报道了该方法在低计算性能和有限内存条件下的…

改进智能优化算法中的一个常见错误

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ ​昨天看到网上有一个流传很广的改进鲸鱼优化算法M…

vue3 使用Mock

官网: http://mockjs.com/ 安装 npm install mockjs -Dsteps1: main.js 文件引入 import /api/mock.jssteps2: src/api/mock.js import Mock from mockjs import homeApi from ./mockData/home /*** 1.拦截的路径:mock拦截了正常NetWork/网络请求,数据正常响应* 2.方法* …

货架管理a

路由->vue的el标签->Api->call方法里calljs的api接口->数据声明const xxxData-> 编辑按钮:点击跳出页面并把这一行的数据给到表单formDataba2 保存按钮:formDataba2改过的数据->xxApi发送->查询Api 跳转仓库:把tableData.value数据清空->callXxxAp…

传输层协议——TCP

TCP协议 TCP全称为“传输控制协议”&#xff0c;要对数据的传输进行一个详细的控制。 特点 面向连接的可靠性字节流 TCP的协议段格式 源/目的端口&#xff1a;表示数据从哪个进程来&#xff0c;到哪个进程4位首部长度&#xff1a;表示该TCP头部有多少字节&#xff08;注意它…

前后端分离项目部署,vue--nagix发布部署,.net--API发布部署。

目录 Nginx免安装部署文件包准备一、vue前端部署1、修改http.js2、npm run build 编译项目3、解压Nginx免安装,修改nginx.conf二、.net后端发布部署1、编辑appsetting.json,配置跨域请求2、配置WebApi,点击发布3、配置文件发布到那个文件夹4、配置发布相关选项5、点击保存,…

搭建自己的金融数据源和量化分析平台(三):读取深交所股票列表

深交所的股票信息读取比较简单&#xff1a; 看上图&#xff0c;爬虫读取到下载按钮的链接之后发起请求&#xff0c;得到XLS文件后直接解析就可以了。 这里放出深交所爬虫模块的代码&#xff1a; # -*- coding: utf-8 -*- # 深圳交易所爬虫 import osimport pandas as pd imp…

Python代码格式化工具库之black使用详解

概要 在软件开发过程中,代码风格和一致性对于提高代码可读性和可维护性至关重要。Python 作为一种高度可读的语言,有多种代码风格指南,但手动保持代码风格的一致性可能会非常耗时且容易出错。black 是一个 Python 代码格式化工具,旨在通过自动格式化代码,使其符合 PEP 8 …

深入浅出mediasoup—WebRtcTransport

mediasoup 提供了多种 transport&#xff0c;包括 WebRtcTransport、PipeTransport、DirectTransport、PlainTransport 等&#xff0c;用来实现不同目的和场景的媒体通信。WebRtcTransport 是 mediasoup 实现与 WebRTC 客户端进行媒体通信的对象&#xff0c;是 mediasoup 最重要…

Clickhouse 生产集群部署(Centos 环境)

文章目录 机器环境配置安装 JDK 8安装 zookeeperClickhouse 集群安装rpm 包离线安装修改全局配置zookeeper配置Shard和Replica设置image.png添加macros配置启动 clickhouse启动 10.82.46.135 clickhouse server启动 10.82.46.163 clickhouse server启动 10.82.46.218 clickhous…

[网络通信原理]——TCP/IP模型—网络层

网络层 网络层概述 网络层位于OSI模型的第三层&#xff0c;它定义网络设备的逻辑地址&#xff0c;也就是我们说的IP地址&#xff0c;能够在不同的网段之间选择最佳数据转发路径。在网络层中有许多协议&#xff0c;其中主要的协议是IP协议。 IP数据包格式 IP数据报是可变长度…

汽车长翅膀:GPU 是如何加速深度学习模型的训练和推理过程的?

编者按&#xff1a;深度学习的飞速发展离不开硬件技术的突破&#xff0c;而 GPU 的崛起无疑是其中最大的推力之一。但你是否曾好奇过&#xff0c;为何一行简单的“.to(‘cuda’)”代码就能让模型的训练速度突飞猛进&#xff1f;本文正是为解答这个疑问而作。 作者以独特的视角&…