后端程序员入门react笔记(五)ajax请求

news2024/11/18 17:28:44

常见的ajax

  • Ajax
    最原始的方式,基于原生的js

  • XmlHttpRequest
    多个请求之间如果有先后关系,会存在很多层回调的问题,也是基于原生js

  • Jquery Ajax
    基于原生XHR封装,依赖Jquery框架,由jquery 框架去封装原生的XML(Xml)封装的API,支持JSONP,如果只是用于发送Ajax而使用jQuery,不推荐。

  • Fetch
    Fetch是一种HTTP数据请求的方式,是XMLHttpRequest的一种替代方案。Fetch不是ajax的进一步封装,它们是两个东西。Fetch函数就是原生js,和XMLHttpRequest是同级别的原生js的api,Fetch 的出现就是为了解决 XHR 的问题,它实现了 Promise 规范,返回 Promise 实例;而 Promise 是为解决异步回调问题而摸索出的一套方案。

  • axios
    对原生XHR的封装,需要进行安装,可以在客户端使用,也可以在node端使用,Axios 是一个基于 promise (Promise 是异步编程的一种解决方案)的 HTTP 库,可以用在浏览器和 node.js 中。

Axios

接下来我们重点了解一下axios

特性

  • 可以从浏览器中创建 XMLHttpRequests
  • 可以从 node.js 创建 http 请求
  • 支持 Promise API
  • 可以拦截请求和响应
  • 可以转换请求数据和响应数据
  • 可以取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

基本使用

我们只需要在组件中引入axios组件即可使用,我们简单举个列子看一下,请求响应的处理在 then 和 catch 回调中,请求正常会进入 then ,请求异常则会进 catch

import React, {Component} from 'react';
//引入组件
import axios from 'axios';

class App extends Component {
    getData = () => {
        //发送请求   请求响应的处理在 then 和 catch 回调中,请求正常会进入 then ,请求异常则会进 catch
        axios.get('http://localhost/data').then((res) => {
            console.log(res);
        }).catch((err) => {
            console.log(err);
        })
    }
    render() {
        return (
            <button onClick={this.getData}> 点击获取数据</button>
        );
    }
}
export default App;

发送请求的两种方式

axios提供了两种方式来发送请求, 一种是通过axios(config)来发送请求,另一种就是上面列子中的axios.get,

axios(config)

config是一个对象,里面配置了请求相关的信息,比如下面这个例子

        axios(
            {
                //请求方法
                method: 'post',
                //请求url
                url: '/user/12345',
                //请求参数
                data: {
                    firstName: 'Fred',
                    lastName: 'Flintstone'
                }
            }
        ).then(res=>{//请求成功
            console.log(res);
        }).catch(err=>{//请求失败
            console.log(err);
        })
  • config可配置的相关项
    config里面可以配置代理,超时,相应的最大尺寸,是否重定向等等
{
   // `url` 是用于请求的服务器 URL
  url: '/user',
  // `method` 是创建请求时使用的方法
  method: 'get', // default
  // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',
  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  transformRequest: [function (data, headers) {
    // 对 data 进行任意转换处理
    return data;
  }],
  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理
    return data;
  }],
  // `headers` 是即将被发送的自定义请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},
  // `params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params: {
    ID: 12345
  },
   // `paramsSerializer` 是一个负责 `params` 序列化的函数
  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  paramsSerializer: function(params) {
    return Qs.stringify(params, {arrayFormat: 'brackets'})
  },
  // `data` 是作为请求主体被发送的数据
  // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  // - Node 专属: Stream
  data: {
    firstName: 'Fred'
  },
  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout: 1000,
   // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false, // default
  // `adapter` 允许自定义处理请求,以使测试更轻松
  // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
  adapter: function (config) {
    /* ... */
  },
 // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
  // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },
   // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'json', // default
  // `responseEncoding` indicates encoding to use for decoding responses
  // Note: Ignored for `responseType` of 'stream' or client-side requests
  responseEncoding: 'utf8', // default
   // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
  xsrfCookieName: 'XSRF-TOKEN', // default
  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
  xsrfHeaderName: 'X-XSRF-TOKEN', // default
   // `onUploadProgress` 允许为上传处理进度事件
  onUploadProgress: function (progressEvent) {
    // Do whatever you want with the native progress event
  },
  // `onDownloadProgress` 允许为下载处理进度事件
  onDownloadProgress: function (progressEvent) {
    // 对原生进度事件的处理
  },
   // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength: 2000,
  // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
  validateStatus: function (status) {
    return status >= 200 && status < 300; // default
  },
  // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
  // 如果设置为0,将不会 follow 任何重定向
  maxRedirects: 5, // default
  // `socketPath` defines a UNIX Socket to be used in node.js.
  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.
  // Only either `socketPath` or `proxy` can be specified.
  // If both are specified, `socketPath` is used.
  socketPath: null, // default
  // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
  // `keepAlive` 默认没有启用
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),
  // 'proxy' 定义代理服务器的主机名称和端口
  // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
  // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
  proxy: {
    host: '127.0.0.1',
    port: 9000,
    auth: {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  },
  // `cancelToken` 指定用于取消请求的 cancel token
  // (查看后面的 Cancellation 这节了解更多)
  cancelToken: new CancelToken(function (cancel) {
  })
}

  • 配置全局默认值
    我们可以给axios配置默认值
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

