• 前端面试指南之React篇(一)


    组件之间传值

    • 父组件给子组件传值

      在父组件中用标签属性的=形式传值

      在子组件中使用props来获取值

    • 子组件给父组件传值

      在组件中传递一个函数

      在子组件中用props来获取传递的函数,然后执行该函数

      在执行函数的时候把需要传递的值当成函数的实参进行传递

    • 兄弟组件之间传值

      利用父组件

      先把数据通过 【子组件】===》【父组件】

      然后在数据通过 【父组件】===〉【子组件】

      消息订阅

      使用PubSubJs插件

    React 16中新生命周期有哪些

    关于 React16 开始应用的新生命周期: 可以看出,React16 自上而下地对生命周期做了另一种维度的解读:

    • Render 阶段:用于计算一些必要的状态信息。这个阶段可能会被 React 暂停,这一点和 React16 引入的 Fiber 架构(我们后面会重点讲解)是有关的;
    • Pre-commit阶段:所谓“commit”,这里指的是“更新真正的 DOM 节点”这个动作。所谓 Pre-commit,就是说我在这个阶段其实还并没有去更新真实的 DOM,不过 DOM 信息已经是可以读取的了;
    • Commit 阶段:在这一步,React 会完成真实 DOM 的更新工作。Commit 阶段,我们可以拿到真实 DOM(包括 refs)。

    与此同时,新的生命周期在流程方面,仍然遵循“挂载”、“更新”、“卸载”这三个广义的划分方式。它们分别对应到:

    • 挂载过程:
      • constructor
      • getDerivedStateFromProps
      • render
      • componentDidMount
    • 更新过程:
      • getDerivedStateFromProps
      • shouldComponentUpdate
      • render
      • getSnapshotBeforeUpdate
      • componentDidUpdate
    • 卸载过程:
      • componentWillUnmount

    Redux 怎么实现属性传递,介绍下原理

    react-redux 数据传输∶ view–>action–>reducer–>store–>view。看下点击事件的数据是如何通过redux传到view上:

    • view 上的AddClick 事件通过mapDispatchToProps 把数据传到action —> click:()=>dispatch(ADD)
    • action 的ADD 传到reducer上
    • reducer传到store上 const store = createStore(reducer);
    • store再通过 mapStateToProps 映射穿到view上text:State.text

    代码示例∶

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { createStore } from 'redux';
    import { Provider, connect } from 'react-redux';
    class App extends React.Component{
        render(){
            let { text, click, clickR } = this.props;
            return(
                <div>
                    <div>数据:已有人{text}</div>
                    <div onClick={click}>加人</div>
                    <div onClick={clickR}>减人</div>
                </div>
            )
        }
    }
    const initialState = {
        text:5
    }
    const reducer = function(state,action){
        switch(action.type){
            case 'ADD':
                return {text:state.text+1}
            case 'REMOVE':
                return {text:state.text-1}
            default:
                return initialState;
        }
    }
    
    let ADD = {
        type:'ADD'
    }
    let Remove = {
        type:'REMOVE'
    }
    
    const store = createStore(reducer);
    
    let mapStateToProps = function (state){
        return{
            text:state.text
        }
    }
    
    let mapDispatchToProps = function(dispatch){
        return{
            click:()=>dispatch(ADD),
            clickR:()=>dispatch(Remove)
        }
    }
    
    const App1 = connect(mapStateToProps,mapDispatchToProps)(App);
    
    ReactDOM.render(
        <Provider store = {store}>
            <App1></App1>
        </Provider>,document.getElementById('root')
    )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    React-Router怎么设置重定向?

    使用组件实现路由的重定向:

    <Switch>
      <Redirect from='/users/:id' to='/users/profile/:id'/>
      <Route path='/users/profile/:id' component={Profile}/>
    </Switch>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    当请求 /users/:id 被重定向去 '/users/profile/:id'

    • 属性 from: string:需要匹配的将要被重定向路径。
    • 属性 to: string:重定向的 URL 字符串
    • 属性 to: object:重定向的 location 对象
    • 属性 push: bool:若为真,重定向操作将会把新地址加入到访问历史记录里面,并且无法回退到前面的页面。

    react代理原生事件为什么?

    通过冒泡实现,为了统一管理,对更多浏览器有兼容效果

    合成事件原理

    如果react事件绑定在了真实DOM节点上,一个节点同事有多个事件时,页面的响应和内存的占用会受到很大的影响。因此SyntheticEvent作为中间层出现了。

    事件没有在目标对象上绑定,而是在document上监听所支持的所有事件,当事件发生并冒泡至document时,react将事件内容封装并叫由真正的处理函数运行。

    版权声明:本文为CSDN博主「jiuwanli666」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

    对React SSR的理解

    服务端渲染是数据与模版组成的html,即 HTML = 数据 + 模版。将组件或页面通过服务器生成html字符串,再发送到浏览器,最后将静态标记"混合"为客户端上完全交互的应用程序。页面没使用服务渲染,当请求页面时,返回的body里为空,之后执行js将html结构注入到body里,结合css显示出来;

    SSR的优势:

    • 对SEO友好
    • 所有的模版、图片等资源都存在服务器端
    • 一个html返回所有数据
    • 减少HTTP请求
    • 响应快、用户体验好、首屏渲染快

    1)更利于SEO

    不同爬虫工作原理类似,只会爬取源码,不会执行网站的任何脚本使用了React或者其它MVVM框架之后,页面大多数DOM元素都是在客户端根据js动态生成,可供爬虫抓取分析的内容大大减少。另外,浏览器爬虫不会等待我们的数据完成之后再去抓取页面数据。服务端渲染返回给客户端的是已经获取了异步数据并执行JavaScript脚本的最终HTML,网络爬中就可以抓取到完整页面的信息。

    2)更利于首屏渲染

    首屏的渲染是node发送过来的html字符串,并不依赖于js文件了,这就会使用户更快的看到页面的内容。尤其是针对大型单页应用,打包后文件体积比较大,普通客户端渲染加载所有所需文件时间较长,首页就会有一个很长的白屏等待时间。

    SSR的局限:

    1)服务端压力较大

    本来是通过客户端完成渲染,现在统一到服务端node服务去做。尤其是高并发访问的情况,会大量占用服务端CPU资源;

    2)开发条件受限

    在服务端渲染中,只会执行到componentDidMount之前的生命周期钩子,因此项目引用的第三方的库也不可用其它生命周期钩子,这对引用库的选择产生了很大的限制;

    3)学习成本相对较高 除了对webpack、MVVM框架要熟悉,还需要掌握node、 Koa2等相关技术。相对于客户端渲染,项目构建、部署过程更加复杂。

    时间耗时比较:

    1)数据请求

    由服务端请求首屏数据,而不是客户端请求首屏数据,这是"快"的一个主要原因。服务端在内网进行请求,数据响应速度快。客户端在不同网络环境进行数据请求,且外网http请求开销大,导致时间差

    • 客户端数据请求

    • 服务端数据请求

      2)html渲染 服务端渲染是先向后端服务器请求数据,然后生成完整首屏 html返回给浏览器;而客户端渲染是等js代码下载、加载、解析完成后再请求数据渲染,等待的过程页面是什么都没有的,就是用户看到的白屏。就是服务端渲染不需要等待js代码下载完成并请求数据,就可以返回一个已有完整数据的首屏页面。

    • 非ssr html渲染

    • ssr html渲染

    React组件命名推荐的方式是哪个?

    通过引用而不是使用来命名组件displayName。

    使用displayName命名组件:

    export default React.createClass({  displayName: 'TodoApp',  // ...})
    
    
    • 1
    • 2

    React推荐的方法:

    export default class TodoApp extends React.Component {  // ...}
    
    
    • 1
    • 2

    参考:前端react面试题详细解答
    **

    React 与 Vue 的 diff 算法有何不同?

    diff 算法是指生成更新补丁的方式,主要应用于虚拟 DOM 树变化后,更新真实 DOM。所以 diff 算法一定存在这样一个过程:触发更新 → 生成补丁 → 应用补丁。

    React 的 diff 算法,触发更新的时机主要在 state 变化与 hooks 调用之后。此时触发虚拟 DOM 树变更遍历,采用了深度优先遍历算法。但传统的遍历方式,效率较低。为了优化效率,使用了分治的方式。将单一节点比对转化为了 3 种类型节点的比对,分别是树、组件及元素,以此提升效率。

    • 树比对:由于网页视图中较少有跨层级节点移动,两株虚拟 DOM 树只对同一层次的节点进行比较。
    • 组件比对:如果组件是同一类型,则进行树比对,如果不是,则直接放入到补丁中。
    • 元素比对:主要发生在同层级中,通过标记节点操作生成补丁,节点操作对应真实的 DOM 剪裁操作。

    以上是经典的 React diff 算法内容。自 React 16 起,引入了 Fiber 架构。为了使整个更新过程可随时暂停恢复,节点与树分别采用了 FiberNode 与 FiberTree 进行重构。fiberNode 使用了双链表的结构,可以直接找到兄弟节点与子节点。整个更新过程由 current 与 workInProgress 两株树双缓冲完成。workInProgress 更新完成后,再通过修改 current 相关指针指向新节点。

    Vue 的整体 diff 策略与 React 对齐,虽然缺乏时间切片能力,但这并不意味着 Vue 的性能更差,因为在 Vue 3 初期引入过,后期因为收益不高移除掉了。除了高帧率动画,在 Vue 中其他的场景几乎都可以使用防抖和节流去提高响应性能。

    constructor

    答案是:在 constructor 函数里面,需要用到props的值的时候,就需要调用 super(props)
    
    • 1
    1. class语法糖默认会帮你定义一个constructor,所以当你不需要使用constructor的时候,是可以不用自己定义的

    2. 当你自己定义一个constructor的时候,就一定要写super(),否则拿不到this

    3. 当你在constructor里面想要使用props的值,就需要传入props这个参数给super,调用super(props),否则只需要写super()

    React.Children.map和js的map有什么区别?

    JavaScript中的map不会对为null或者undefined的数据进行处理,而React.Children.map中的map可以处理React.Children为null或者undefined的情况。

    React如何获取组件对应的DOM元素?

    可以用ref来获取某个子节点的实例,然后通过当前class组件实例的一些特定属性来直接获取子节点实例。ref有三种实现方法:

    • 字符串格式:字符串格式,这是React16版本之前用得最多的,例如:

      span

    • 函数格式:ref对应一个方法,该方法有一个参数,也就是对应的节点实例,例如:

      this.info = ele}>

    • createRef方法:React 16提供的一个API,使用React.createRef()来实现

    何为 reducer

    一个 reducer 是一个纯函数,该函数以先前的 state 和一个 action 作为参数,并返回下一个 state。

    对React-Fiber的理解,它解决了什么问题?

    React V15 在渲染时,会递归比对 VirtualDOM 树,找出需要变动的节点,然后同步更新它们, 一气呵成。这个过程期间, React 会占据浏览器资源,这会导致用户触发的事件得不到响应,并且会导致掉帧,导致用户感觉到卡顿

    为了给用户制造一种应用很快的“假象”,不能让一个任务长期霸占着资源。 可以将浏览器的渲染、布局、绘制、资源加载(例如 HTML 解析)、事件响应、脚本执行视作操作系统的“进程”,需要通过某些调度策略合理地分配 CPU 资源,从而提高浏览器的用户响应速率, 同时兼顾任务执行效率。

    所以 React 通过Fiber 架构,让这个执行过程变成可被中断。“适时”地让出 CPU 执行权,除了可以让浏览器及时地响应用户的交互,还有其他好处:

    • 分批延时对DOM进行操作,避免一次性操作大量 DOM 节点,可以得到更好的用户体验;
    • 给浏览器一点喘息的机会,它会对代码进行编译优化(JIT)及进行热代码优化,或者对 reflow 进行修正。

    核心思想: Fiber 也称协程或者纤程。它和线程并不一样,协程本身是没有并发或者并行能力的(需要配合线程),它只是一种控制流程的让出机制。让出 CPU 的执行权,让 CPU 能在这段时间执行其他的操作。渲染的过程可以被中断,可以将控制权交回浏览器,让位给高优先级的任务,浏览器空闲后再恢复渲染。

    React中constructor和getInitialState的区别?

    两者都是用来初始化state的。前者是ES6中的语法,后者是ES5中的语法,新版本的React中已经废弃了该方法。

    getInitialState是ES5中的方法,如果使用createClass方法创建一个Component组件,可以自动调用它的getInitialState方法来获取初始化的State对象,

    var APP = React.creatClass ({
      getInitialState() {
        return { 
            userName: 'hi',
            userId: 0
         };
     }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    React在ES6的实现中去掉了getInitialState这个hook函数,规定state在constructor中实现,如下:

    Class App extends React.Component{
        constructor(props){
          super(props);
          this.state={};
        }
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    state 是怎么注入到组件的,从 reducer 到组件经历了什么样的过程

    通过connect和mapStateToProps将state注入到组件中:

    import { connect } from 'react-redux'
    import { setVisibilityFilter } from '@/reducers/Todo/actions'
    import Link from '@/containers/Todo/components/Link'
    
    const mapStateToProps = (state, ownProps) => ({
        active: ownProps.filter === state.visibilityFilter
    })
    
    const mapDispatchToProps = (dispatch, ownProps) => ({
        setFilter: () => {
            dispatch(setVisibilityFilter(ownProps.filter))
        }
    })
    
    export default connect(
        mapStateToProps,
        mapDispatchToProps
    )(Link)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    上面代码中,active就是注入到Link组件中的状态。 mapStateToProps(state,ownProps)中带有两个参数,含义是∶

    • state-store管理的全局状态对象,所有都组件状态数据都存储在该对象中。
    • ownProps 组件通过props传入的参数。

    reducer 到组件经历的过程:

    • reducer对action对象处理,更新组件状态,并将新的状态值返回store。
    • 通过connect(mapStateToProps,mapDispatchToProps)(Component)对组件 Component进行升级,此时将状态值从store取出并作为props参数传递到组件。

    高阶组件实现源码∶

    import React from 'react'
    import PropTypes from 'prop-types'
    
    // 高阶组件 contect 
    export const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => {
        class Connect extends React.Component {
            // 通过对context调用获取store
            static contextTypes = {
                store: PropTypes.object
            }
    
            constructor() {
                super()
                this.state = {
                    allProps: {}
                }
            }
    
            // 第一遍需初始化所有组件初始状态
            componentWillMount() {
                const store = this.context.store
                this._updateProps()
                store.subscribe(() => this._updateProps()); // 加入_updateProps()至store里的监听事件列表
            }
    
            // 执行action后更新props,使组件可以更新至最新状态(类似于setState)
            _updateProps() {
                const store = this.context.store;
                let stateProps = mapStateToProps ?
                    mapStateToProps(store.getState(), this.props) : {} // 防止 mapStateToProps 没有传入
                let dispatchProps = mapDispatchToProps ?
                    mapDispatchToProps(store.dispatch, this.props) : {
                                        dispatch: store.dispatch
                                    } // 防止 mapDispatchToProps 没有传入
                this.setState({
                    allProps: {
                        ...stateProps,
                        ...dispatchProps,
                        ...this.props
                    }
                })
            }
    
            render() {
                return <WrappedComponent {...this.state.allProps} />
            }
        }
        return Connect
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    对componentWillReceiveProps 的理解

    该方法当props发生变化时执行,初始化render时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用。

    使用好处: 在这个生命周期中,可以在子组件的render函数执行前获取新的props,从而更新子组件自己的state。 可以将数据请求放在这里进行执行,需要传的参数则从componentWillReceiveProps(nextProps)中获取。而不必将所有的请求都放在父组件中。于是该请求只会在该组件渲染时才会发出,从而减轻请求负担。

    componentWillReceiveProps在初始化render的时候不会执行,它会在Component接受到新的状态(Props)时被触发,一般用于父组件状态更新时子组件的重新渲染。

    React 16.X 中 props 改变后在哪个生命周期中处理

    在getDerivedStateFromProps中进行处理。

    这个生命周期函数是为了替代componentWillReceiveProps存在的,所以在需要使用componentWillReceiveProps时,就可以考虑使用getDerivedStateFromProps来进行替代。

    两者的参数是不相同的,而getDerivedStateFromProps是一个静态函数,也就是这个函数不能通过this访问到class的属性,也并不推荐直接访问属性。而是应该通过参数提供的nextProps以及prevState来进行判断,根据新传入的props来映射到state。

    需要注意的是,如果props传入的内容不需要影响到你的state,那么就需要返回一个null,这个返回值是必须的,所以尽量将其写到函数的末尾:

    static getDerivedStateFromProps(nextProps, prevState) {
        const {type} = nextProps;
        // 当传入的type发生变化的时候,更新state
        if (type !== prevState.type) {
            return {
                type,
            };
        }
        // 否则,对于state不进行任何操作
        return null;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    什么是上下文Context

    Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。

    • 用法:在父组件上定义getChildContext方法,返回一个对象,然后它的子组件就可以通过this.context属性来获取
    import React,{Component} from 'react';
    import ReactDOM from 'react-dom';
    import PropTypes from 'prop-types';
    class Header extends Component{
        render() {
            return (
                <div>
                    <Title/>
                </div>
            )
        }
    }
    class Title extends Component{
        static contextTypes={
            color:PropTypes.string
        }
        render() {
            return (
                <div style={{color:this.context.color}}>
                    Title
                </div>
            )
        }
    }
    class Main extends Component{
        render() {
            return (
                <div>
                    <Content>
                    </Content>
                </div>
            )
        }
    }
    class Content extends Component{
        static contextTypes={
            color: PropTypes.string,
            changeColor:PropTypes.func
        }
        render() {
            return (
                <div style={{color:this.context.color}}>
                    Content
                    <button onClick={()=>this.context.changeColor('green')}>绿色</button>
                    <button onClick={()=>this.context.changeColor('orange')}>橙色</button>
                </div>
            )
        }
    }
    class Page extends Component{
        constructor() {
            super();
            this.state={color:'red'};
        }
        static childContextTypes={
            color: PropTypes.string,
            changeColor:PropTypes.func
        }
        getChildContext() {
            return {
                color: this.state.color,
                changeColor:(color)=>{
                    this.setState({color})
                }
            }
        }
        render() {
            return (
                <div>
                    <Header/>
                    <Main/>
                </div>
            )
        }
    }
    ReactDOM.render(<Page/>,document.querySelector('#root'));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    Redux 中间件是怎么拿到store 和 action? 然后怎么处理?

    redux中间件本质就是一个函数柯里化。redux applyMiddleware Api 源码中每个middleware 接受2个参数, Store 的getState 函数和dispatch 函数,分别获得store和action,最终返回一个函数。该函数会被传入 next 的下一个 middleware 的 dispatch 方法,并返回一个接收 action 的新函数,这个函数可以直接调用 next(action),或者在其他需要的时刻调用,甚至根本不去调用它。调用链中最后一个 middleware 会接受真实的 store的 dispatch 方法作为 next 参数,并借此结束调用链。所以,middleware 的函数签名是({ getState,dispatch })=> next => action。

    对虚拟 DOM 的理解?虚拟 DOM 主要做了什么?虚拟 DOM 本身是什么?

    从本质上来说,Virtual Dom是一个JavaScript对象,通过对象的方式来表示DOM结构。将页面的状态抽象为JS对象的形式,配合不同的渲染工具,使跨平台渲染成为可能。通过事务处理机制,将多次DOM修改的结果一次性的更新到页面上,从而有效的减少页面渲染的次数,减少修改DOM的重绘重排次数,提高渲染性能。

    虚拟DOM是对DOM的抽象,这个对象是更加轻量级的对DOM的描述。它设计的最初目的,就是更好的跨平台,比如node.js就没有DOM,如果想实现SSR,那么一个方式就是借助虚拟dom,因为虚拟dom本身是js对象。 在代码渲染到页面之前,vue或者react会把代码转换成一个对象(虚拟DOM)。以对象的形式来描述真实dom结构,最终渲染到页面。在每次数据发生变化前,虚拟dom都会缓存一份,变化之时,现在的虚拟dom会与缓存的虚拟dom进行比较。在vue或者react内部封装了diff算法,通过这个算法来进行比较,渲染时修改改变的变化,原先没有发生改变的通过原先的数据进行渲染。

    另外现代前端框架的一个基本要求就是无须手动操作DOM,一方面是因为手动操作DOM无法保证程序性能,多人协作的项目中如果review不严格,可能会有开发者写出性能较低的代码,另一方面更重要的是省略手动DOM操作可以大大提高开发效率。

    为什么要用 Virtual DOM:

    (1)保证性能下限,在不进行手动优化的情况下,提供过得去的性能

    下面对比一下修改DOM时真实DOM操作和Virtual DOM的过程,来看一下它们重排重绘的性能消耗∶

    • 真实DOM∶ 生成HTML字符串+ 重建所有的DOM元素
    • Virtual DOM∶ 生成vNode+ DOMDiff+必要的DOM更新

    Virtual DOM的更新DOM的准备工作耗费更多的时间,也就是JS层面,相比于更多的DOM操作它的消费是极其便宜的。尤雨溪在社区论坛中说道∶ 框架给你的保证是,你不需要手动优化的情况下,我依然可以给你提供过得去的性能。 (2)跨平台 Virtual DOM本质上是JavaScript的对象,它可以很方便的跨平台操作,比如服务端渲染、uniapp等。

  • 相关阅读:
    WPF 使用Image控件显示图片
    Jmeter参数化 —— 循环断言多方法
    ESP8266-Arduino编程实例-MQ-6异丁烷丙烷传感器驱动
    设计模式之(13)--模板方法模式
    PyTorch中ReduceLROnPlateau的学习率调整优化器
    外汇天眼:ThinkMarkets 获得 CySEC 许可证,允许其从塞浦路斯扩展其欧盟服务
    【机器学习】python机器学习使用scikit-learn对模型进行评估:使用t分布及z分布评估模型误差的95%置信空间
    Python自动化(3)——鼠标模拟
    【数据结构初阶】(栈和队列)图文详解四道oj+三道easy概念题
    单例模式坑这么多,不会用别乱用
  • 原文地址:https://blog.csdn.net/beifeng11996/article/details/127644758