react-问卷星项目(3)

项目实战

React Hooks

缓存,性能优化,提升时间效率,但是不要为了技术而优化,应该是为了业务而进行优化

内置Hooks保证基础功能,灵活配合实现业务功能,抽离公共部分,自定义Hooks或者第三方,即复用代码

React组件公共逻辑的抽离和复用

  • 之前是class组件,现在是函数组件
  • class组件:Mixing HOC render-props 来复用
  • 函数组件:使用Hooks-当前最完美的解决方法,vue3也参考这种实现方式

useState

用普通的js变量无法触发组件的更新,如下代码,方法触发了,但是数值没更新

function App() {let count = 0;function add() {count++;}// 列表页return (<>{/* <List1></List1> */}<div><button onClick={add}>点我增加 {count}</button></div></>);
}

下面的写法能触发更新。导入useState函数,设置初始数字为0,返回的是一个数组。数组的第一个值就是当前count的值,第二个是setCount函数,就是设置新值的函数,注意必须是传入新的值,不能通过count++传入

import React, { useState } from "react";
import "./List1.css";
// import List1 from "./List1";function App() {// let count = 0;const [count, setCount] = useState(0);function add() {// count++;setCount(count + 1);}// 列表页return (<>{/* <List1></List1> */}<div><button onClick={add}>点我增加 {count}</button></div></>);
}export default App;
state