axios.option

我们也可以使用axios.get()这种方式发送请求,里面定义data和config

        axios.get('http://localhost/data').then().catch()
        axios.post('http://localhost/data',{name:'张三'},{timeout: 1000}).then().catch()

拦截器

axios提供了请求拦截器和响应拦截器,帮助我们在请求前对config做一些配置,判断是否重复提交,或者对config做一些检查以及配置纠正等,响应拦截器帮助我们根据不同的返回内容做不同的数据处理,相关案例如下

import React, {Component} from 'react';
//引入组件
import axios from 'axios';
// 创建一个请求拦截器 请求头附加一个token 值是1111
const requestInterceptor = axios.interceptors.request.use(
    (config) => {
        config.headers['token'] = '1111111';
        return config;
    },
    (error) => {
        // 处理请求错误
        return Promise.reject(error);
    }
);
// 创建一个响应拦截器
const responseInterceptor = axios.interceptors.response.use(
    (response) => {
        // 处理响应数据
        return response;
    },
    (error) => {
        console.log(error);
        // 处理响应错误
        return Promise.reject(error);
    }
);
class App extends Component {

    // 添加请求拦截器

    getData = () => {
        axios.post('http://localhost/data',{name:'张三'},{timeout: 1000}).then(res=>{
            console.log(res);
        },err=>{
            console.log(err);
        }).catch(err=>{
            console.log(err);
        })
    }
    render() {
        return (
            <button onClick={this.getData}> 点击获取数据</button>
        );
    }
}
// 移除拦截器
axios.interceptors.request.eject(requestInterceptor);
axios.interceptors.response.eject(responseInterceptor);
export default App;

开启后端服务,发送请求

我们知道,我们前端的服务器是3000端口,但是我们后端的服务器不一定是3000,也可能是80端口,现在我启动一个go编写的后台服务,调用一下接口
我这现在有一个获取博客详情的接口,端口号是8080
在这里插入图片描述
接下来我们通过axios访问一下

    getData = () => {
        axios.get('http://127.0.0.1:8080/v1/blog/detail?id=123').then(res=>{
            console.log(res);
        },err=>{
            console.log(err);
        }).catch(err=>{
            console.log(err);
        })
    }

问题来了,浏览器发送了请求,后端的gin服务收到了请求,但是结果没过来,浏览器报错说我跨域了。这说明主要问题在Ajax引擎对响应的处理那块。怎么办?作为后端人员最熟悉不过的方式就是做个代理。
在这里插入图片描述

配置代理

怎么配置代理呢?我们可以在react项目根目录下的package.json里面配置上这样一句声明,这表示请求的3000端口的请求会被转发到8080,对于后端人员都明白,这个转发规则是什么呢?优先匹配3000服务的路径,匹配不到再转去8080服务。

"proxy": "http://127.0.0.1:8080"
  • 把axios的请求改为本域名下路径就可以了
 axios.get('/v1/blog/detail?id=123')
  • 添加完毕后我们重启服务,响应数据回来了
    在这里插入图片描述
  • 但是上面这种有一个问题,就是不够灵活,比如我们常用的/blog/v1/detail需要代理到blog服务,但是我/goods/v1/detail是要代理到goods服务器。我们需要更灵活的配置方式,那么我们就需要借助一个第三方库http-proxy-middleware,接下来我们在src目录下新建一个setupProxy.js文件,内容如下
