04-React脚手架 集成Axios
初始化React脚手架
前期准备
-
1.脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
- 1.包含了所有需要的配置(语法检查、jsx编译、devServer…)
- 2.下载好了所有相关的依赖
- 3.可以直接运行一个简单效果
-
2.react提供了一个用于创建react项目的脚手架库: create-react-app
-
3.项目的整体技术架构为: react + webpack + es6 + eslint
-
4.使用脚手架开发的项目的特点: 模块化, 组件化, 工程化
全局安装工具
首先要在全局安装create-react-app
,推荐使用yarn来安装,因为react和yarn都是facebook出的。但是大部分人用的npm,也是完全可以,这里用npm演示
全局安装react脚手架工具:
npm i -g create-react-app
i代表install
,g代表global全局
,create-react-app代表react脚手架
安装后查看版本:
D:\WebProject\ReactProject>npm create-react-app -v
6.14.16
我们依靠这个就可以在想要的目录下面创建react工程
安装脚手架
切换到想要创建脚手架的目录
使用命令:create-react-app 工程名字
名字仅限英文,不要用特殊字符
安装完毕之后,可以看到React提示的四个命令:
npm start 启动项目Starts the development server.npm run build 打包Bundles the app into static files for production.npm test 测试模式启动Starts the test runner.npm run eject 将隐藏的webpack配置文件显示出来Removes this tool and copies build dependencies, configuration filesand scripts into the app directory. If you do this, you can’t go back!
我们可以查看配置文件,package.json,所有启动短命令已经配置好了
输入npm start
,启动项目
脚手架结构
这种项目也叫SPA项目:
- S–single
- P–page
- A–app
public ---- **静态资源文件夹**favicon.icon ------ 网站页签图标index.html -------- **主页面,整个项目只有这一个html文件,作为基点**logo192.png ------- logo图logo512.png ------- logo图manifest.json ----- 应用加壳的配置文件robots.txt -------- 爬虫协议文件
src ---- **源码文件夹**App.css -------- App组件的样式App.js --------- App组件App.test.js ---- 用于给App做测试index.css ------ 样式index.js ------- 入口文件logo.svg ------- logo图reportWebVitals.js--- 页面性能分析文件(需要web-vitals库的支持)setupTests.js---- 组件单元测试的文件(需要jest-dom库的支持)
启动项目后默认页面
详解index.html
作为整个项目里唯一一个html文件,也是整个app的基点,有必要详细解读一下
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><!-- %PUBLIC_URL%代表public文件夹的路径 --><link rel="icon" href="%PUBLIC_URL%/favicon.ico" /><!-- 开启理想视口,移动端适配 --><meta name="viewport" content="width=device-width, initial-scale=1" /><!-- 配置浏览器页签颜色(仅支持安卓原生浏览器) --><meta name="theme-color" content="#000000" /><!-- 描述网站信息的,搜索引擎会读取这个 --><metaname="description"content="Web site created using create-react-app"/><!-- 苹果手机的Safari把网页添加到主屏幕后,启动图标 --><link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /><!-- 将web套壳成为安卓或ios的安装包用,(应用加壳技术) --><link rel="manifest" href="%PUBLIC_URL%/manifest.json" /><!-- 网页tab的名字 --><title>React App</title></head><body><!-- 如果客户端浏览器不支持JS的运行 --><noscript>You need to enable JavaScript to run this app.</noscript><!-- 根标签 --><div id="root"></div></body>
</html>
src目录解析
App组件相关
webpack入口相关:index.js
如果是用webpack打包,那么默认情况下,index.js就是入口文件
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<React.StrictMode><App /></React.StrictMode>
);**上下这两种写法是完全等价的**ReactDOM.render(<App />,document.getElementById('root'))
<React.StrictMode>
这个<React.StrictMode>并不是ES5的严格模式,而是React检查子组件是否有不合理的地方
比如:ref=字符串,或者一些过时的写法,来做一些检查<React.StrictMode><App /></React.StrictMode>
reportWebVitals()
作为入口的最底下的方法,是用来记录网页的性能检测
至于public里的index.html是如何被src的index.js找到的,这个我们不需要关心,是React用webpack配置好的。所以index.html的名字是不可以随便动的,动了就找不到了。
我们写一个小应用,只需要去关注,index.html 主页面
,App.js App组件
,index.js 入口文件
,这三个就够了。
注意:工程里import 进js和jsx都是不需要写后缀的
写一个小demo
1.我们保持public中的Index.html不变
2.修改src下面的APP.js以及index.js文件
App.js: 【注意:创建好的组件一定要暴露出去】
//创建外壳组件APP
import React from 'react'class App extends React.Component{render(){return (<div>Hello world</div>)}
}export default App
index.js: 【主要的作用其实就是将App这个组件渲染到页面上】
//引入核心库
import React from 'react'
import ReactDOM from 'react-dom'
//引入组件
import App from './App'ReactDOM.render(<App />,document.getElementById("root"))
这样在重新启动应用,就成功了。
我们也不建议这样直接将内容放入App组件中,尽量还是用内部组件。
我们在顶一个Hello组件:
import React,{Componet} from 'react'export default class Hello extends Componet{render() {return (<h1>Hello</h1>)}
}
在App组件中,进行使用
class App extends Component{render(){return (<div><Hello /></div>)}
}
这样的结果和前面是一样的。
但是由于普通的Js和组件都是js,所一最好组件使用jsx去展示。
样式模块化
前面会有一个问题,当css和组件越来越多的时候,如果css不分层不分级,就会造成混乱的场景,同时带来样式冲突难以管理。
当组件逐渐增多起来的时候,我们发现,组件的样式也是越来越丰富,这样就很有可能产生两个组件中样式名称有可能会冲突,这样会根据引入App这个组件的先后顺序,后面的会覆盖前面的。
同名造成的冲突
传统的引入方式:
修改后的引入方式:
为了避免这样的样式冲突,我们采用下面的形式:
1.将css文件名修改: hello.css — >hello.module.css
css内部不用做出修改,也就是以对象形式进行css导入
注意:不要用{}套css对象,这玩意只是个标记,不是解构出来的!!!
会如果套了会导致对象获取不到!!!
2.引入并使用的时候改变方式:
import React from "react";
//引入css,此时css都以对象形式存在hello中
import hello from "./hello.module.css"export default class Hello extends React.Component{render(){return(// 以对象形式获取css<div className={hello.title}>Hello world</div>)}
}
逆天导入方法
有些项目为了避免大量导入import时导致后面有一串路径,就采用这种简写方式,即每个文件夹下组件名和css名字都是 index的名字,这种情况下,导入的路径写到包就可以了,因为如果不写最后的文件名,默认就导入index
就会从这种具体到文件的导入
import Hello from './component/Hello/hello.jsx'
import Welcome from './component/Welcome/welcome.jsx'
变成这种,导入截止到包名,后缀默认用index
import Hello from './component/Hello'
import Welcome from './component/Welcome'
这种导入方法肯定是不推荐的,但是有的公司可能就会用到这种,所以要提一下
React插件推荐
可以快速帮助你创建模板
比如输入rcc,自动根据文件名创建类组件
rcc:react class component
输入rfc,自动根据文件名创建函数式组件
rfc:react function component
回车就自动生成类组件了,函数式组件也是一样
等等一些其他的快捷键可以自己去查,非常方便
组件化编码的流程
- 拆分组件: 拆分界面,抽取组件 (页面拆组件的过程中如果拆完了不知道叫啥名字,多半是没拆好)
- 实现静态组件: 使用组件实现静态页面效果
- 实现动态组件
3.1 动态显示初始化数据(数据驱动页面变化)
3.1.1 数据类型
3.1.2 数据名称
3.1.2 保存在哪个组件?
3.2 交互(从绑定事件监听开始)
脚手架插件
nanoId
相比于uuid更加轻量化,生成一个唯一id
UUID:生成唯一时间戳的库
npm i uuid
(库比较大)
npm i nanoid
(库小,很快安装)/ yarn add nanoid
用法:
import {nanoid} from 'nanoid'
//调用,直接就可以生成一个随机ID
nanoid()
PropTypes
脚手架本身并不自带这个,需要自行安装,完成类型的约束
用npm进行安装,安装后即可进行操作,对传入参数进行类型约束
npm install prop-types
static propTypes = {addTodo: proptypes.func.isRequired,
};
TodoList组件Demo总结
拆分组件、实现静态组件,注意:className、style的写法
动态初始化列表,如何确定将数据放在哪个组件的state中?
- 1)某个组件使用:放在其自身的state中
- 2)某些组件使用:放在他们共同的父组件state中(官方称此操作为:状态提升)
关于父子之间通信:
- 1)【父组件】给【子组件】传递数据:通过props传递
- 2)【子组件】给【父组件】传递数据:通过props传递,要求父提前给子传递一个函数
注意defaultChecked 和 checked的区别,类似的还有:defaultValue 和 value
状态在哪里,操作状态的方法就在哪里
兄弟之间的组件通信,用Pub-Sub订阅机制实现,后续会有
脚手架集成Axios
Ajax和Axios是啥就不多说了
React本身并不带这些插件,所以需要额外去引入这些插件
前期安装插件
Axios官网
npm安装Axios npm install axios
npm查看版本 npm list axios
查看package里的依赖
JSX内导入
安装完成后就可以使用这种方式在JSX内导入
import axios from "axios";
方法里面发起Get请求,其他的用法可以看官网:Axios请求官网例子
startAxios = () => {// 这里会先看自身有没有这个路径下的资源,没有的话才会去转发给代理服务器axios.get("http://localhost:3000/api/test").then((response) => {console.log("成功了", response.data);},(error) => {console.log("失败了", error);});};
请求发起后发生跨域问题
这个时候就需要代理来解决跨域问题,跨域为什么要用代理是什么请自行搜索
请求实际上是已经到了server,但是Ajax引擎不许跨域的值返回,所以跨域给拦下来的本质是Ajax引擎把响应给拦住了
代理服务器与server是同一个域名+端口上的
只完成一个转发功能,代理服务器把请求转到Server上,Server的内容还给代理,代理上因为没有Ajax引擎,就把返回来的数据还给Client,由于代理与Client同源,没有跨域限制,也就解决了跨域问题
代理配置
package.json配置
可以叫做全局代理,因为它直接将代理配置在了配置文件 package.json
中
"proxy":"http://localhost:5000"
// "proxy":"请求的地址"
追加的配置文件
这样配置代理时,首先会在在原请求地址http://localhost:3000/api/test
上访问,如果访问不到资源,就会转发到这里配置的地址上去请求,也就是http://localhost:5000/api/test
,如果这时候还没有,就404
说明:
- 优点:配置简单,前端请求资源时可以不加任何前缀。
- 缺点:不能配置多个代理。
- 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)
修改了配置类的操作一定要重启!!!
setupProxy.js配置
这里不用记,会查会配即可,但是要注意 http-proxy-middleware 与脚手架的版本兼容
一定在src目录下!!!
-
第一步:创建代理配置文件
在src下创建配置文件:src/setupProxy.js
-
编写setupProxy.js配置具体代理规则:
const proxy = require('http-proxy-middleware')module.exports = function(app) {app.use(proxy('/api1', { //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)changeOrigin: true, //控制服务器接收到的请求头中host字段的值/*changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000changeOrigin默认值为false,但我们一般将changeOrigin值设为true*/pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)}),proxy('/api2', { target: 'http://localhost:5001',changeOrigin: true,pathRewrite: {'^/api2': ''}})) }
两个关键配置属性详解:
changeOrigin:
控制服务器收到的请求头中Host的值(本次请求从哪来的)
true:Origin是走代理的,false:Origin不走代理,是走代理前的host 。
一般都是true,避免后端做奇奇怪怪的check
changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
changeOrigin默认值为false,但我们一般将changeOrigin值设为true
pathRewrite:
重写请求路径(必须) { "要被替换的路径": "替换成啥" },这里的规则是去掉了 /api1
相当于去掉了 /api1 对于后端来说不会有api1的前缀,这只是前端区分请求走哪个代理的标识,真正发起请求给后端要把这种标识干掉当然,这种做法也不绝对,也可以把重写的路径换成需要的东西,灵活配置即可
说明:
- 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
- 缺点:配置繁琐,前端请求资源时必须加前缀。
setupProxy.js配置过程中遇到的坑
参考文档
因为const proxy = require("http-proxy-middleware");
这个中间件的版本不兼容,导致无法启动项目,具体现象是:启动后台无报错,但是页面无内容
要把第一句的中间件获取换成这个,项目就可以正常启动了
const {createProxyMiddleware: proxy} =require('http-proxy-middleware');
例子
分别根据 /api1
和 /api2
这两个前缀,去到不同的server上面
代码如下
可以看到都是访问自己的前端端口,如果当前资源没找到,就会去找上面配置的代理路径(如果配了多个url前缀
,就会根据url前缀
去不同server)
class App extends React.Component {getData1 = () => {axios.get("http://localhost:3000/api1/search/users2").then((response) => {console.log("成功了", response.data);},(error) => {console.log("失败了", error);});};getData2 = () => {axios.get("http://localhost:3000/api2/search/users2").then((response) => {console.log("成功了", response.data);},(error) => {console.log("失败了", error);});};render() {return (<div className="todo-container"><button onClick={this.getData1}>获取数据1</button><button onClick={this.getData2}>获取数据2</button></div>);}
}
export default App;
执行结果:
两个node的Server也都正常执行了
兄弟组件传值Pub-Sub
之前可以看到不同的组件之间传值只能通过state的状态提升来进行传值,但是很明显这么做在大量数据交互的时候会变得巨难管理,所以我们要引入Pub-Sub.js来实现兄弟组件传值。
PubSub组件传值官网
npm安装命令
npm install pubsub-js
版本查看
npm pubsub-js -v
快速起步
import PubSub from 'pubsub-js' //引入
PubSub.subscribe('用于识别的key', function(msg, data){ }); //订阅
PubSub.publish('用于识别的key', data) //发布消息
注意:
适用于任意组件之前的消息沟通
谁用谁接,谁传谁发
特别注意:
一定要先开启监听,再发布,要不然发半天没人听发了也没有用
发布消息(publish)
消息发布,第一个参数订阅key(后续订阅会用到),第二个参数是值,下面这两个都是完全可以的传值方式
PubSub.publish('MY TOPIC', 'hello world!');
PubSub.publish('MY TOPIC', { info: "info" });还有一种同步发布,但是这种性能略强,但是不推荐,但有可能出现安全问题,慎重。用上面那两个就够了
PubSub.publishSync('MY TOPIC', 'hello world!');
比如这种,就可以传入对象进去,发布给obj-key
的这个消息订阅方
注意这里传入对象不要用展开符
订阅消息(subscribe)
// msg是必须接受的,如果实在不想接受可以传个占位符
// var mySubscriber = function (_, data)
var mySubscriber = function (msg, data) {console.log(msg, data);
};// 生成一个token是为了后续停止订阅用的,有专门api来关闭订阅
var token = PubSub.subscribe('MY TOPIC', mySubscriber);// 关闭订阅(可以用在组件卸载这种)
PubSub.unsubscribe(token);
也可以用箭头函数,这两种写法是完全等价的
var mySubscriber = function (msg, data) {console.log(msg, data);
};// 生成一个token是为了后续停止订阅用的,有专门api来关闭订阅
var token = PubSub.subscribe('MY TOPIC', (msg, data)=>{// 打印出来的msg就是订阅keyconsole.log(msg, data);
});
在实际代码中加入,发现token作用域出现问题了,所以要改一下
用this修改一下,再用箭头函数优化一下
代码示例
三个组件集成在一个文件里,实现测试
import React from "react";
import PubSub from "pubsub-js";
import "./App.css";// 一定要先开启监听,再发布,要不然发半天没人听发了也没有用
class PublishInfo extends React.Component {publishInfo = () => {var obj = { info: "info" };PubSub.publish("publish-key", obj);};render() {return (<div><button onClick={this.publishInfo}>publishInfo(后开启发布)</button></div>);}
}// 一定要先开启监听,再发布,要不然发半天没人听发了也没有用
class SubscriptInfo extends React.Component {subScriptInfo = () => {this.token = PubSub.subscribe("publish-key", (msg, data) => {// 这里只接受一个data也是可以的console.log(msg, data);});};unsubscribeBeforeUnmount = () => {// 模拟组件卸载前函数,暂停监听。当然放在生命周期里面也可以console.log("tokenID:", this.token, PubSub.unsubscribe(this.token));};render() {return (<div><button onClick={this.subScriptInfo}>subScriptInfo(先开启监听)</button><button onClick={this.unsubscribeBeforeUnmount}>模拟卸载组件(最后)</button></div>);}
}
// 创建并暴露App组件
class App extends React.Component {render() {return (<div><SubscriptInfo /><PublishInfo /></div>);}
}
export default App;
极端场景
这种,从F组件给C组件传值,只要key是一样得,就可以通信到,所以跨组件传值非常方便
Fetch发送请求(扩展)
首先 fetch 也是一种发送请求的方式,它是在 xhr 之外的一种,我们平常用的 Jquery 和 axios 都是封装了 xhr 的第三方库,而 fetch 是js官方自带的库(也是XMLHttpRequest的升级版),同时它也采用的是 Promise 的方式,大大简化了写法
由于是js内置,所以甚至可以在控制台运行
在代码里如何使用呢?
fetch("https://api.github.com/users/ruanyf").then((response) => response.json()).then((json) => console.log(json)).catch((err) => console.log("Request Failed", err));
搞个按钮触发一下fetch就可以用了
它的使用方法和 axios 非常的类似,都是返回 Promise 对象,但是不同的是, fetch 关注分离,它在第一次请求时,不会直接返回数据,会先返回联系服务器的状态,在第二步中才能够获取到数据
我们需要在第一次 then
中返回 response.json()
因为这个是包含数据的 promise 对象,response.json()
是一个异步操作,取出所有内容,并将其转为 JSON 对象。再调用一次 then
方法即可获取到对象,
但是这么多次的调用 then
并不是我们所期望的,相信看过之前生成器的文章的伙伴,已经有了想法。
我们可以利用 async
和 await
配合使用,来简化代码
可以将 await
理解成一个自动执行的 then
方法,这样清晰多了
async function getJSON() {let url = 'https://xxx';try {let response = await fetch(url);return await reasponse.json();} catch (error) {console.log('Request Failed', error);}
}
最后关于错误对象的获取可以采用 try...catch
来实现
关于 fetch 的更多内容
强烈推荐阮一峰老师的博文:fetch
相关文章:

04-React脚手架 集成Axios
初始化React脚手架 前期准备 1.脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目 1.包含了所有需要的配置(语法检查、jsx编译、devServer…)2.下载好了所有相关的依赖3.可以直接运行一个简单效果 2.react提供了一个用于创建react项目的脚手架库…...

时序预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost时间序列预测
时序预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost时间序列预测 目录 时序预测 | MATLAB实现基于BiLSTM-AdaBoost双向长短期记忆网络结合AdaBoost时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.Matlab实现BiLSTM-Adaboost…...

【nlp】3.6 Tansformer模型构建(编码器与解码器模块耦合)
Tansformer模型构建(编码器与解码器模块耦合) 1. 模型构建介绍2 编码器-解码器结构的代码实现3 Tansformer模型构建过程的代码实现4 小结1. 模型构建介绍 通过上面的小节, 我们已经完成了所有组成部分的实现, 接下来就来实现完整的编码器-解码器结构耦合. Transformer总体架…...

【【Linux系统下常用指令学习 之 二 】】
Linux系统下常用指令学习 之 二 文件查询和搜索 文件的查询和搜索也是最常用的操作,在嵌入式 Linux 开发中常常需要在 Linux 源码文件中查询某个文件是否存在,或者搜索哪些文件都调用了某个函数等等。 1、命令 find find 命令用于在目录结构中查找文件…...
Git-将指定文件回退到指定版本
场景1:修改了文件/path/to/file,没有提交,但是觉得改的不好,想还原。 解决: git checkout -- /path/to/file 场景2:修改了文件/path/to/file,已经提交,但是觉得改的不好,…...

docker环境安装
环境 主机环境 1. 宿主机环境 ubuntu-22.04.3-live-server-amd64 ,下载地址: https://mirrors.aliyun.com/ubuntu-releases/22.04.3/ubuntu-22.04.3-live-server-amd64.iso 2. apt 包管理器,镜像源修改 : 将 http://cn.archive.ubunt…...

【Java】智慧工地云平台源码(APP+SaaS模式)
在谈论“智慧工地”之前,我们首先得知道传统工地为什么跟不上时代了。 说起传统工地,总有一些很突出的问题:比如工友多且杂,他们是否入场、身体状况如何,管理人员只能依靠巡查、手工纪录来判断,耗时耗力&am…...

2016年11月10日 Go生态洞察:七年的Go语言旅程
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
深入了解Java中SQL优化的关键技巧与实践
引言 介绍SQL优化对于Java应用性能的重要性,并概述本文将要讨论的内容。 1. 编写高效的SQL语句 - **索引的类型与使用:** 解释B-Tree索引、哈希索引等类型的区别,以及如何根据查询需求合理创建和使用索引。 - **查询优化器:** 说明…...

6.3.WebRTC中的SDP类的结构
在上节课中呢,我向你介绍了sdp协议, 那这节课呢,我们再来看看web rtc中。是如何存储sdp的?也就是sdp的类结构,那在此之前呢?我们先对sdp的内容啊,做一下分类。因为在上节课中呢,虽然…...

ArcGis如何用点连线?
这里指的是根据已有坐标点手动连线,类似于mapgis中的“用点连线”,线的每个拐点是可以自动捕捉到坐标点的,比直接画精确。 我也相信这么强大的软件一定可以实现类似于比我的软件上坐标时自动生成的线,但是目前我还没接触到那里&a…...

自定义精美商品分类列表组件 侧边栏商品分类组件 category组件(适配vue3)
随着技术的发展,开发的复杂度也越来越高,传统开发方式将一个系统做成了整块应用,经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改,造成牵一发而动全身。通过组件化开发,可以有效实现单…...
造一个float类型二维矩阵,并将二维矩阵存快速储到一个float*中(memcpy)
// 创建并初始化一个二维数组 std::vector<std::vector<float>> createAndInitializeArray(int rows, int cols) {std::vector<std::vector<float>> array(rows, std::vector<float>(cols));float value 0.0f;for (int i 0; i < rows; i) {…...
python通过继承、组合、委托组织类
1 python通过继承、组合、委托组织类 #概念描述1继承属性查找X.name2多态方法调用X.method,取决于X的类型3封装方法和运算符实现行为 通常来说,独特的运算使用独特的方法名称,不要依赖于调用标记。 python组织类结构的方式包括:…...

OSG粒子系统与阴影-自定义粒子系统示例<1>(4)
自定义粒子系统示例(一) 自定义粒子系统示例(一)的代码如程序清单11-5所示: /* 自定义粒子系统示例1 */ void particleSystem_11_5(const string &strDataFolder) {osg::ref_ptr<osgViewer::Viewer> viewer new osgViewer::Viewer();osg::ref_ptr<os…...

激活函数与其导数:神经网络中的关键元素
激活函数是神经网络中的重要组成部分,有力地推动了深度学习的发展。然而,仅仅了解和选择激活函数是不够的,我们还需要理解激活函数的导数。本文将详细介绍激活函数的概念、作用及其导数的重要性,并探究导数对神经网络训练的影响。…...

微信公众号对接获取用户openid预约项目心路全历程
公众号对接获取openid全历程 一、背景二、选型三、开始修改若依框架四、自己搭后端框架五、前端框架uni-app修改六、对接获取公众号登录用户openId七、总结 一、背景 老板接了朋友的一个公众号需求,要求做一个简单的疫苗预约系统。功能是获取当前登录用户࿰…...

大中小协作 共筑科学梦——华中科技大学附属花城中学举办首届科技节
为普及科学知识,张扬科学精神,创设浓郁的科学氛围,11月24日,华中科技大学附属花城中学举办了以“走近科学,触碰未来”为主题的首届科技节暨科创文化展示周活动。学生们在学习中感受科技的魅力,在“玩”中感…...
ElasticSearch之Health API
查看当前集群全部健康指标的信息,执行如下命令: curl -X GET "https://localhost:9200/_health_report?pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下: {&quo…...

图的建立基本操作
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> // 添加头文件#define MAX_VERTEX_NUM 100 //图中最大顶点数//struct ArcNode* nextarc; //ArcNode* firstarc; //这两个是很有必要的,如果你没有这两个指针,你就无法判…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...