皮皮网

【标签云-源码】【pcietlp源码】【phoenixminer源码】contexttype源码

来源:semaphore指标源码 时间:2024-12-23 00:01:34

1.python context 使用
2.preact源码解析,从preact中理解react原理
3.React中不常用的功能——Context

contexttype源码

python context 使用

        python中context可以用于一些需要自动管理逻辑的场景,比如读取文件内容后需要自动关闭文件,对代码块进行自动上锁和解锁等,下面我们就简单介绍下context的使用。

        一、context使用语法

        context 与 with 一块使用,也可以附加一个 as 语句,如下:

        二、context 工作原理

        __exit__ 方法有3个参数exc_type, exc_value, exc_tb,无论 code block 中的代码在执行中是否有异常都会执行 __exit__ 方法。

        如果 code block 中的代码有抛异常,__exit__ 方法的3个参数值与 sys.exc_info 返回值一样(分别代表异常类型、异常值、堆栈信息),此时如果方法返回 False 则异常会继续往上抛,否则代码继续往下执行。如果 code block 中的代码没有抛异常则3个参数为None。

        三、context 实战

        open 函数的返回值已经是一个context了,假设 “a.txt” 文件已经存在且当前用户有读权限,则以下示例在 with 代码块执行完后会自动关闭文件:

        如果我们要自己实现这个 context 该怎么实现呢?其实很简单,只需要按照上面的描述定义一个类就行,如下:

        是不是很简单,你学会了吗?如果有任何疑问,欢迎评论交流。

preact源码解析,从preact中理解react原理

       基于preact.3.4版本进行分析,完整注释请参阅链接。阅读源码建议采用跳跃式阅读,遇到难以理解的标签云-源码部分先跳过,待熟悉整体架构后再深入阅读。如果觉得有价值,不妨为项目点个star。

       一直对研究react源码抱有兴趣,但每次都半途而废,主要原因是react项目体积庞大,代码颗粒化且执行流程复杂,需要投入大量精力。因此,转向研究preact,pcietlp源码一个号称浓缩版react,体积仅有3KB。市面上已有对preact源码的解析,但大多存在版本过旧和分析重点不突出的问题,如为什么存在_nextDom?value为何不在diffProps中处理?这些都是解析代码中的关键点和收益点。

       一. 文件结构

       二. 渲染原理

       简单demo展示如何将App组件渲染至真实DOM中。

       vnode表示节点描述对象。在打包阶段,babel的transform-react-jsx插件会将jsx语法编译为JS语法,即转换为React.createElement(type, props, children)形式。preact中需配置此插件,使React.createElement对应为h函数,编译后的jsx语法如下:h(App,null)。

       执行render函数后,先调用h函数,phoenixminer源码然后通过createVNode返回虚拟节点。最终,h(App,null)的执行结果为{ type:App,props:null,key:null,ref:null},该虚拟节点将被用于渲染真实DOM。

       首次渲染时,旧虚拟节点基本为空。diff函数比较虚拟节点与真实DOM,创建挂载完成,执行commitRoot函数,该函数执行组件的did生命周期和setState回调。

       2. diff

       diff过程包含diff、diffElementNodes、diffChildren、diffProps四个函数。diff主要处理函数型虚拟节点,源码档案非函数型节点调用diffElementNodes处理。判断虚拟节点是否存在_component属性,若无则实例化,执行组件生命周期,调用render方法,保存子节点至_children属性,进而调用diffChildren。

       diffElementNodes处理HTML型虚拟节点,创建真实DOM节点,查找复用,若无则创建文本或元素节点。diffProps处理节点属性,如样式、事件监听等。diffChildren比较子节点并添加至当前DOM节点。elo源码

       分析diff执行流程,render函数后调用diff比较虚拟节点,执行App组件生命周期和render方法,保存返回的虚拟节点至_children属性,调用diffChildren比较子节点。整体虚拟节点树如下:

       diffChildren遍历子节点,查找DOM节点,比较虚拟节点,返回真实DOM,追加至parentDOM或子节点后。

       三. 组件

       1. component

       Component构造函数设置状态、强制渲染、定义render函数和enqueueRender函数。

       强制渲染通过设置_force标记,加入渲染队列并执行。_force为真时,diff渲染不会触发某些生命周期。

       render函数默认为Fragment组件,返回子节点。

       enqueueRender将待渲染组件加入队列,延迟执行process函数。process排序组件,渲染最外层组件,调用renderComponent渲染,更新DOM后执行所有组件的did生命周期和setState回调。

       2. context

       使用案例展示跨组件传递数据。createContext创建context,包含Provider和Consumer组件。Provider组件跨组件传递数据,Consumer组件接收数据。

       源码简单,createContext后返回context对象,包含Consumer与Provider组件。Consumer组件设置contextType属性,渲染时执行子节点,等同于类组件。

       Provider组件创建函数,渲染到Provider组件时调用getChildContext获取ctx对象,diff时传递至子孙节点组件。组件设置contextType,通过sub函数订阅Provider组件值更新,值更新时渲染订阅组件。

       四. 解惑疑点

       理解代码意图。支持Promise时,使用Promise处理,否则使用setTimeout。了解Promise.prototype.then.bind(Promise.resolve())最终执行的Promise.resolve().then。

       虚拟节点用Fragment包装的原因是,避免直接调用diffElementNodes,以确保子节点正确关联至父节点DOM。

       hydrate与render的区别在于,hydrate仅处理事件,不处理其他props,适用于服务器端渲染的HTML,客户端渲染使用hydrate提高首次渲染速度。

       props中value与checked单独处理,diffProps不处理,处理在diffChildren中,找到原因。

       在props中设置value为空的原因是,遵循W3C规定,不设置value时,文本内容作为value。为避免MVVM问题,需在子节点渲染后设置value为空,再处理元素value。

       组件异常处理机制中,_processingException和_pendingError变量用于标记组件异常处理状态,确保不会重复跳过异常组件。

       diffProps中事件处理机制,为避免重复添加事件监听器,只在事件函数变化时修改dom._listeners,触发事件时仅执行保存的监听函数,移除监听在onChange设置为空时执行。

       理解_nextDom的使用,确保子节点与父节点关联,避免在函数型节点渲染时进行不必要的关联操作。

React中不常用的功能——Context

        React源码版本.8

        跨层级通信 Context

        React.createContext创建context对象

        Context.Provider父级创建provider传递参数

        子组件消费

        该 API 订阅单一 context

        useContext只可以用在函数组件中或者自定义hook,且第二个参数不会覆盖第一个

        ReactContext.js 中的createContext

        ReactFiberClassComponent.js 中的constructClassInstance

        即Class 组件 构造函数初始化

        从上可知若contextType是对象 且不为null 则将contextType赋值给this.context

        从构造函数可以知晓Consumer跟Provider是指向同一个context的,所以实现了跨级访问

        在ReactFiberHooks.js中 声明了

        在HooksDispatcherOnMount或HooksDispatcherOnUpdate中,useContext实际调用的都是readContext

        ReactFiberNewContext.js中的readContext

        readContext返回context._currentValue

        总结

        context实现跨级读取访问的根本性就是通过Context组件维护一个稳定对象,在对象内维护一个可变的_currentValue值,供Consumer访问

        React源码

        React-Context-文档

        react组件化——context