const {createProxyMiddleware} =require('http-proxy-middleware')
module.exports=function(app){
    app.use(
        createProxyMiddleware('/api',{ // api 是需要转发的请求(所有带/api 前缀的请求都会转发给8080)
            target:'http://localhost:8080', // 配置转发目标地址(能返回数据的服务器地址)
            changeOrigin:true, // 控制服务器接收到的请求头中host字段的值
            //设置为true,服务器端接收的host就是8080,如果为false,那么后端服务器接收到的host就是3000
            //  changeOrigin 默认值为false 但我们一般将changeOrigin值设为true
            pathRewrite:{'^/api':''} // 去请求前缀,保证交给后台服务器是正常请求地址(必须配置)
        }),

    )
}

  • 在发送请求的时候,如果是需要代理,我们只需要在原来的url上面加上/api/就可以了,或者和后端协商好某个统一前缀也能解决。
 axios.get('/api/v1/blog/detail?id=123')//被转发后就是/v1/blog/detail?id=123

案例一 用户搜索

静态页面渲染

  • index.js
import React from "react";
import ReactDOM  from "react-dom/client";
import App from "./App";
const content=<App/>
const root=ReactDOM.createRoot(document.getElementById("root"))
root.render(content)
  • app.jsx
import React, {Component} from 'react';
import Search from './components/Search/Search'
import List from "./components/List/List";

class App extends Component {
    render() {
        return (
            <div>
                <div className="container">
                    <Search></Search>
                    <List></List>
                </div>
            </div>
        );
    }
}

export default App;
  • Search.jsx
import React, {Component} from 'react';

class Search extends Component {
    render() {
        return (
            <div>
                <section className="jumbotron">
                    <h3 className="jumbotron-heading">Search Github Users</h3>
                    <div>
                        <input type="text" placeholder="enter the name you search"/>&nbsp;
                        <button>Search</button>
                    </div>
                </section>
            </div>
        );
    }
}

export default Search;
  • list.jsx
import React, {Component} from 'react';
import './List.css'

class List extends Component {
    render() {
        return (
            <div>
                <div className="row">
                    <div className="card">
                        <a rel="noreferrer" href="https://github.com/reactjs" target="_blank">
                            <img alt="head_protrait" src="https://avatars.githubusercontent.com/u/6412038?v=3" style={{width:'100px'}}/>
                        </a>
                        <p className="card-text">reactjs</p>
                    </div>
                </div>
            </div>
        );
    }
}

export default List;

在这里插入图片描述

配置代理 获取数据

真实接口地址如下https://api.github.com/search/users?q=react,我们先拿到数据吧,点击search获取到input的内容,并尝试请求数据

  • Search.jsx
import React, {Component, createRef} from 'react';
import axios from "axios";

class Search extends Component {
    searchInput=createRef()
    searchData=()=>{
        //获取input的值
        const key=this.searchInput.current.value
        //发送Ajax请求

        axios.get(`/api/search/users?q=${key}`).then(res=>{
            console.log(res);
        },(err)=>{
            console.log(err);
        }).catch(err=>{
            console.log(err);
        })
        //
    }
    render() {
        return (
            <div>
                <section className="jumbotron">
                    <h3 className="jumbotron-heading">Search Github Users</h3>
                    <div>
                        <input type="text" ref={this.searchInput} placeholder="enter the name you search"/>&nbsp;
                        <button onClick={this.searchData}>Search</button>
                    </div>
                </section>
            </div>
        );
    }
}

export default Search;
  • 点击搜索后我们发现一个问题,接口返回的和axios里面的结构不一致,可以看出,axios对接口数据又做了封装
    在这里插入图片描述

把数据传递给state,并渲染列表

  • list.jsx
class List extends Component {
    render() {
        const data=this.props.data;
        return (
            <div>
                <div className="row">
                    {
                        data.map((item,index)=>{
                            return  <div className="card" key={item.html_url}>
                                <a rel="noreferrer" href={item.html_url} target="_blank">
                                    <img alt="head_protrait" src={item.avatar_url} style={{width:'100px'}}/>
                                </a>
                                <p className="card-text">{item.login}</p>
                            </div>
                        })
                    }
                </div>
            </div>
        );
    }
}
  • app.js
    getData=(data)=>{
        console.log(data);
        this.setState(
            {
                list:data
            }
        )
    }

在这里插入图片描述

发布订阅和同步机制

我们从上一个搜索的例子其实可以看到,在app search list组件直接传递数据的时候,我们都绕不开父组件app,那么有没有一种方式,让search 和list直接沟通,而不需要再通过父组件App传递? 这就用到了发布订阅。
其实后端同学都很熟悉发布订阅模式,首先我们需要创建一个topic,然后有发布者,还得有订阅者。
接下来我们使用第三方组件pubsubjs来体验一下发布订阅,

  • search.jsx
