当前位置: 首页 > news >正文

React源码02 - 基础知识 React API 一览

1. JSX到JavaScript的转换

<div id="div" key="key"><span>1</span><span>2</span>
</div>
React.createElement("div", // 大写开头会当做原生dom标签的字符串,而组件使用大写开头时,这里会成为变量引用{ id: "div", key: "key" },React.createElement("span", null, "1"),React.createElement("span", null, "2")
);
createElement(type, config, children) {// 从用户传入的 config 中把4种内置的属性 key、ref、self、source 单独挑出来,config 中剩余的参数作为用户的 props。// 然后返回使用 ReactElement 创建的 element 对象。
return ReactElement( type,  key,  ref,  self,  source,  ReactCurrentOwner.current,  props, );
}

2. ReactElement

const ReactElement = function(type, key, ref, self, source, owner, props) {const element = {// This tag allows us to uniquely identify this as a React Element$$typeof: REACT_ELEMENT_TYPE,// Built-in properties that belong on the elementtype: type, // 可能是原生dom标签字符串如'span',也可能是一个class类(class组件),还可能是一个function(函数式组件),也可能是 forwardRef 返回的对象,或者 symbol 标记等 key: key,ref: ref,props: props,// Record the component responsible for creating this element._owner: owner,};if (__DEV__) {// 略}return element;
};
React.createElement("div",{ id: "div", key: "key" },React.createElement("span", null, "1"),React.createElement("span", null, "2")
);// 于是最初的 jsx 经过 React.createElement() 后成为了下面的对象树,
// 也是函数式组件返回的东西,也是 class 组件组件 render() 方法返回的东西
element = {$$typeof: REACT_ELEMENT_TYPE,type: type,key: key,ref: ref,props: {userProps1: userProps1,// ... 用户其他的自定义propschildren: [{$$typeof: REACT_ELEMENT_TYPE,type: type,key: key,ref: ref,props: props,_owner: owner,}, {$$typeof: REACT_ELEMENT_TYPE,type: type,key: key,ref: ref,props: props,_owner: owner,}]},_owner: owner,
};

3. 基类 React.Component

Component 类可能不是想象中那样用于渲染子组件什么的,只是做一些绑定工作:

function Component(props, context, updater) {this.props = props;this.context = context;// If a component has string refs, we will assign a different object later.this.refs = emptyObject;// We initialize the default updater but the real one gets injected by the// renderer.this.updater = updater || ReactNoopUpdateQueue;
}// PureComponent 继承了 Component
function PureComponent(props, context, updater) {this.props = props;this.context = context;// If a component has string refs, we will assign a different object later.this.refs = emptyObject;this.updater = updater || ReactNoopUpdateQueue;
}
// pureComponentPrototype.isPureReactComponent = true;// 常规的 setState,这里只是入队列
Component.prototype.setState = function(partialState, callback) {invariant(typeof partialState === 'object' ||typeof partialState === 'function' ||partialState == null,'setState(...): takes an object of state variables to update or a ' +'function which returns an object of state variables.',);this.updater.enqueueSetState(this, partialState, callback, 'setState');
};// 可主动强制更新,这里也只是入队列
// enqueueForceUpdate 内部实现了 ”重载”
Component.prototype.forceUpdate = function(callback) {this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};

4. createRef & ref

ref 用于获取 dom 节点或者 class component 的实例。
有三种用法,第一种 string 方法不推荐使用,后面在 React 17 中应该会被废弃:

import React from 'react'export default class RefDemo extends React.Component {constructor() {super()this.objRef = React.createRef()// { current: null }}componentDidMount() {setTimeout(() => {this.refs.stringRef.textContent = 'string ref got'this.methodRef.textContent = 'method ref got'this.objRef.current.textContent = 'obj ref got'}, 1000)}render() {return (<><p ref="stringRef">span1</p><p ref={ele => (this.methodRef = ele)}>span3</p><p ref={this.objRef}>span3</p></>)}
}// export default () => {
//   return <div>Ref</div>
// }

Object.seal() 密封,阻止目标对象上增删属性,并且关闭所有属性的 configurable,但仍可以修改现有的、是 writable 的属性。
Object.freeze() 冻结,比密封更严格,会将 writable 也关闭,意味着现有属性“不可以”修改。但如果属性本身是个引用类型,比如 const object = {a: 1, b: []},那么即使冻结 object 后,object.b.push(666) 也是可以的。
另外,冻结也会冻结目标对象上的 prototype 原型对象。

createRef 源码:

import type {RefObject} from 'shared/ReactTypes';// an immutable object with a single mutable value
export function createRef(): RefObject {const refObject = {current: null,};if (__DEV__) {Object.seal(refObject);}return refObject;
}

5. forwardRef

字面意思,转发 ref ?为什么 ref 需要转发,不能像上面那样直接使用?

dom 节点或者 class component,是可以由 react 在组件渲染之后把实例绑定(或提供)至我们指定的“容器”中,之后我们就可以从“容器”中引用刚才的实例,进行想要的操作。

React.createRef() 返回的就是 { current: null },这个对象就可以理解为一个“容器”,我们以在 jsx 上声明的方式,提供给 react,渲染之后返回我们想要的实例引用。

image

然而 function 函数式组件并没有实例,就是个函数。所以外部用户无差别地尝试为组件提供 ref “容器”希望回头能拿到实例时,如果遇到 function 组件,则会失败、报错。而这种报错可以通过转发 ref 来避免,因为 function 组件没有所谓的实例,但内部至少返回了 dom 或者另外的 class 组件吧,所以把 ref 转发给它们即可。
即外部用户最终拿到的实例引用,其实是函数式组件内层的实例。

自己的组件可能知道报错,不会去直接试图获取 function 组件的 ref,但如果是作为第三方组件库提供给其他 react 用户来调用,则要使用 forwardRef 来转发用户的诉求,并实现他们。

import React from 'react';class App extends React.Component {render() {return <div>div</div>;}
}const TargetComponent = React.forwardRef((props, ref) => (<input type="text" ref={ref}/>
));export default class Comp extends React.Component {constructor() {super();this.ref = React.createRef();this.ref2 = React.createRef();}componentDidMount() {// 虽然还是声明在 TargetComponent 函数组件上,但最终拿到了有效的实例引用,即内部的 dom 节点this.ref.current.value = 'ref get input';console.log('this.ref', this.ref);console.log('this.ref2', this.ref2);}render() {return <><TargetComponent ref={this.ref}/><App ref={this.ref2} /></>;}
}

React.forwardRef() 源码:

export default function forwardRef<Props, ElementType: React$ElementType>(render: (props: Props, ref: React$Ref<ElementType>) => React$Node,
) {if (__DEV__) {// 用户不按规定的使用会抛出异常信息}return {$$typeof: REACT_FORWARD_REF_TYPE,render,};
}

可以看到向 forwardRef 传入的 render 函数至少没在这里被调用,只是用对象包了一层,并增加了一个 $$typeof 属性,值是个 symbol。所以上面例子中声明实际等价于:

const TargetComponent = {$$typeof: REACT_FORWARD_REF_TYPE,render: (props, ref) => (<input type="text" ref={ref}/>)
};// 经过 React.createElement() 创建出的 element:
const element = {// This tag allows us to uniquely identify this as a React Element$$typeof: REACT_ELEMENT_TYPE,type: TargetComponent,key: null,ref: React.createRef(),props: {},// Record the component responsible for creating this element._owner: owner,
};

6. Context

使用 context 也有两种方式,childContextType 和 createContext。
childContextType 是老的方式,在将来的 React 17 中应该会被废弃,所以优先使用 createContext。

import React from 'react'const MyContext = React.createContext('default');
const { Provider, Consumer } = MyContext;class Parent extends React.Component {state = {newContext: '123',};render() {return (<><div><label>newContext:</label><inputtype="text"value={this.state.newContext}onChange={e => this.setState({ newContext: e.target.value })}/></div><Provider value={this.state.newContext}>{this.props.children}</Provider></>)}
}class Parent2 extends React.Component {render() {return this.props.children}
}function Child1(props, context) {console.log(MyContext);console.log(context);return <Consumer>{value => <p>newContext: {value}</p>}</Consumer>
}export default () => (<Parent><Parent2><Child1 /></Parent2></Parent>
);

React.createContext() 源码:
返回的 context 对象中有 $$typeof: REACT_CONTEXT_TYPE ,且有 Provider 和 Consumer,Provider 只是用对象包了一下原 context,添加了 $$typeof: REACT_PROVIDER_TYPE 属性;而 Consumer 压根就是引用原 context。有点俄罗斯套娃的感觉,能想到的就是 $$typeof 会作为 react 更新时判断不同类型的依据。而套娃的操作,可能就是为了方便操作 context,引来引去总能找到那个 context。


export function createContext<T>(defaultValue: T,calculateChangedBits: ?(a: T, b: T) => number,
): ReactContext<T> {if (calculateChangedBits === undefined) {calculateChangedBits = null;} else {if (__DEV__) {// 略);}}const context: ReactContext<T> = {$$typeof: REACT_CONTEXT_TYPE,_calculateChangedBits: calculateChangedBits,// As a workaround to support multiple concurrent renderers, we categorize// some renderers as primary and others as secondary. We only expect// there to be two concurrent renderers at most: React Native (primary) and// Fabric (secondary); React DOM (primary) and React ART (secondary).// Secondary renderers store their context values on separate fields._currentValue: defaultValue,_currentValue2: defaultValue,// These are circularProvider: (null: any),Consumer: (null: any),};context.Provider = {$$typeof: REACT_PROVIDER_TYPE,_context: context,};if (__DEV__) {// 异常处理} else {context.Consumer = context;}return context;
}

打印 React.createContext() 返回的 context 对象,验证套娃操作:


image

7. ConcurrentMode

在 React 16.6 提出,让 react 整体渲染过程可以根据优先级排列,可以任务调度、可以中断渲染过程等。来提高渲染性能,减少页面卡顿。

flushSync 使用优先级最高的方式进行更新,用来提高 this.setState 优先级。

使用 ConcurrentMode 包裹的组件都是低优先级的,所以为了演示高低优先级带来的区别感受,对比使用 flushSync。

例子中使用 flushSync 时,setState 优先级最高,基本是立即更新,这也导致动画卡顿明显,因为 200ms setState 间隔太快了,可能还没来得及渲染完,又要更新。因此使用 ConcurrentMode 把更新的优先级降低,从而不会频繁更新动画,显得流畅许多。

import React, { ConcurrentMode } from 'react'
import { flushSync } from 'react-dom'import './index.css'class Parent extends React.Component {state = {async: true,num: 1,length: 20000,}componentDidMount() {this.interval = setInterval(() => {this.updateNum()}, 200)}componentWillUnmount() {// 别忘了清除intervalif (this.interval) {clearInterval(this.interval)}}updateNum() {const newNum = this.state.num === 3 ? 0 : this.state.num + 1if (this.state.async) {this.setState({num: newNum,})} else {flushSync(() => {this.setState({num: newNum,})})}}render() {const children = []const { length, num, async } = this.statefor (let i = 0; i < length; i++) {children.push(<div className="item" key={i}>{num}</div>,)}return (<div className="main">async:{' '}<inputtype="checkbox"checked={async}onChange={() => flushSync(() => this.setState({ async: !async }))}/><div className="wrapper">{children}</div></div>)}
}export default () => (<ConcurrentMode><Parent /></ConcurrentMode>
)
@keyframes slide {0% {margin-left: 0;/* transform: translateX(0); */}50% {margin-left: 200px;/* transform: translateX(200px); */}100% {margin-left: 0;/* transform: translateX(0); */}
}.wrapper {width: 400px;animation-duration: 3s;animation-name: slide;animation-iteration-count: infinite;display: flex;flex-wrap: wrap;background: red;
}.item {width: 20px;height: 20px;line-height: 20px;text-align: center;border: 1px solid #aaa;
}

React.ConcurrentMode 源码:
没错,源码就是一个 Symbol 符号,显示 react 内部会判断该标记然后做些什么。

React.ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;

不难想象,经过 createElement() 创建出的 reactElement 树节点应该会是这样:

element = {// This tag allows us to uniquely identify this as a React Element$$typeof: REACT_ELEMENT_TYPE,// Built-in properties that belong on the elementtype: REACT_CONCURRENT_MODE_TYPE, // 看这里key: null,ref: null,props: props,// Record the component responsible for creating this element._owner: owner,
};

8. Suspense

Suspense 是一种在组件所依赖的数据尚未加载 ok 时,负责和 react 进行沟通,展示中间态的机制。
react 将会等待数据加载完成然后进行 UI 更新。

传统做法是在组件第一次挂载之后,即 componentDidMount() 或 useEffect() 中加载数据。即:

  1. Start fetching
  2. Finish fetching(然后调用 setState)
  3. Start rendering(再次渲染)

而 Suspense 也是先获取数据,(而且可以比传统做法更早一步,在第一次渲染之前),接着立马就开始第一次渲染(甚至在网络请求被实际发出前),遇到悬而未决即数据尚未获取,则挂起(suspends)该组件,跳过,然后继续渲染 element 树中其他的组件,如果又遇到还没搞定的 Suspense,则继续挂起并跳过。

  1. Start fetching
  2. Start rendering
  3. Finish fetching

Suspense 具体使用时,有一个“边界”概念,只有当一个 Suspense 内部的所有“挂起”都落地后,Suspense 才会停止展示 fallback 中间态,然后一并展示内部的 UI,因此可以通过合理增添 Suspense 边界来控制这种粒度。

// 用于懒加载的组件:
import React from 'react'
export default () => <p>Lazy Comp</p>
import React, { Suspense, lazy } from 'react'const LazyComp = lazy(() => import('./lazy.js'))let data = ''
let promise = ''
function requestData() {if (data) return dataif (promise) throw promisepromise = new Promise(resolve => {setTimeout(() => {data = 'Data resolved'resolve()}, 2000)})throw promise
}function SuspenseComp() {const data = requestData() // 数据尚未加载完成时,该组件的渲染会被挂起。return <p>{data}</p>
}export default () => (<Suspense fallback="loading data"><SuspenseComp /><LazyComp /></Suspense>
)

Suspense 源码:

  Suspense: REACT_SUSPENSE_TYPE // 又是一个 symbol 常量

lazy 源码:
_ctor 就是调用 lazy() 时传入的函数,该函数应返回一个 Thenable(具有then方法的对象)。react 渲染到该组件时,会调用 _ctor 函数。
_status 用于记录当前 Thenable 的状态, -1 代表尚未解决,对应到 promise 中也就是 pending 状态。
_result 用于存放 resolve 后的结果。

import type {LazyComponent, Thenable} from 'shared/ReactLazyComponent';import {REACT_LAZY_TYPE} from 'shared/ReactSymbols';export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {return {$$typeof: REACT_LAZY_TYPE,_ctor: ctor,// React uses these fields to store the result._status: -1,_result: null, };
}

另外,关于 Suspense 能解决异步竞态问题的理解:

异步请求带来的竞态问题,本质是因为异步请求和 React 分别处于各自的生命周期,二者并未相互同步、一一对应。往往需要等待一段时间,在数据返回之后才去调用 setState,如果快速操作 UI,多次发送相同请求时,由于异步请求时间的不确定性,可能第一条请求反而比第二条同样的请求,响应的更慢,这将导致页面展示了“旧”的数据,带来了混乱。

而使用 Suspense 时,是在UI触发之后,立即调用 setState 尝试去更新数据,如果数据还没返回,则 Suspense 会挂起(suspend)并展现 fallback 中间态。但这个等待正确数据的时间管理工作,已经交给 Suspense 内部去处理了,setState 的使命已经立即完成。暂时理解为脏活累活交给 Suspense 自行消化。

Suspense 结合 useTransition 使用更佳:

This scenario (Receded → Skeleton → Complete) is the default one. However, the Receded state is not very pleasant because it “hides” existing information. This is why React lets us opt into a different sequence (Pending → Skeleton → Complete) with useTransition.
When we useTransition, React will let us “stay” on the previous screen — and show a progress indicator there. We call that a Pending state. It feels much better than the Receded state because none of our existing content disappears, and the page stays interactive.

9. Hooks

hooks 用于 function 函数式组件,内部没有 class component 中那样用来维持内部状态的 this 对象,也没有典型的生命周期方法。

一个非常简单的例子,hooks 是一个大块的内容,这里不表。

/*** 必须要react和react-dom 16.7以上*/import React, { useState, useEffect } from 'react';export default () => {const [name, setName] = useState('jokcy');useEffect(() => {console.log('component update');return () => {console.log('unbind');};}, []);return (<><p>My Name is: {name}</p><input type="text" value={name} onChange={e => setName(e.target.value)}/></>);
}

useState 源码:
useEffect 等 use* 类似,都是在调用 dispatcher 上的方法。后期会再深入研究 hooks 内层的源码:

export function useState<S>(initialState: (() => S) | S) {const dispatcher = resolveDispatcher();return dispatcher.useState(initialState);
}
// 局部
function resolveDispatcher() {const dispatcher = ReactCurrentOwner.currentDispatcher;invariant(dispatcher !== null,'Hooks can only be called inside the body of a function component.',);return dispatcher;
}
/*** Keeps track of the current owner.** The current owner is the component who should own any components that are* currently being constructed.*/
const ReactCurrentOwner = {/*** @internal* @type {ReactComponent}*/current: (null: null | Fiber), // 代表当前正在被构建的组件实例currentDispatcher: (null: null | Dispatcher),
};export default ReactCurrentOwner;

10. Children

Children 上的方法有:

Children: {map,forEach,count,toArray,only,
},

React.Children.map() 中 map 可以遍历 child 并映射展开:

import React from 'react'function ChildrenDemo(props) {console.log(props.children)console.log(React.Children.map(props.children, c => [c, [c, c]]))return props.children
}export default () => (<ChildrenDemo><span>1</span><span>2</span></ChildrenDemo>
)

map 遍历 children 时有个 contextPool 对象常量池的概念,用于复用对象。以节省递归遍历 child 时多次对象创建和 GC 回收的开销。

React 这么实现主要是两个目的:

  1. 拆分 map 出来的数组
  2. 因为对 Children 的处理一般在 render 里面,所以会比较频繁,所以设置一个对象池子减少声明和 GC 的开销。


    image

11. Other

  • memo ,用于 function component,功能上对标 class component 中的 pureComponent

浅层源码中,也没多少东西,只是返回了一个带有 $$typeof 标记的对象及 typecompare ,memo 这种返回类似前面 createRef 的返回:

export default function memo<Props>(type: React$ElementType,compare?: (oldProps: Props, newProps: Props) => boolean,
) {if (__DEV__) {if (!isValidElementType(type)) {warningWithoutStack(false,'memo: The first argument must be a component. Instead ' +'received: %s',type === null ? 'null' : typeof type,);}}return {$$typeof: REACT_MEMO_TYPE,type,compare: compare === undefined ? null : compare,};
}
  • FragElement(简写方式是空标签 <></>

最外层源码就是 FragElement: REACT_FRAGMENT_TYPE
是临时节点,因为 React 要求不能直接返回多个兄弟节点,要么“包”一层,要么返回数组。而 FragElement 就是用来“包”一层的,相比于用真实的 div 去“包”一层,FragElement 并不会实际被创建。

  • cloneElement

克隆一个节点,源码基本和 createElement 一样,只是第一个参数从 type 变为了 element ,实际即要克隆的 element 对象上属性,然后把参数丢给 ReactElement() 来返回一个新的 element 对象:

/*** Clone and return a new ReactElement using element as the starting point.* See https://reactjs.org/docs/react-api.html#cloneelement*/
export function cloneElement(element, config, children) {invariant(!(element === null || element === undefined),'React.cloneElement(...): The argument must be a React element, but you passed %s.',element,);let propName;// Original props are copiedconst props = Object.assign({}, element.props);// Reserved names are extractedlet key = element.key;let ref = element.ref;// Self is preserved since the owner is preserved.const self = element._self;// Source is preserved since cloneElement is unlikely to be targeted by a// transpiler, and the original source is probably a better indicator of the// true owner.const source = element._source;// Owner will be preserved, unless ref is overriddenlet owner = element._owner;if (config != null) {if (hasValidRef(config)) {// Silently steal the ref from the parent.ref = config.ref;owner = ReactCurrentOwner.current;}if (hasValidKey(config)) {key = '' + config.key;}// Remaining properties override existing propslet defaultProps;if (element.type && element.type.defaultProps) {defaultProps = element.type.defaultProps;}for (propName in config) {if (hasOwnProperty.call(config, propName) &&!RESERVED_PROPS.hasOwnProperty(propName)) {if (config[propName] === undefined && defaultProps !== undefined) {// Resolve default propsprops[propName] = defaultProps[propName];} else {props[propName] = config[propName];}}}}// Children can be more than one argument, and those are transferred onto// the newly allocated props object.const childrenLength = arguments.length - 2;if (childrenLength === 1) {props.children = children;} else if (childrenLength > 1) {const childArray = Array(childrenLength);for (let i = 0; i < childrenLength; i++) {childArray[i] = arguments[i + 2];}props.children = childArray;}return ReactElement(element.type, key, ref, self, source, owner, props);
}
  • createFactory

如果时候 jsx 语法,而不是手动用 JS 调用 createElement 来创建 element 树的话,基本不会用到该方法,createFactory 就只是包了一层,省的每次创建同样类型的 element,都传入第一个 type 参数了:

/*** Return a function that produces ReactElements of a given type.* See https://reactjs.org/docs/react-api.html#createfactory*/
export function createFactory(type) {const factory = createElement.bind(null, type);// Expose the type on the factory and the prototype so that it can be// easily accessed on elements. E.g. `<Foo />.type === Foo`.// This should not be named `constructor` since this may not be the function// that created the element, and it may not even be a constructor.// Legacy hook: remove itfactory.type = type;return factory;
}
  • isValidElement

判断一个对象是否是合法的 element:

/*** Verifies the object is a ReactElement.* See https://reactjs.org/docs/react-api.html#isvalidelement* @param {?object} object* @return {boolean} True if `object` is a ReactElement.* @final*/
export function isValidElement(object) {return (typeof object === 'object' &&object !== null &&object.$$typeof === REACT_ELEMENT_TYPE);
}


喜欢的朋友记得点赞、收藏、关注哦!!!

相关文章:

React源码02 - 基础知识 React API 一览

1. JSX到JavaScript的转换 <div id"div" key"key"><span>1</span><span>2</span> </div>React.createElement("div", // 大写开头会当做原生dom标签的字符串&#xff0c;而组件使用大写开头时&#xff0c;这…...

COMSOL with Matlab

文章目录 基本介绍COMSOL with MatlabCOMSOL主Matlab辅Matlab为主Comsol为辅 操作步骤常用指令mphopenmphgeommghmeshmphmeshstatsmphnavigatormphplot常用指令mphsavemphlaunchModelUtil.clear 实例教学自动另存新档**把语法套用到边界条件**把语法套用到另存新档 函数及其微分…...

【报表查询】.NET开源ORM框架 SqlSugar 系列

文章目录 前言实践一、按月统计没有为0实践二、 统计某月每天的数量实践三、对象和表随意JOIN实践四、 List<int>和表随意JOIN实践五、大数据处理实践六、每10分钟统计Count实践七、 每个ID都要对应时间总结 前言 在我们实际开发场景中&#xff0c;报表是最常见的功能&a…...

PostgreSQL数据库访问限制详解

pg_hba.conf 文件是 PostgreSQL 数据库系统中非常重要的一个配置文件&#xff0c;它用于定义哪些用户&#xff08;或客户端&#xff09;可以连接到 PostgreSQL 数据库服务器&#xff0c;以及他们可以使用哪些认证方法进行连接。 pg_hba.conf 的名称来源于 "Host-Based Aut…...

【test linux】创建一个ext4类型的文件系统

创建一个ext4类型的文件系统 dd 是一个非常强大的命令行工具&#xff0c;用于在Unix/Linux系统中进行低级别的数据复制和转换。这条命令的具体参数含义如下&#xff1a; if/dev/zero&#xff1a;指定输入文件&#xff08;input file&#xff09;为 /dev/zero&#xff0c;这是一…...

如何在繁忙的生活中找到自己的节奏?

目录 一、理解生活节奏的重要性 二、分析当前生活节奏 1. 时间分配 2. 心理状态 3. 身体状况 4. 生活习惯 1. 快慢适中 2. 张弛结合 3. 与目标相符 三、掌握调整生活节奏的策略 1. 设定优先级 2. 合理规划时间 3. 学会拒绝与取舍 4. 保持健康的生活方式 5. 留出…...

AI-PR曲线

PR曲线 人工智能里面的一个小概念。 2.3 性能度量&#xff08;查全率&#xff0c;查准率&#xff0c;F1&#xff0c;PR曲线与ROC曲线&#xff09; 预测出来的是一个概率&#xff0c;不能根据概率来说它是正类还是负类&#xff0c;要有一个阈值。 查准率&#xff08;Precision&…...

Guava 提供了集合操作 `List`、`Set` 和 `Map` 三个工具类

入门示例 guava 最佳实践 学习指南 以下是使用Google Guava库中的工具方法来创建和操作List、Set、Map集合的一些示例&#xff1a; List相关操作 创建List 使用Lists.newArrayList()创建一个新的可变ArrayList实例。List<Integer> list Lists.newArrayList(1, 2, 3);/…...

深入解析 Elasticsearch 集群配置文件参数

在自建 Elasticsearch 集群时&#xff0c;我们需要通过 elasticsearch.yml 文件对节点角色、网络设置、集群发现和数据存储路径等进行灵活配置。配置项的合理设置对集群的稳定性、性能与扩展性影响深远。本文将以一个示例配置文件为蓝本&#xff0c;逐条解析各参数的含义与建议…...

WebMvcConfigurer和WebMvcConfigurationSupport(MVC配置)

一:基本介绍 WebMvcConfigurer是接口&#xff0c;用于配置全局的SpringMVC的相关属性&#xff0c;采用JAVABean的方式来代替传统的XML配置文件&#xff0c;提供了跨域设置、静态资源处理器、类型转化器、自定义拦截器、页面跳转等能力。 WebMvcConfigurationSupport是webmvc的…...

用 javascript 来回答宇宙外面是什么

宇宙外面是什么呢? 估计这个问题要困扰很多人, 让我们用一段 javascript 代码来回答一下. 一, 从一段代码说起 var 地球 {名字 : "地球",女友 : "月亮",外面 : {名字 : "太阳系",老大 : "太阳",老二 : {名字 : "木星",二…...

我的性能优化经验

专业方向&#xff1a;App cpu/memory/gpu/流畅度/响应时间的优化&#xff0c;Anr&#xff0c;Framework CarPowerManagementService模块的&#xff08;STR&#xff09;&#xff0c;从0~1完成性能监控体系搭建&#xff0c;完成3大版本迭代高质量性能交付 响应时间&#xff1a; …...

XSLT 编辑 XML

XSLT 编辑 XML 介绍 XSLT&#xff08;可扩展样式表语言转换&#xff09;是一种用于转换XML文档的语言。它允许开发人员将XML数据转换为其他格式&#xff0c;如HTML、PDF或纯文本。XSLT通过使用XPath查询来定位XML文档中的元素&#xff0c;并对这些元素应用转换规则。在本教程…...

数智读书笔记系列010 生命3.0:人工智能时代 人类的进化与重生

书名&#xff1a;生命3.0 生命3.0&#xff1a;人工智能时代,人类的进化与重生 著者&#xff1a;&#xff3b;美&#xff3d;迈克斯•泰格马克 迈克斯・泰格马克 教育背景与职业 教育背景&#xff1a;迈克斯・泰格马克毕业于麻省理工学院&#xff0c;获物理学博士学位。职业经…...

Transfomer的各层矩阵

一、输入 输入一句话&#xff1a;Hello CYZLAB the inspired world 每个单词为一个token 二、Embedding 这里的词向量维度为6&#xff0c;矩阵的行数为token数&#xff0c;列数是词向量的维度 这列是注释不算hello122694CYZLAB222372the222596inspired132440world431273 …...

代码随想录第51天

99.岛屿数量 深搜 import java.util.*;class Main{static int[][] directions {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};static boolean[][] visited;public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int m sc.nextInt();int…...

基础库httpx的使用

urllib 库和 requests 库的使用&#xff0c;已经可以爬取绝大多数网站的数据&#xff0c;但对于某些网站依然无能为力。什么情况?这些网站强制使用HTTP/2.0协议访问&#xff0c;这时 urllib 和requests 是无法爬取数据的&#xff0c;因为它们只支持 HTTP/1.1&#xff0c;不支持…...

c++中如何保持结构体的线程安全?3D坐标的线程安全:从理论到最优解

使用mutex的困扰 struct Point3d {std::mutex mtx;double x, y, z;void set(double nx, double ny, double nz) {std::lock_guard<std::mutex> lock(mtx);x nx; y ny; z nz;} };这种方案虽然安全&#xff0c;但性能开销确实不小。每次访问都需要加锁解锁&#xff0c;…...

Zabbix6.0升级为6.4

为了体验一些新的功能&#xff0c;比如 Webhook 和问题抑制等&#xff0c;升级个小版本。 一、环境信息 1. 版本要求 一定要事先查看官方文档&#xff0c;确认组件要求的版本&#xff0c;否则版本过高或者过低都会出现问题。 2. 升级前后信息 环境升级前升级后操作系统CentOS…...

答题考试系统v1.6.1高级版源码分享+uniapp+搭建测试环境

一.系统介绍 一款基于FastAdminThinkPHPUniapp开发的小程序答题考试系统&#xff0c;支持多种试题类型、多种试题难度、练题、考试、补考模式&#xff0c;提供全部前后台无加密源代码&#xff0c;支持私有化部署 二.测试环境 系统环境&#xff1a;CentOS、 运行环境&#x…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...