一个组件的独特记忆

  • props是父组件传递过来的信息
  • state是组件内部的状态信息,不对外
  • state变化触发组件更新,重新渲染rerender
  • 特点:
    1. 异步更新,比如将添加数字抽出为组件,并在每一次点击后打印出来,会发现打印出来的数值是点击前的内容,如图所示。
      1. // stateDemo组件
        import React, { FC, useState } from "react";
        const Demo: FC = () => {const [count, setCount] = useState(0);function add() {// count++;// setCount(count + 1);// 上下两个写法一致,都是异步更新setCount((count) => count + 1);console.log(count);}return (<>{/* <List1></List1> */}<div><button onClick={add}>点我增加 {count}</button></div></>);
        };
        export default Demo;
      2.                ​​​​​​
      3. 如果一个变量不用jsx显示,就不需要用state来管理。比如设置一个变量name,页面上并不需要展示这个变量,但是每次方法的时候会调用setState来设置name,而setState只要改变就会触发页面更新,这就导致不需要的变量触发了页面的更新。这种情况下用useRef
    2. 可能会被合并,state异步更新,相同的内容执行的时候每次传入的都是最新的值,无论多少次被更新都是执行的相同步骤,导致结果应该为5的倍数却还是123这样子增加,用下面函数更新的方式可以解决合并问题
      1. // stateDemo组件
        import React, { FC, useState } from "react";
        const Demo: FC = () => {const [count, setCount] = useState(0);function add() {// count++;// setCount(count + 1); 这个多次执行会导致合并setCount((count) => count + 1);setCount((count) => count + 1);setCount((count) => count + 1);setCount((count) => count + 1);console.log(count);}return (<>{/* <List1></List1> */}<div><button onClick={add}>点我增加 {count}</button></div></>);
        };
        export default Demo;
    3. 不可变数据(重要)

      1. 不修改state的值,而是传入一个新的值。下列代码中只修改了age,其他属性使用解构语法获得,即解构这个数据对象,未修改的数据保持不变

      2. import React, { FC, useState } from "react";
        const Demo: FC = () => {const [userInfo, setUserInfo] = useState({ name: "双", age: 20 });// function changeAge() {//   setUserInfo({//     // 解构语法//     ...userInfo,//     age: 21,//   });// }function addItem() {// 不能使用list.push,因为不可变数据,要传入新值而不是改变state// concat返回的是一个新数组,push返回的不是setList(List.concat("z"));setList([...List, "z"]);}const [List, setList] = useState(["x", "y"]);return (<div><h2>state不可变数据</h2>{/* <div>{JSON.stringify(userInfo)}</div><button onClick={changeAge}></button> */}<div>{JSON.stringify(List)}</div><button onClick={addItem}>add item</button></div>);
        };
        export default Demo;
    4. 实现增删改,因为抽离出了子组件,增删改需要通过父组件触发相应的操作,涉及到一个状态提升的概念,即数据源在父组件中,子组件中只需要执行传递过来的命令,显示数据即可。

      1. 以下是子组件中的代码,基本思想是面向对象,抽离出一个列表类,因为子组件被抽出所以对子组件进行操作的时候需要通知父组件,自己删除自己不合适

      2. // 子组件 uestionCard
        import React, { FC } from "react";
        import "./QuestionCard.css";
        type PropsType = {id: string;title: string;isPublished: boolean;// 问号表示这个属性可写可不写,跟flutter语法相似deletQuestion?: (id: string) => void;pubQuestion?: (id: string) => void;
        };const QuestionCard: FC<PropsType> = (props) => {const { id, title, isPublished, deletQuestion, pubQuestion } = props;function pub(id: string) {pubQuestion && pubQuestion(id);}function del(id: string) {// 与运算符,前一个为true才去执行后一个判断条件deletQuestion && deletQuestion(id);}return (<div key={id} className="list-item"><strong>{title}</strong><br />{/* {条件判断} */}{isPublished ? (<span style={{ color: "green" }}>已发布</span>) : (<span>未发布</span>)}<buttononClick={() => {pub(id);}}>发布问卷</button><buttononClick={() => {del(id);}}>删除问卷</button></div>);
        };export default QuestionCard;
        
      3. 以下是父组件的代码,在父组件中定义对列表元素的增删改后将相应的方法传递给子元素,并在子组件中进行调用
      4. import React, { FC, useState } from "react";
        import QuestionCard from "./ListCard/QuestionCard";
        const List2: FC = () => {const [questionList, setQuestionList] = useState([{ id: "q1", title: "问卷1", isPublished: true },{ id: "q2", title: "问卷2", isPublished: false },{ id: "q3", title: "问卷3", isPublished: false },{ id: "q4", title: "问卷4", isPublished: false },]);// 异步更新所以设置为5const [count, setCount] = useState(5);function deletQuestion(id: string) {// 不可变数据setQuestionList(// 返回true是保存,false就是删除,filter返回的是一个过滤后的新数组questionList.filter((que) => {if (que.id == id) return false;else return true;}),);}function pubQuestion(id: string) {setQuestionList(// 返回的同样是新的数组questionList.map((que) => {if (que.id !== id) return que;return {...que,isPublished: true,};}),);}function add() {setCount((count) => count + 1);setQuestionList(questionList.concat({id: "q" + count,title: "问卷" + count,isPublished: false,}),);}return (<div><h1>问卷列表页2</h1><div>{questionList.map((question) => {const { id, title, isPublished } = question;return (<QuestionCardkey={id}id={id}title={title}isPublished={isPublished}deletQuestion={deletQuestion}pubQuestion={pubQuestion}/>);})}</div><div><button onClick={add}>新增问卷</button></div></div>);
        };
        export default List2;

immer

出现背景,state是不可变数据,并且state操作成本比较高,有很大的不稳定性

  • 执行相应的下载指令

npm install immer

  • vsc上安装相应的识别插件 Code Spell Checker (可选)
  • 以下代码为immer使用,和state做比较
  • // 更换年龄,对象单属性
    import React, { FC, useState } from "react";
    import { produce } from "immer";
    const Demo: FC = () => {const [userInfo, setUserInfo] = useState({ name: "双", age: 20 });function changeAge() {// setUserInfo({//   // 解构语法//   ...userInfo,//   age: 21,// });setUserInfo(produce((item) => {item.age = 21;}),);}return (<div><h2>immer可变数据</h2><div>{JSON.stringify(userInfo)}</div><button onClick={changeAge}>点击更换年龄</button></div>);
    };
    export default Demo;// 更换列表对象的属性
    import React, { FC, useState } from "react";
    import { produce } from "immer";
    const Demo: FC = () => {function addItem() {// 不能使用list.push,因为不可变数据,要传入新值而不是改变state// concat返回的是一个新数组,push返回的不是// setList(List.concat("z"));// setList([...List, "z"]);setList(produce((item) => {item.push("z");}),);}const [List, setList] = useState(["x", "y"]);return (<div><div>{JSON.stringify(List)}</div><button onClick={addItem}>add item</button></div>);
    };
    export default Demo;
  • 使用immer重构问卷列表

  • import React, { FC, useState } from "react";
    import { produce } from "immer";
    import QuestionCard from "./ListCard/QuestionCard";
    const List2: FC = () => {const [questionList, setQuestionList] = useState([{ id: "q1", title: "问卷1", isPublished: true },{ id: "q2", title: "问卷2", isPublished: false },{ id: "q3", title: "问卷3", isPublished: false },{ id: "q4", title: "问卷4", isPublished: false },]);// 异步更新所以设置为5const [count, setCount] = useState(5);function deletQuestion(id: string) {// 不可变数据// setQuestionList(//   // 返回true是保存,false就是删除,filter返回的是一个过滤后的新数组//   questionList.filter((que) => {//     if (que.id == id) return false;//     else return true;//   }),// );// 更换为immer的方法setQuestionList(produce((item) => {// 找到对应的id在列表中的位置const index = item.findIndex((q) => q.id === id);// 在原数组上进行修改使用splice即可item.splice(index, 1);}),);}function pubQuestion(id: string) {// setQuestionList(//   // 返回的同样是新的数组//   questionList.map((que) => {//     if (que.id !== id) return que;//     return {//       ...que,//       isPublished: true,//     };//   }),// );setQuestionList(produce((item) => {const q = item.find((i) => i.id === id);if (q) q.isPublished = !q.isPublished;}),);}function add() {// setCount((count) => count + 1);// setQuestionList(//   questionList.concat({//     id: "q" + count,//     title: "问卷" + count,//     isPublished: false,//   }),// );// 替换为immersetCount(produce((item) => {// 这里要返回return不然只增加到5就不递增了,暂不清楚原因return (item += 1);}),);setQuestionList(produce((item) => {item.push({id: "q" + count,title: "问卷" + count,isPublished: false,});}),);}return (<div><h1>问卷列表页2</h1><div>{questionList.map((question) => {const { id, title, isPublished } = question;return (<QuestionCardkey={id}id={id}title={title}isPublished={isPublished}deletQuestion={deletQuestion}pubQuestion={pubQuestion}/>);})}</div><div><button onClick={add}>新增问卷</button></div></div>);
    };
    export default List2;

useEffect

当一个组件渲染完成或者当某个state更新时,加载一个Ajax网络请求,使用useEffect可以实现。state实现不了,因为如果在某个组件中写上需要执行的语句,会导致任何state更新都会触发组件的更新(重新执行函数),不满足初次更新或者某个特定条件更新的两个条件

副作用:本来组件只需要执行完函数即可,但是现在却要求在特定的时间或者满足特定的条件下实现函数,即副作用

数组传入的是依赖项,不设置即为无依赖,即在第一次更新后,后续不会触发,有设置则相应的依赖项改变时会触发这个函数。数组中可以添加多个依赖项,只要其中一个被触发就会执行这个函数

import React, { FC, useState, useEffect } from "react";
import { produce } from "immer";
import QuestionCard from "./ListCard/QuestionCard";
const List2: FC = () => {// 一传函数,二传数组useEffect(() => {console.log("加载Ajax网络请求");}, []);
}

子组件销毁时的调用,能打印出来销毁,但是不知道为什么视频里打印出来单个,但是我打印的时候有其他几个子组件的销毁状态

// QuestionCarduseEffect(() => {console.log("组件挂载");return () => {console.log("组件销毁" + id);};});

解决打印两次的问题。如图所示,为什么会显示打印两次,是因为组件自销毁了一次。从react18开始,useEffect在开发环境下会执行两次,目的是模拟组件创建,销毁,再创建的流程,方便及早发现问题。发布版本就不会有这个问题

通过下列指令发布

npm run build

执行完毕后在build目录下可以查看到项目的相关目录和内容,再通过以下指令运行服务器查看打包后的项目,生产环境下useEffect只执行一次

http-server

npm install -g serve

serve -s build

其他内置Hooks

useRef
  • 一般用于操作DOM
import React, { FC, useRef } from "react";
const Demo: FC = () => {// 初始化传入默认值为null,因为初始化的时候页面还没创建// ts泛型const inputRef = useRef<HTMLInputElement>(null);function selectInput() {// 当前指向const inputElm = inputRef.current;if (inputElm) inputElm.select();}return (<div>{/* 通过ref指向DOM节点 */}<input ref={inputRef} defaultValue="hello"></input><button onClick={selectInput}>选中input</button></div>);
};
export default Demo;
  • 可传入普通的JS变量,但不会触发rerender(渲染),比如下面这个例子,打印出来的数值改变了,但是界面上展示的数值没有改变,state修改会触发rerender,想要显示出来就用state,只是保存结果就是用ref
const Demo: FC = () => {const nameRef = useRef("双"); // 不是DOM节点而是普通的JS变量function changeName() {nameRef.current = "双月亮";console.log(nameRef.current);}return (<><p>name{nameRef.current}</p><button onClick={changeName}>change name</button></>);
};
  • 要和vue3 ref区分开,vue3的ref是用于响应式监听的 

useMemo

函数组件,每次state更新都会重新执行函数,useMemo可以缓存数据,不用每次执行函数都重新生成,可用于计算量较大的场景,提高缓存性能

import React, { FC, useMemo, useState } from "react";
const Demo: FC = () => {console.log("demo");const [num1, setNum1] = useState(10);const [num2, setNum2] = useState(20);const [text, setText] = useState("hello");// 跟useEffect相似const sum = useMemo(() => {console.log("gen sum");return num1 + num2;}, [num1, num2]);return (<><p>{sum}</p><div><p>{num1}</p><buttononClick={() => {setNum1(num1 + 1);}}>add num1</button></div><div><p>{num2}</p><buttononClick={() => {setNum2(num2 + 1);}}>add num2</button></div><div>{/* form组件,受控组件 */}<input onChange={(e) => setText(e.target.value)} value={text} /></div></>);
};
export default Demo;

useMemo依赖num1和num2,两个数字变化的时候会触发相应的函数,即重新计算sum,而text不是依赖项,所以text改变的时候不会重新计算sum。

可以把useMemo作为性能优化的手段,但不要把它当成语义上的保证,即不要认为每次使用都会真正的缓存,因为Memo可能会选择性的缓存或者遗忘一个值,然后下次再缓存

useCallback

作用和useMemo一致,也是用于缓存,准们用于缓存函数,可以理解为useMemo的语法糖,下列代码中的两个方法比较类似,fn1是什么时候加载什么时候打印,fn2只有相关依赖改变的时候才会触发

import React, { FC, useState, useCallback } from "react";
const Demo: FC = () => {const [text, setText] = useState("hello");const fn1 = () => console.log("fn1", text);const fn2 = useCallback(() => {console.log("fn2", text);}, [text]);return (<><div><button onClick={fn1}>fn1</button> &nbsp;{" "}<button onClick={fn2}>fn2</button></div>{/* form组件,受控组件,即输入的时候会导致页面数值的变化,类似vue的双向数据绑定 */}<input onChange={(e) => setText(e.target.value)} value={text} /></>);
};
export default Demo;

自定义hooks

抽离出来的这个组件定义为ts组件即可

// ts文件即可,因为没有JSX片段,即div等标签
import { useEffect } from "react";
function useTitle(title: string) {useEffect(() => {document.title = title;}, []);
}
export default useTitle;

监听鼠标事件

import { useState, useEffect } from "react";
// 获取鼠标位置
function useMouse() {const [x, setX] = useState(0);const [y, setY] = useState(0);// "这个组件",即谁引用就指向谁useEffect(() => {const mouseMoveHandler = (event: MouseEvent) => {setX(event.clientX);setY(event.clientY);};// 监听鼠标事件window.addEventListener("mousemove", mouseMoveHandler);// 组件销毁时一定要解绑DOM事件,不然可能会出现内存泄漏问题// 解绑的时候需要和绑定的时候的函数相同return () => {window.removeEventListener("mousemove", mouseMoveHandler);};}, []);return { x, y };
}
export default useMouse;

模拟异步加载数据

import { useState, useEffect } from "react";
function getInfo(): Promise<string> {// 模拟异步信息return new Promise((resolve) => {setTimeout(() => {resolve(Date.now().toString());}, 1500);});
}const useGetInfo = () => {const [loading, setLoading] = useState(true);const [info, setInfo] = useState("");useEffect(() => {getInfo().then((info) => {setLoading(false);setInfo(info);});}, []);return { loading, info };
};
export default useGetInfo;

第三方Hooks
  • ahooks国内流行 官网
  • react-hooks国外流程

使用下列指令下载ahooks

npm install ahooks --save

下载完后看官网的文档选择调用即可,官网有相关的讲解

使用规则

  • 必须用useXxx格式命名
  • 只能在两个地方调用Hook(组件内,其他Hook内)
  • 必须保证每次调用顺序一致(不能把hooks放在for if内部,只能放在函数第一层,可以在hooks内部加逻辑判断)

闭包陷阱

当异步函数获取state时,可能不是当前最新的state,可使用useRef解决

  • 对闭包问题还有点疑惑,通过文心一言描述一下,下面的代码中,setTimeout 函数在调用时捕获了 count 变量的当前值(在其调用时的值)。由于 setTimeout 是异步执行的,它在 3 秒后执行时,并不会自动获取 count 的最新值。这就是闭包的作用:它保存了函数定义时的环境(在这里是 count 的值),
import React, { FC, useState, useEffect, useRef } from "react";
const Demo: FC = () => {const [count, setCount] = useState(0);function add() {setCount(count + 1);}function alertFn() {setTimeout(() => {alert(count);}, 3000);}return (<><p>闭包陷阱</p><div><span>{count}</span><button onClick={add}>add</button><button onClick={alertFn}>alert</button></div></>);
};export default Demo;

上述问题就是当异步函数获取state时,可能不是当前最新的state,接下来使用useRef解决,本质是因为count是一个值类型,而ref是引用类型

import React, { FC, useState, useEffect, useRef } from "react";
const Demo: FC = () => {const [count, setCount] = useState(0);const countRef = useRef(0);useEffect(() => {countRef.current = count;}, [count]);function add() {setCount(count + 1);}function alertFn() {setTimeout(() => {// alert(count);alert(countRef.current);}, 3000);}return (<><p>闭包陷阱</p><div><span>{count}</span><button onClick={add}>add</button><button onClick={alertFn}>alert</button></div></>);
};export default Demo;

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

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

相关文章

【Linux】包管理器、vim详解及简单配置

&#x1f680;个人主页&#xff1a;小羊 &#x1f680;所属专栏&#xff1a;Linux 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 前言一、包管理器1.1 apt1.2 yum 二、Linux编辑器——vim2.1 vim的三种模式2.2 vim普通模式常用命令2.2.1 移动…

【C++复习】C++11经典语法

文章目录 {}列表初始化1. 初始化内置类型变量2. 初始化数组3. 初始化标准容器4. 初始化自定义类型5. 构造函数初始化列表6. 初始化列表&#xff08;initializer_list&#xff09;7. 返回值初始化8. 静态成员变量和全局变量的就地初始化9. 防止类型收窄总结 decltype右值引用完美…

使用Pytorch构建自定义层并在模型中使用

使用Pytorch构建自定义层并在模型中使用 继承自nn.Module类&#xff0c;自定义名称为NoisyLinear的线性层&#xff0c;并在新模型定义过程中使用该自定义层。完整代码可以在jupyter nbviewer中在线访问。 import torch import torch.nn as nn from torch.utils.data import T…

IP 数据包分包组包

为什么要分包 由于数据链路层MTU的限制,对于较⼤的IP数据包要进⾏分包. 什么是MTU MTU相当于发快递时对包裹尺⼨的限制.这个限制是不同的数据链路对应的物理层,产⽣的限制. • 以太⽹帧中的数据⻓度规定最⼩46字节,最⼤1500字节,ARP数据包的⻓度不够46字节,要在后⾯补填 充…

IDEA在git提交时添加忽略文件

在IntelliJ IDEA中&#xff0c;要忽略target目录下所有文件的Git提交&#xff0c;你可以通过设置.gitignore文件来实现。以下是步骤和示例代码&#xff1a; 1、打开项目根目录下的.gitignore文件。也可以先下载这个.ignore插件。 2、如果不存在&#xff0c;利用上面的插件新建…

Stable Diffusion绘画 | 来训练属于自己的模型:炼丹参数调整--步数设置与计算

要想训练一个优质的模型&#xff0c;一定要认识和了解模型训练中&#xff0c;参数的作用和意义。 整个模型训练的过程&#xff0c;参数并不是一成不变的&#xff0c;也没有固定的模板&#xff0c; 当我们修改了模型训练里面的某个参数&#xff0c;很可能就需要连带其他一系列…

五.运输层

目录 5.1概述 5.2传输层的寻址与端口 熟知端口号 套接字(Socket) 5.3 UDP 特点 UDP报文格式 UDP校验 二进制反码求和 5.4 TCP 特点 可靠传输 停止等待协议 流水线方式 累计应答 流量控制 滑动窗口 拥塞控制 三次握手&#xff0c;四次握手 5.1概述 只有主机…

首屏优化之:SSR(服务端渲染)

引言 今天我们来聊一下首屏优化之SSR-服务端渲染&#xff08;Server-Side Rendering&#xff09;。 可能很多朋友并不了解什么是 SSR&#xff0c;包括在工作中写的网站是什么类型的也不太清楚&#xff0c;是 CSR 还是 SSR&#xff1f;作者在阅读过大量的文章之后&#xff0c;…

MySQL进阶篇 - 存储引擎

01 MySQL体系结构 【1】索引是在存储引擎层实现的&#xff0c;不同的存储引擎&#xff0c;索引的结构是不一样的。 【2】InnoDB引擎是MySQL5.5版本之后默认的存储引擎。 【3】MySQL体系结构分为客户端和服务器&#xff0c;服务器又分为4个层次。 02 存储引擎简介 【1】引擎…

C--编译和链接见解

欢迎各位看官&#xff01;如果您觉得这篇文章对您有帮助的话 欢迎您分享给更多人哦 感谢大家的点赞收藏评论 感谢各位看官的支持&#xff01;&#xff01;&#xff01; 一&#xff1a;翻译环境和运行环境 在ANSIIC的任何一种实现中&#xff0c;存在两个不同的环境1&#xff0c;…

BugReport中的App Processor wakeup字段意义

一、功耗字段意义&#xff1a; App processor wakeup:Netd基于xt_idletimer 待机下监视网络设备的收发工作状态&#xff0c;即当设备发生联网从休眠态变成为唤醒态时&#xff0c;会记录打醒者的uid(uid大于0)和网络类型(wifi或数据类型)、时间戳 实际日志&#xff1a;我们在B…

【Streamlit案例】制作销售数据可视化看板

目录 一、案例效果 二、数据分析 三、加载数据 四、网站前端 &#xff08;一&#xff09;网页标题和图标 &#xff08;二&#xff09;侧边栏和多选框 &#xff08;三&#xff09;主页面信息 ​&#xff08;四&#xff09;主页面图表 &#xff08;五&#xff09;隐藏部…

微信小程序操作蓝牙

主要流程&#xff1a; 1.初始化蓝牙适配器openBluetoothAdapter&#xff0c;如果不成功就onBluetoothAdapterStateChange监听蓝牙适配器状态变化事件 2.startBluetoothDevicesDiscovery开始搜寻附近的蓝牙外围设备 3.onBluetoothDeviceFound监听寻找到新设备的事件&#xff0c;…

用Python+flask+mysql等开发的Excel数据资产落地工具

话不多说 1)Excel文件上传,列表预览 2)选中要导入结构及数据的Excel文件 约束说明: 2.1)Excel文件的第一行约定为表头名称 2.2)系统自动识别字段列名及数据类型,目前不支持合并表头 3)Excel建表导入数据成功后,可在表源列表中预览查看 4)对数据表源可进行透视图设计管理,可对…

可以无限次使用o1-mini和o1-preview模型API接口的方法,并且比便宜便宜7倍以上

打开网站 https://open.xiaojingai.com 然后点击令牌页面&#xff0c;生成令牌&#xff0c;令牌就是api-key

Hive数仓操作(一)

Hive 介绍 Hive 是一个基于 Hadoop 的数据仓库工具&#xff0c;旨在简化大规模数据集的管理和分析。它将结构化数据文件映射为表&#xff0c;并提供类似 SQL 的查询功能。Hive 的数据存储在 Hadoop 分布式文件系统&#xff08;HDFS&#xff09;中&#xff0c;使用 Hive 查询语…

12.梯度下降法的具体解析——举足轻重的模型优化算法

引言 梯度下降法(Gradient Descent)是一种广泛应用于机器学习领域的基本优化算法&#xff0c;它通过迭代地调整模型参数&#xff0c;最小化损失函数以求得到模型最优解。 通过阅读本篇博客&#xff0c;你可以&#xff1a; 1.知晓梯度下降法的具体流程 2.掌握不同梯度下降法…

数据仓库简介(一)

数据仓库概述 1. 什么是数据仓库&#xff1f; 数据仓库&#xff08;Data Warehouse&#xff0c;简称 DW&#xff09;是由 Bill Inmon 于 1990 年提出的一种用于数据分析和挖掘的系统。它的主要目标是通过分析和挖掘数据&#xff0c;为不同层级的决策提供支持&#xff0c;构成…

云服务架构与华为云架构

目录 1.云服务架构是什么&#xff1f; 1.1 云服务模型 1.2 云部署模型 1.3 云服务架构的组件 1.4 云服务架构模式 1.5 关键设计考虑 1.6 优势 1.7 常见的云服务架构实践 2.华为云架构 2.1 华为云服务模型 2.2 华为云部署模型 2.3 华为云服务架构的核心组件 2.4 华…

【C++】STL标准模板库容器set

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:C ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;关联式容器set(集合)简介 &#x1f4cc;set(集合)的使用 &#x1f38f;set(集合)的模板参数列表 &#x1f38f;set(集合)的构造函数 &#x1f38f;set(集合)的迭代…