import React, {Component, createRef} from 'react';
import axios from "axios";
import PubSub from 'pubsub-js';


class Search extends Component {
    searchInput=createRef()
    searchData=()=>{
        //获取input的值
        const key=this.searchInput.current.value
        //发送Ajax请求
        axios.get(`/api/search/users?q=${key}`).then(res=>{
            //发布消息
            PubSub.publish('list',res.data.items);
        },(err)=>{
            console.log(err);
        }).catch(err=>{
            console.log(err);
        })
        //
    }
    render() {
        return (
            <div>
                <section className="jumbotron">
                    <h3 className="jumbotron-heading">Search Github Users</h3>
                    <div>
                        <input type="text" ref={this.searchInput} placeholder="enter the name you search"/>&nbsp;
                        <button onClick={this.searchData}>Search</button>
                    </div>
                </section>
            </div>
        );
    }
}

export default Search;
  • list.jsx
import React, {Component} from 'react';
import './List.css'
import PubSub from 'pubsub-js';

class List extends Component {

    state ={
        data:[]
    }
    getData = (msg, data) => {
        this.setState({
            data:data
        })
    }

    //挂载完毕开始订阅
    componentDidMount() {//用一个函数处理订阅消息
       const token= PubSub.subscribe('list', this.getData);
       this.setState({
           token:token
       })
    }

    //卸载后取消订阅
    componentWillUnmount() {
        PubSub.unsubscribe(this.state.token);
    }

    render() {
        const data=this.state.data;
        return (
            <div>
                <div className="row">
                    {
                        data.map((item,index)=>{
                            return  <div className="card" key={item.html_url}>
                                <a rel="noreferrer" href={item.html_url} target="_blank">
                                    <img alt="head_protrait" src={item.avatar_url} style={{width:'100px'}}/>
                                </a>
                                <p className="card-text">{item.login}</p>
                            </div>
                        })
                    }
                </div>
            </div>
        );
    }
}
export default List;

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

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

相关文章

Linux Seccomp 简介

文章目录 一、简介二、架构三、Original/Strict Mode四、Seccomp-bpf五、seccomp系统调用六、Linux Capabilities and Seccomp6.1 Linux Capabilities6.2 Linux Seccomp 参考资料 一、简介 Seccomp&#xff08;secure computing&#xff09;是Linux内核中的一项计算机安全功能…

从新手到专家:AutoCAD 完全指南

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 引言 AutoCAD是一款广泛用于工程设计和绘图的…

《汇编语言》- 读书笔记 - 第13章-实验13编写、应用中断例程

《汇编语言》- 读书笔记 - 第13章-实验13编写、应用中断例程 1. 编写并安装中断例程主程序运行效果 2. 编写并安装 int 7ch 中断例程&#xff0c;功能为完成 loop 指令的功能。3. 下面的程序&#xff0c;分别在屏幕的第 2、4、6、8行显示4句英文诗&#xff0c;补全程序。 1. 编…

5G网络介绍

目录 一、网络部署模式 二、4/5G基站网元对标 三、4/5G系统架构对比 四、5G核心单元 五、边缘计算 六、轻量化&#xff08;UPF下沉&#xff09; 方案一&#xff1a;UPF下沉 方案二&#xff1a;UPF下沉 方案三&#xff1a;5GC下沉基础模式 方案四&#xff1a;…

亚信安慧AntDB开启超融合数据库新纪元

&#xff08;一&#xff09; 前言 据统计&#xff0c;在信息化时代的今天&#xff0c;人们一天所接触到的信息量&#xff0c;是古人一辈子所能接收到的信息量的总和。当今社会中除了信息量“多”以外&#xff0c;人们对信息处理的“效率”和“速度”的要求也越来越高。譬如&…

特征融合篇 | YOLOv8 引入通用高效层聚合网络 GELAN | YOLOv9 新模块

今天的深度学习方法专注于如何设计最合适的目标函数,以使模型的预测结果最接近真实情况。同时,必须设计一个合适的架构,以便为预测提供足够的信息。现有方法忽视了一个事实,即当输入数据经过逐层特征提取和空间转换时,会丢失大量信息。本文将深入探讨数据通过深度网络传输…

如果软件测试工程师们在面试的时候都说真话.....

俗话说面试造火箭&#xff0c;入职拧螺丝&#xff0c;许多入职大厂的朋友们都容易有这样的感受。 面试时&#xff0c;过五关、斩六将 几轮面试提出的问题一个比一个专业。 让人真切的感受到这份工作的重要性和挑战性 大家如果想下载我录制的一些软件测试学习视频、大厂面试资料…

