React16源码: JSX2JS及React.createElement源码实现
JSX 到 Javascript 的转换
- React中的 JSX 类似于 Vue中的template模板文件,Vue是基于编译时将template模板转换成render函数
- 在React中,JSX是类似于html和javascript混编的语法,而javascript是真的javascript, html并非真的html
- 它的可阅读性可维护性都是要高很多的
1 )JSX2JS 原理
- JSX 通过 babel 进行转换之后,生成了纯JS
- JSX相对于JS来讲,它唯一的一个区别,就是它可以写类似于HTML的一个标签
- 比如说我们通过写div 然后在 div 这种方式去声明HML的标签
- 然后它会给我们返回在React当中需要使用的对象
- 这就是JSX到JS的一个转化过程
2 ) 工具演示
- 这个工具是 babel playground
- babeljs.io/repl
- 要做一些代码转化的一个测试,可以直接到这个playground上面来
- 它会实时在为我们展现出我们写的代码转化出来的是什么样的样子
- 下面的示例是使用较低版本的 babel 来配合 React 16.6 版本
示例1
jsx
<div></div>
js
React.createElement("div", null);
示例2
jsx
<div class="test"></div>
js
React.createElement("div", {class: "test"
});
示例3
jsx
<div id="div" key="key" class="test"><span>1</span><span>1</span>
</div>
js
React.createElement("div", {id: "div",key: "key",class: "test"
}, React.createElement("span", null, "1"), React.createElement("span", null, "1"));
示例4
jsx
function Comp() {return <a>123</a>
}<Comp id="div" key="key"><span>1</span><span>1</span><div id="box"><span class='inner'>2</span></div>
</Comp>
js
function Comp() {return React.createElement("a", null, "123");
}React.createElement(Comp, {id: "div",key: "key"
}, React.createElement("span", null, "1"),React.createElement("span", null, "1"),React.createElement("div", {id: "box"}, React.createElement("span", {class: "inner"}, "2"))
);
3 )说明
- 从上面我们可以看出来我们的一个类似html的标签,或者是组件的一个标签
- 通过这种尖括号的方式来写的,它最终都会转换成
React.createElement
- 我们写的这些标签或者一些props,或者它的 children 都会作为一个参数
- props 是一个 key-value 形式的一个对象
- 它可以支持多层,无限层的嵌套,也就是一个树形结构
- 如果是一个函数式的组件作为参数
- 这里要分两种情况
- 1 ) 组件是大写的,这样会直接转换成变量(对象)
- 2 ) 组件是小写的,这样会直接变成字符串类型的标记(组件将失效)
- 注意
- 如果变成字符串,那么在React中,它是会认为这是一个原生的dom节点的
- 如果不存在这么一个dom节点,那么后续在运行的时候,可能就报错了
- 所以自定义的组件必须使用大写的开头,这是一个规范
- 这里要分两种情况
- 综上,我们现在问题的重点就在
createElement
之上了
React.createElement 源码解析
- 在上一步的 JSX2JS中,我们的标签,标签里的属性,标签的内容,都会变成各种类型的参数
- 传到我们调用的
createElement
这个方法里面,这个方法内部如何实现的 - 在 createElement 函数的内部,返回了一个
React Element
, 我们来看看它具体的作用 - 看源码肯定要从它的入口文件开始看,因为入口文件会给我们很多的信息告诉我们
- 常用的使用这个包的时候的这些API它都来自于哪里,以及它是如何
export
出来的
1 )React 入口文件 packages/react/src/React.js
/*** Copyright (c) Facebook, Inc. and its affiliates.** This source code is licensed under the MIT license found in the* LICENSE file in the root directory of this source tree.*/import ReactVersion from 'shared/ReactVersion';
import {REACT_CONCURRENT_MODE_TYPE,REACT_FRAGMENT_TYPE,REACT_PROFILER_TYPE,REACT_STRICT_MODE_TYPE,REACT_SUSPENSE_TYPE,
} from 'shared/ReactSymbols';import {Component, PureComponent} from './ReactBaseClasses';
import {createRef} from './ReactCreateRef';
import {forEach, map, count, toArray, only} from './ReactChildren';
import {createElement,createFactory,cloneElement,isValidElement,
} from './ReactElement';
import {createContext} from './ReactContext';
import {lazy} from './ReactLazy';
import forwardRef from './forwardRef';
import memo from './memo';
import {createElementWithValidation,createFactoryWithValidation,cloneElementWithValidation,
} from './ReactElementValidator';
import ReactSharedInternals from './ReactSharedInternals';
import {enableStableConcurrentModeAPIs} from 'shared/ReactFeatureFlags';const React = {Children: {map,forEach,count,toArray,only,},createRef,Component,PureComponent,createContext,forwardRef,lazy,memo,Fragment: REACT_FRAGMENT_TYPE,StrictMode: REACT_STRICT_MODE_TYPE,Suspense: REACT_SUSPENSE_TYPE,createElement: __DEV__ ? createElementWithValidation : createElement,cloneElement: __DEV__ ? cloneElementWithValidation : cloneElement,createFactory: __DEV__ ? createFactoryWithValidation : createFactory,isValidElement: isValidElement,version: ReactVersion,__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals,
};if (enableStableConcurrentModeAPIs) {React.ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;React.Profiler = REACT_PROFILER_TYPE;
} else {React.unstable_ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;React.unstable_Profiler = REACT_PROFILER_TYPE;
}export default React;
- 上面全是 import 其他一些东西,import 进来之后, 它声明了 React 对象
- 这个对象就是我们在外部去用 React 的时候,给我们提供的API
- 然后最终它
export default React
把这个对象给它 export 出来 - 这样的话我们就可以在外部使用
- 我们回到
createElement
上面来,从上面可知,跟Element相关的一些代码 - 都放在了 ./ReactElement 这个文件下面
2 )定位到 ReactElement.js 文件中
/*** Copyright (c) Facebook, Inc. and its affiliates.** This source code is licensed under the MIT license found in the* LICENSE file in the root directory of this source tree.*/import invariant from 'shared/invariant';
import warningWithoutStack from 'shared/warningWithoutStack';
import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';import ReactCurrentOwner from './ReactCurrentOwner';const hasOwnProperty = Object.prototype.hasOwnProperty;const RESERVED_PROPS = {key: true,ref: true,__self: true,__source: true,
};let specialPropKeyWarningShown, specialPropRefWarningShown;function hasValidRef(config) {if (__DEV__) {if (hasOwnProperty.call(config, 'ref')) {const getter = Object.getOwnPropertyDescriptor(config, 'ref').get;if (getter && getter.isReactWarning) {return false;}}}return config.ref !== undefined;
}function hasValidKey(config) {if (__DEV__) {if (hasOwnProperty.call(config, 'key')) {const getter = Object.getOwnPropertyDescriptor(config, 'key').get;if (getter && getter.isReactWarning) {return false;}}}return config.key !== undefined;
}function defineKeyPropWarningGetter(props, displayName) {const warnAboutAccessingKey = function() {if (!specialPropKeyWarningShown) {specialPropKeyWarningShown = true;warningWithoutStack(false,'%s: `key` is not a prop. Trying to access it will result ' +'in `undefined` being returned. If you need to access the same ' +'value within the child component, you should pass it as a different ' +'prop. (https://fb.me/react-special-props)',displayName,);}};warnAboutAccessingKey.isReactWarning = true;Object.defineProperty(props, 'key', {get: warnAboutAccessingKey,configurable: true,});
}function defineRefPropWarningGetter(props, displayName) {const warnAboutAccessingRef = function() {if (!specialPropRefWarningShown) {specialPropRefWarningShown = true;warningWithoutStack(false,'%s: `ref` is not a prop. Trying to access it will result ' +'in `undefined` being returned. If you need to access the same ' +'value within the child component, you should pass it as a different ' +'prop. (https://fb.me/react-special-props)',displayName,);}};warnAboutAccessingRef.isReactWarning = true;Object.defineProperty(props, 'ref', {get: warnAboutAccessingRef,configurable: true,});
}/*** Factory method to create a new React element. This no longer adheres to* the class pattern, so do not use new to call it. Also, no instanceof check* will work. Instead test $$typeof field against Symbol.for('react.element') to check* if something is a React Element.** @param {*} type* @param {*} key* @param {string|object} ref* @param {*} self A *temporary* helper to detect places where `this` is* different from the `owner` when React.createElement is called, so that we* can warn. We want to get rid of owner and replace string `ref`s with arrow* functions, and as long as `this` and owner are the same, there will be no* change in behavior.* @param {*} source An annotation object (added by a transpiler or otherwise)* indicating filename, line number, and/or other information.* @param {*} owner* @param {*} props* @internal*/
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,key: key,ref: ref,props: props,// Record the component responsible for creating this element._owner: owner,};if (__DEV__) {// The validation flag is currently mutative. We put it on// an external backing store so that we can freeze the whole object.// This can be replaced with a WeakMap once they are implemented in// commonly used development environments.element._store = {};// To make comparing ReactElements easier for testing purposes, we make// the validation flag non-enumerable (where possible, which should// include every environment we run tests in), so the test framework// ignores it.Object.defineProperty(element._store, 'validated', {configurable: false,enumerable: false,writable: true,value: false,});// self and source are DEV only properties.Object.defineProperty(element, '_self', {configurable: false,enumerable: false,writable: false,value: self,});// Two elements created in two different places should be considered// equal for testing purposes and therefore we hide it from enumeration.Object.defineProperty(element, '_source', {configurable: false,enumerable: false,writable: false,value: source,});if (Object.freeze) {Object.freeze(element.props);Object.freeze(element);}}return element;
};/*** Create and return a new ReactElement of the given type.* See https://reactjs.org/docs/react-api.html#createelement*/
export function createElement(type, config, children) {let propName;// Reserved names are extractedconst props = {};let key = null;let ref = null;let self = null;let source = null;if (config != null) {if (hasValidRef(config)) {ref = config.ref;}if (hasValidKey(config)) {key = '' + config.key;}self = config.__self === undefined ? null : config.__self;source = config.__source === undefined ? null : config.__source;// Remaining properties are added to a new props objectfor (propName in config) {if (hasOwnProperty.call(config, propName) &&!RESERVED_PROPS.hasOwnProperty(propName)) {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];}if (__DEV__) {if (Object.freeze) {Object.freeze(childArray);}}props.children = childArray;}// Resolve default propsif (type && type.defaultProps) {const defaultProps = type.defaultProps;for (propName in defaultProps) {if (props[propName] === undefined) {props[propName] = defaultProps[propName];}}}if (__DEV__) {if (key || ref) {const displayName =typeof type === 'function'? type.displayName || type.name || 'Unknown': type;if (key) {defineKeyPropWarningGetter(props, displayName);}if (ref) {defineRefPropWarningGetter(props, displayName);}}}return ReactElement(type,key,ref,self,source,ReactCurrentOwner.current,props,);
}/*** 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;
}export function cloneAndReplaceKey(oldElement, newKey) {const newElement = ReactElement(oldElement.type,newKey,oldElement.ref,oldElement._self,oldElement._source,oldElement._owner,oldElement.props,);return newElement;
}/*** 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);
}/*** 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);
}
- 在这个文件里面先找到
createElement
这个方法,我们可以看到它接收的三个参数type
- 就是我们的节点类型,如果是原生的节点,那么它是一个字符串
- 那如果是我们自己声明的组件,它就是一个class component 或者是一个 functional component
- 还会有其他的一些情况。比如 使用 React 原生的一些组件
- 比如说 Fragment、 StrictMode、 Suspense
- 这些都是 React 提供我们的一些原生组件,
- 其实,上面三个它们默认就只是一个
Symbol
- 它没有任何其他的功能,就仅仅是一个标志
config
- 是我们写在这个JSX标签上面的所有的 attributes
- 它们都会变成key value的形式存到这个config对象里面
- 我们要从这个对象里面筛选出真正的props的内容
- 还有特殊的,比如说 key,ref 这些属性
children
- 就是我们标签中间我们放的一些内容
- 它可能是一个子标签,或者它直接是文字 text
- 我们来看一下它如何去创建一个
ReactElement
, 还是回到createElement
这个方法- 内部声明了一堆变量,找到有没有合理的REF,有没有合理的key
- 我们把这些都给它读到一个单独的变量里面
- 忽略 self 和 source 这两个东西,不是特别的重要
- 接下去,要对剩下的config下面的 props 进行一个处理
- 判断一下它是否是内建的 props,如果不是的话,就放到一个新建的 props 对象里面
- 如果是内建的 props,就不放进去了,因为它不属于正常的 props 的范畴
- 看一下这个内建的 props,它是什么东西
const RESERVED_PROPS = {key: true,ref: true,__self: true,__source: true, };
key
,ref
,__self
,__source
, 这些都不会出现在我们使用class component 的场景下- 比如说我们的 this.props里面
- 因为在处理props的过程当中,就已经把它处理掉了
- 这边把 props 的属性全部拿出来,放到一个新的对象里面之后
- 接下去要处理children
- children 是可以有多个的,在一个节点下面
- 它的 children 可能有很多的兄弟节点存在
- 它是作为后续的参数传进来的,虽然在声明
createElement
的时候只有三个参数 - 但是它是可以传 3,4,5,6,7,8,9, … 多个参数的
- 后续第三个参数之后的参数,我们都认为它们是 children
- 在react当中把后续
arguments.length - 2
代表剩下的这个长度都是children - 然后会一个一个把它读出来,然后变成一个数组
- 声明一个数组, 存放后续所有的 children 节点对象, 最终再把它放到 props.children
- 通过
this.props.children
拿到的就是这部分的内容
- 接下来,就是
defaultProps
的处理- 在声明 class Comp 的时候,比如说我们
extends React.Component
- 我们可以通过
Comp.defaultProps
一个对象,给接收的这些props去设置一些默认值 - 比如说, 这边它的默认值是
{value:1}
,当组件在被使用的时候,没有传value这个props - 在这里面就会使用 1 作为我们在组件内部
this.props.value
去拿到的这个值 - 它就是把我们刚才上面处理过的那个props对象上面去读取对应的defaultProps里面的每一个key的值
- 如果值是
undefined
,就把它设置为 defaultProps 里面的属性 - 如果它是有值的, 我们就不设置了
- 注意
- 它的判断条件是
undefined
- 也就是说 null 也是一个不需要使用默认值的情况
- 它的判断条件是
- 在声明 class Comp 的时候,比如说我们
- 接着,下面 DEV 判断的代码,进行忽略
- 最终 return了一个
ReactElement
- 传入刚才处理过的这些内容
- 关于
ReactElement
- 它不是一个 class Comp, 而是一个 function
- 最终会return一个Object, 这个Object也就几个主要的属性
$$typeof
是REACT_ELEMENT_TYPE
- 是用来标识我们的 element 是什么类型的
- 在写JSX代码的时候,所有的节点都是通过 createElement 进行创建的
- 那么,它的
$$typeof
永远都是REACT_ELEMENT_TYPE
- 在后续React的更新渲染dom的过程中是经常被用到的
- 大部分情况下,我们拿到的
$$typeof
都是REACT_ELEMENT_TYPE
- 有一些特殊情况是和平台相关
- 在react-dom里面,它有一个API叫做
React.createPortal
, 它返回的对象和这里的类似 - 但是它的
$$typeof
是REACT_PORTAL_TYPE
- 在react-dom里面,它有一个API叫做
type
是之前传进来的那个 type- 是在
createElement
的时候接收的那个 type - 用于记录节点的类型,是原生组件,还是 class Comp
- 是在
key
就是上面处理过的 keyref
就是 refprops
就是 props
- 综上,就是一个 ReactElement, 具体的方法,如何去操作,以及最终返回的类型
相关文章:
React16源码: JSX2JS及React.createElement源码实现
JSX 到 Javascript 的转换 React中的 JSX 类似于 Vue中的template模板文件,Vue是基于编译时将template模板转换成render函数在React中,JSX是类似于html和javascript混编的语法,而javascript是真的javascript, html并非真的html它的可阅读性可…...
整理composer安装版本的python脚本
整理composer安装版本的python脚本 脚本实现的功能是去除composer安装命令后的版本号 def remove_version_numbers(commands):"""Remove version numbers from composer require commands.Args:commands (list of str): List of composer require commands.Retu…...

十、基本对话框大集合(Qt5 GUI系列)
目录 一、设计需求 二、实现代码 三、代码解析 四、总结 一、设计需求 Qt提供了很多标准的对话框。例如标准文件对话框(QFileDialog)、标准颜色对话框(QColorDialog)、标准字体对话框 (QFontDialog)、标准输入对话框 (QInputDialog) 及消息对话框 (QMessageBox)。本文展示各…...
大A又跌了
才开盘几天,又开始下跌了。生活更加苦难。期待高深算法。...

This error originates from a subprocess, and is likely not a problem with pip
我遇这个问题是的原因是包名错误 注意检查包名...

数据库基础知识1
关系模型的程序员不需熟悉数据库的存取路径 在3层模式结构中,___I___是数据库的核心和关键,___Ⅱ___通常是模式的子集,数据库模式的描述提供给用户,____Ⅲ__的描述存储在硬盘上。Ⅰ.模式Ⅱ. 外模式Ⅲ. 内模式 数据库中,数据的物理独立性是指用户的应用程序与存储在磁盘上数据库…...

【GO语言卵细胞级别教程】01.GO基础知识
01.GO基础知识 目录 01.GO基础知识1.GO语言的发展历程2.发展历程3.Windowns安装4.VSCode配置5.基础语法5.1 第一段代码5.2 GO执行的流程5.3 语法规则5.4 代码风格5.5 学习网址 1.GO语言的发展历程 Go语言是谷歌公司于2007年开始开发的一种编程语言,由Robert Griese…...
215.【2023年华为OD机试真题(C卷)】按身高和体重排排队(排序题-JavaPythonC++JS实现)
🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-按身高和体重排排队二.解题思路三.题解代码Pyt…...
虚函数(C++)
四、多态4.1 虚函数 四、多态 多态性是面向对象程序设计语言的又一重要特征,多态(polymorphism)通俗的讲,就是用一个相同的名字定义许多不同的函数,这些函数可以针对不同数据类型实现相同或类似的功能,即所…...
力扣25题: K 个一组翻转链表
【题目链接】力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台,解题代码如下: class Solution {public ListNode reverseKGroup(ListNode head, int k) {ListNode curNode head;ListNode groupHead, groupTail head, lastGrou…...

网络安全应急响应工具之-流量安全取证NetworkMiner
在前面的一些文章中,用了很多的章节介绍流量分析和捕获工具wireshark。Wireshark是一款通用的网络协议分析工具,非常强大,关于wireshark的更多介绍,请关注专栏,wireshark从入门到精通。本文将介绍一个专注于网络流量取…...
http 401 错误
HTTP 401 错误表示未被授权,指客户端通过请求头中的身份验证数据进行身份验证,服务器返回401状态码表示身份验证失败。HTTP 401 错误通常与身份验证和授权相关的 Web 请求有关。 一、HTTP 401错误的定义 HTTP 401 错误是 HTTP 状态码的一种。由于服务器…...

Docker-Compose部署Redis(v7.2)哨兵模式
文章目录 一、前提准备1. 主从集群2. 文件夹结构 二、配置文件1. redis server配置文件2. redis sentinel配置文件3. docker compose文件 三、运行四、测试 环境 docker desktop for windows 4.23.0redis 7.2 一、前提准备 1. 主从集群 首先需要有一个redis主从集群&#x…...

解决问题:PPT中插入视频编辑模式可以播放,幻灯片放映后播放不了
目录 一、原因分析二、解决办法三、其它问题 一、原因分析 这可能是由于PowerPoint的硬件图形加速功能导致的。 二、解决办法 禁用硬件图形加速。 (1)点击《文件》选项卡 (2)点击《选项》 (3)在《高级》…...

使用react+vite开发项目时候,部署上线后刷新页面无法访问解决办法
说一下我这边的环境和使用的路由模式:vitereactBrowserRouter路由模式,所以如果你和我一样的话,可以试试我的这种解决办法,我是将项目打包后直接丢到服务器上的目录里面,然后配置nginx直接访问根目录。 我的nginx配置…...
45. 跳跃游戏 II(Java)
题目描述: 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回到…...

[足式机器人]Part4 南科大高等机器人控制课 CH12 Robotic Motion Control
本文仅供学习使用 本文参考: B站:CLEAR_LAB 笔者带更新-运动学 课程主讲教师: Prof. Wei Zhang 课程链接 : https://www.wzhanglab.site/teaching/mee-5114-advanced-control-for-robotics/ 南科大高等机器人控制课 Ch12 Robotic …...
【C++】知识点汇总(上)
C知识点复习上 一、C 概述1. 基本数据类型2. 变量定义和访问3. 常量与约束访问 二、程序控制结构详解与示例1. 表达式2. 选择控制2.1 if 语句2.2 switch 语句 3. 循环控制3.1 for 循环3.2 while 循环3.3 do-while 循环 4. goto 语句5. 控制语句的嵌套 三、函数1. 函数的定义和调…...

解决docker容器内无法连接宿主redis
背景 小程序的发短信服务挂了,随查看日志,该报错日志如下 Error 111 connecting to 127.0.0.1:6379. Connection refused. 6379是监听redis服务的端口,那大概是redis出错了。 首先查看了redis是否正常启动,检查出服务正常。 由于小…...

43 tmpfs/devtmpfs 文件系统
前言 在 linux 中常见的文件系统 有很多, 如下 基于磁盘的文件系统, ext2, ext3, ext4, xfs, btrfs, jfs, ntfs 内存文件系统, procfs, sysfs, tmpfs, squashfs, debugfs 闪存文件系统, ubifs, jffs2, yaffs 文件系统这一套体系在 linux 有一层 vfs 抽象, 用户程序不用…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...