BOOT电路

本质&#xff1a;BOOT电路本质上是单片机的引脚 作用&#xff1a;BOOT电路的作用是用于确定单片机的启动模式 使用方法&#xff1a;在单片机上电或者复位时给BOOT管脚设置为指定电平即可将单片机设置为指定启动模式。 原理&#xff1a;单片机上电或复位后会先启动内部晶振&a…

13.题目:编号511 灌溉

题目&#xff1a; ###本题主要考察枚举、模拟 #include<bits/stdc.h> using namespace std; const int N105; bool a[N][N],b[N][N]; int main(){int n,m;cin>>n>>m;int t;cin>>t;while(t--){int c,r;cin>>c>>r;a[c][r]1;}int k;cin>…

线性表——单链表的增删查改

本节复习链表的增删查改 首先&#xff0c; 链表不是连续的&#xff0c; 而是通过指针联系起来的。 如图&#xff1a; 这四个节点不是连续的内存空间&#xff0c; 但是彼此之间使用了一个指针来连接。 这就是链表。 现在我们来实现链表的增删查改。 目录 单链表的全部接口…

vue项目导出excel ,文件过大导致请求超时的处理方法

一、因为文件过大&#xff0c;请求时间较长&#xff0c;就会产生请求超时的情况&#xff0c;处理方式是可以分为三个接口&#xff0c;接口1用来获取id值&#xff0c;接口2利用id值发起请求&#xff0c;询问是否准备好下载&#xff0c;如果没准备好&#xff0c;则没隔一秒再次发…

搜维尔科技:OptiTrack 提供了性能最佳的动作捕捉平台

OptiTrack 动画 我们的 Prime 系列相机和 Motive 软件相结合&#xff0c;产生了世界上最大的捕获量、最精确的 3D 数据和有史以来最高的相机数量。OptiTrack 提供了性能最佳的动作捕捉平台&#xff0c;具有易于使用的制作工作流程以及运行世界上最大舞台所需的深度。 无与伦比…

Linux Centos7配置SSH免密登录

Linux Centos7配置SSH免密登录 配置SSH免密登录说明&#xff1a; 分两步 第一步、给Server A生成密钥对 第二步、给Server B授权 生成密钥对之后&#xff0c;我们可以看看它保存的目录下的文件。 接下来我们就要把Server A&#xff08;10.1.1.74&#xff09;的公钥拷贝到Se…

【踩坑】修复xrdp无法关闭Authentication Required验证窗口

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 问题如下&#xff0c;时不时出现&#xff0c;有时还怎么都关不掉&#xff0c;很烦&#xff1a; 解决方法一&#xff1a;命令行输入 dbus-send --typemethod_call --destorg.gnome.Shell /org/gnome/Shell org.gn…

ElasticSearch之找到乔丹的空中大灌篮电影

写在前面 本文看一个搜索的实际例子&#xff0c;找到篮球之神乔丹的电影Space Jam&#xff0c;即空中大灌篮。 正式开始之前先来看下要查询的目标文档&#xff0c;以及查询的text&#xff1a; 要查询的目标文档 {..."title": "Space Jam",..."ove…

加密与安全_深入了解哈希算法

文章目录 Pre概述哈希碰撞常用的哈希算法Codejava.security.MessageDigestMD5SHA-1SHA-256MessageDigest支持算法 哈希算法的用途彩虹表攻击基本原理攻击过程 防御彩虹表攻击基本原理用途 小结 Pre PKI - 01 散列(Hash)函数 概述 哈希算法&#xff08;Hash&#xff09;又称摘…

TikTok云手机可以运营多少个账号

在社交媒体平台上&#xff0c;尤其是像TikTok这样的热门应用中&#xff0c;账号运营已经成为了许多人的日常工作。而利用云手机技术&#xff0c;一台手机能够同时运营多个TikTok账号&#xff0c;为用户带来了更大的便利和灵活性。本文将探讨 TikTok云手机能够运营多少个账号&am…

【生成式AI】ChatGPT原理解析(1/3)- 对ChatGPT的常见误解

Hung-yi Lee 课件整理 文章目录 误解1误解2ChatGPT真正在做的事情-文字接龙 ChatGPT是在2022年12月7日上线的。 当时试用的感觉十分震撼。 误解1 我们想让chatGPT讲个笑话&#xff0c;可能会以为它是在一个笑话的集合里面随机地找一个笑话出来。 我们做一个测试就知道不是这样…

Linux课程四课---Linux开发环境的使用(vim编辑器的相关)

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…