React---面试题

翻到OneNote乱七八糟的面试题截图,随手整理一下整了一天,手已软··· 

什么是虚拟 DOM?

  • 虚拟 DOM(VDOM)是真实 DOM 在内存中的表示,是 UI 的表示形式,同时和实际 DOM 同步。这是发生在渲染函数被调用DOM 元素在屏幕上显示之间的过程,整个过程被称为调和

为什么虚拟 DOM 会提高性能?

  • 虚拟 DOM 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。

  • 用 JavaScript 对象结构表示 DOM 树的结构,然后用这个树构建一个真正的 DOM 树,插到文档当中,当状态变更的时候,重新构造一颗新的对象树,然后用新的树和旧的树进行比较,记录两棵树的差异,把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。

react diff 原理?

  1. 把树形结构按层分解,只比较同级元素。
  2. 把列表结构的每个单元添加唯一的 key 属性,方便比较。
  3. react 只会匹配相同的 class 名的 component。
  4. 合并操作,调用 component 的 setState 方法的时候,react 将其标记到 dirty。到每一个事件循环结束,react 检查所有标记 dirty 的 component 重新绘制。
  5. 选择性子树渲染,开发人员可以重写 shouldComponentUpdate,提高 diff 性能。

react 构建组件的三种方式?

  1. React.createClass()
  2. ES6 clss
  3. 无状态函数 function

如何 React.createElement?

const element=React.createElement(
    'h1',
    {className:'greeting'},
    'Hello,world!'
)

类组件(Class)和函数组件(Function)有什么区别?

  1. 类组件允许使用其它特性,如组件自身的状态 state 和生命周期钩子,还能使组件直接访问 store 并维持状态。
  2. 当组件只接收 props 组件渲染页面时,就是一个"无状态组件(Stateless)",可以使用一个纯函数来创建这样的组件,这就是函数组件,这种组件也被称为"哑组件(Dumb)“或"展示组件”。
  3. 通过 function 定义组件的写法更加 js,代码结构简单,代码量小,没有 this 指向问题

什么是纯函数?

  • 纯函数是不依赖并且不会在其作用域之外修改变量状态的函数。本质上,纯函数始终在给定向同参数的情况下返回相同的结果

(组件的)状态(State)和属性(props)之间有何不同

  1. State 是一个数据结构,用于组件挂载时所需数据的默认值,是组件自己管理数据,控制自己的状态,可变。
  2. Props(properties)是组件的配置,是外部传入的数据参数,Props 由父组件传递给子组件,并且就子组件而言,props 是不可变的。组件虽然不能改变自身的 props,但是可以把其子组件的 props 放在一起统一管理。Props 也不仅仅是数据,回调函数也可以通过 Props 传递。
  • props 和 state 是普通的 JS 对象,它们都包含影响渲染输出的信息,没有 state 的叫做无状态组件,有 state 的叫做有状态组件,多用 props,少用 state,也就是多写无状态组件

在构造函数中,调用 super(props)的目的/作用是什么?

  • 在 super()被调用之前,子类构造函数是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super(),ES6 一样。
  • 将参数 props 传递 给 super()的原因则是:便于在子类中能在 constructor 访问 this.props,通过 this.props 来获取传入的 props。

为什么类方法需要绑定到类实例?

  • 在 JS 中,this 值会根据当前上下文变化,在 React 类组件方法中,开发人员通常希望 this 引用组件的当前实例,因此非常有必要把这些方法绑定到实例,通常这是在构造函数中完成的。

有几种为事件处理函数绑定 this 指向方法?

  1. 组件初始化时,通过 class 类的方法在 constructor 里绑定,好处只会执行一次。
this.state = {};
this.keyUpHandle = this.keyUpHandle.bind(this);
  1. 方法调用时绑定,每一次数据改变,方法重新调用就会执行。
<input onKeyUp = { this.nickNameKeyUpHandle.bind(this) }>

nickNameKeyUpHandle(e){
    console.group("在方法调用的时候绑定");
    console.log("e.target.value");
    console.log("this");
    console.groupEnd();
}
  1. render 里,用箭头函数绑定,因为箭头函数的 this 指向箭头函数定义的时候其所处作用域的 this,render 函数 this 始终指向组件实例,所以箭头函数 this 也指向组件实例,但是,每次数据改变页面刷新都会重新绑定。
<input onKeyUp = { e => this.skillKeyUpHandle(e) }>

skillKeyUpHandle(e){
    console.group("箭头函数改变this指向");
    console.log("e.target.value");
    console.log("this");
    console.groupEnd();
}

有几种常用方法可以避免在 react 中绑定方法?

  1. 将事件处理程序定义为内联箭头函数
class SubmitButton extends React.Component{
    constructor(props){
        super(props);
        this.state={
            isFormSubmitted:false
        }
    }

    render(){
        return(
            <button onClick={()=>{
                this.setState({isFormSubmitted:true});
            }}>Submit</button>
        )
    }
}
  1. 使用箭头函数来定义方法
class SubmitButton extends React.Component{
    state={
        isFormSubmitted:false
    }

    handleSubmit =()=>{
        this.setState({
            isFormSubmitted:true
        })
    }

    render(){
        return(
            <button onClick={this.handleSubmit}>Submit</button>
        )
    }
}
  1. 使用带有 Hooks 的函数组件
const SubmitButton=()=>{
    const [isFormSubmitted,setIsFormSubmitted]=useState(false);

    return(
        <button onClick={()=>{
            setIsFormSubmitted(true)
        }}>Submit</button>
    )
}

什么是受控组件?

  • 在 HTML 中,类似<input>、<textarea>和<select>这样的表单元素会维护自身的状态,并基于用户的输入来更新,当用户提交表单时,前面提到的元素的值将随表单一起被发送,但在 react 中会有些不同,包含表单元素的组件将会在 state 中追踪输入的值,并且每次调用回调函数时,如 onChange 会更新 state,重新渲染组件。一个输入表单元素,它的值通过 react 这种方式来控制,这样的元素就被称为"受控元素"

受控组件和非受控组件区别是什么?

  1. 受控组件是 react 控制中的组件,并且是表单数据真实的唯一来源。

  2. 非受控组件是由 DOM 处理表单数据的地方,而不在 react 组件中。

  • 尽管非受控组件通常更易于实现,因为只需使用 refs 即可从 DOM 中获取值,但通常建议优先选择受控组件,主要原因是受控组件支持即时字段验证,允许有条件地禁用/启用按钮,强制输入格式

什么是 React Hooks?

  • Hooks是 react16.8 中的新增内容,它们允许在不编写类的情况下使用 state 和其他 react 特性。使用 Hooks 可以从组件中提取有状态逻辑,这样就可以独立地测试和重用它。Hooks允许咱在不改变组件层次结构的情况下重用有状态逻辑,这使得在许多组件之间或者与社区共享 Hooks 变得很容易。

使用 React Hooks 好处是啥?

  • 首先,Hooks通常支持提取和重用跨多个组件通用的有状态逻辑,而无需承担高阶组件或渲染 props 的负担,Hooks可以轻松地操作函数组件的状态,而不需要将它们转换为类组件

  • Hooks 在类中不起作用,通过使用它们,咱们可以完全避免使用生命周期,例如 componentDidMount、componentDidUpdate、componentWillUnmount,相反去使用像 useEffect 这样的内置钩子

  • useState、useEffect、useLocation、useParams 等,useLocation 可以获取当前的 url 地址数据,useParams 是路由新增的 hook 方法可以直接获取到当前的 params 参数。

什么是 useState,useEffect?

  1. useState 可以在 function 定义的组件中设置局部状态,返回两个值:局部状态的名字和改变状态的方法。改变数据或者使用数据直接使用 useState,数组。
const {useState}=React;
function Counter(){
    const [count,setCount]=useState(0);
}
  1. useEffect 副作用,可以在 function 定义的组件中模拟生命周期,参数一是回调函数,参数二是依赖项,当参数二中的数据改变之后会触发第一个回调函数,如果参数二为空数组表示组件初始化的时候只执行一次
useEffect(()=>{

},[...])

Hooks 会取代 render props 和高阶组件吗?

  • 通常,render、props 和高阶组件仅渲染一个子组件,React 团队认为,Hooks 是服务此用例的更简单方法。
  • 这两种模式仍然有一席之地(例如,一个虚拟的 scroller 组件可能有一个 renderItem prop,或者一个可视化的容器组件可能有它自己的 DOM 结构)。但在大多数情况下,Hooks 就足够了,可以帮助减少树中的嵌套

这三个点(…)在 React 是干嘛用的?

  • 对于创建具有现有对象大多数属性的新对象非常方便,更新 state 经常这么做

为什么建议传递给 setState 的参数是一个 callback 而不是一个对象?

  • 因为 this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state

为什么不直接更新 state 呢?

  • 如果试图直接更新 state,则不会重新渲染组件,需要使用 setState()方法来更新 state,它调度对组件 state 对象的更新,当 state 改变时,组件通过重新渲染来响应。

当调用 setState 时,React render 是如何工作的?

  • 咱们可以将"render"分为两个步骤:

    1. 虚拟 DOM 渲染:当 render 方法被调用时,它返回一个新组件的虚拟 DOM 结构,当调用 setState()时,render 会被再次调用,因为默认情况下 shouldComponentUpdate 总是返回 true,所以默认情况下 react 是没有优化的。

    2. 原生 DOM 渲染:react 只会在虚拟 DOM 中修改真实 DOM 节点,而且修改的次数非常少–这是很棒的 react 特性,它优化了真实 DOM 的变化,使 React 变得更快。

调用 setState 之后发生了什么?

  • 在代码中调用 setState 函数之后,react 会传入的参数对象和组件当前的状态合并,然后触发所谓的调和过程

  • 经过调和过程,react 会以相对高效的方式根据新的状态构建 react 元素树并且着手重新渲染整个 UI 界面

  • 在 react 得到元素树之后,react 会自动计算出新树和老树的节点差异,然后根据差异对界面进行最小化重渲染,在差异计算算法中,react 能够相对精确地知道哪些位置发生了改变,以及应该如何改变,这就保证了按需更新而不是全部重新渲染

如果需要根据以前的状态重新设置状态,怎么写比较好?

  • 将一个函数传递给 setState,该函数接收上一个 state 的值和当前的 props,并返回一个新的状态。
this.setState((prevState,props)=>{
    return{
        streak:prevState.streak+props.count
    }
})

react 中 refs 是干嘛用的?

  • Refs提供了一种访问在 render 方法中创建 DOM 节点或者 React 元素的方法,在典型的数据流中,父子组件交互的唯一方式是 props,先要修改子组件,需要使用新的 props 重新渲染,凡是有例外,某些情况下咱们需要在典型数据流外,强制修改子代,这个时候可以使用 refs,在组件添加一个 ref 属性来用,该属性的是一个回调函数,接收作为其第一个参数的底层 DOM 元素组件的挂载实例
<form onSumbit={this.handleSubmit}>

<input type="text" ref={(input)=>this.input=input} />
  • Input 有一个ref 属性,它的是一个函数,该函数接收输入的实际 DOM 元素,然后将其放在实例上,这样就可以在 handleSumbmit 内部访问它。
handelSubmit=()=>{
    console.log('Input Value:',this.input.value)
}
  • 经常被误解,只有在类组件才能使用 refs,但 refs 也可以通过利用 js 中的闭包和函数组件一起使用。
function CustomForm({handleSumit}){
    let inputElement
    return(
        <form onSubmit={()=>handleSubmit(inputElement.value)}>

        <input type="text"
                ref={(input)=>inputElement=input} />

        <button type="submit">Submit</button>

        </form>
    )
}

react 中 keys 是什么作用?

  • Keys 是 react 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
render(){
    return(
        <ul>
        {this.state.todoItems.map(({item,key})=>{
            return <li key={key}>{item}</li>>
        })}
        </ur>
    )
}

  • 在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性
  • 在 React Diff 算法中 react 会借助元素的 key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染
  • React 还需要借助 Key 值来判断元素和本地状态的关联关系,因此,绝不可忽视转换函数中 Key 的重要性。

React 组件生命周期有哪些不同阶段?

  • 在组件生命周期有四个不同阶段:
  1. 组件初始化阶段,Initialization,该阶段组件设置一些默认属性和初始化状态 state

  2. 挂载阶段,Mounting,该阶段三个过程:将要挂载(componentWillMount)->render 渲染(此阶段 render 执行一次)->挂载完成(componentDidMount)。

  3. 更新阶段,Updating,该阶段中,组件以两种方式更新:属性更新和数据更新。发送新的 props 和 state 状态,当组件接收之后会判断组件是否需要更新,更新阶段只有修改了属性或者数据,都会重新渲染。在 render 调用 this.setState 就会死循环。(shouldComponentUpdata,ComponentWillUpdata 和 ComponentDidUpdata)

  4. 卸载阶段,componentWillUnmount

React 组件生命周期方法有哪些?

  • componentWillMount:渲染之前执行,用于根组件的 App 级配置
  • componentDidMount:在第一次渲染之后执行,可以在这里做ajax 请求、dom 的操作和状态更新以及事件监听器
  • componentWillReceiveProps:初始化 render 时不会执行,会在组件接收到新的状态(props)时被触发,一般用于父组件状态更新时子组件的重新渲染
  • shouldComponentUpdata:确定是否更新组件,默认情况下返回 true,如果确定在 state 或 props 更新后组件不需要再重新渲染,返回 false,这是一个提高性能的好方法
  • ComponentWillUpdata:在 shouldComponentUpdata 返回 true 确定要更新组件之前执行
  • ComponentDidUpdata:主要用于更新 DOM 以响应 props 或 state 更改
  • componentWillUnmount:用于取消任何的网络请求,或删除与组件关联的所有事件监听器

shouldComponentUpdate 是做什么的,(react 性能优化是哪个周期函数?)

  • shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新描绘 dom,因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中写出更优化的 dom diff 算法,可以极大的提高性能

应该在 React 组件的何处发起 ajax 请求

  • 在 react 组件中,应该在 componentDidMount 中发网络请求,这个方法会在组件第一次挂载时执行,在组件的生命周期中仅会执行一次。最重要的是,你不能保证组件挂载之前 ajax 请求已经完成,如果是这样,也就意味着你将尝试在一个未挂载的组件上调用 setState,这将不起作用,在 componentDidMount 中发网络请求将保证这有一个组件可以更新了

描述事件在 React 中的处理方式,(在 react 中如何处理事件)?

  • 为了解决浏览器的兼容性问题,SyntheticEvent 实例将被传递给事件处理函数。SyntheticEvent 是 react 跨浏览器的浏览器原生事件包装器,它还拥有和浏览器原生事件相同的接口,包括 stopPropagation()和 preventDefault()。

  • react 实际上并不将事件附加到子节点本身,react 使用单个事件侦听器侦听顶层所有事件,这对性能有好处,也意味着 react 在更新 dom 时不需要跟踪事件监听器

React 组件的划分业务组件技术组件?

  • 根据组件的职责通常把组件分为UI 组件容器组件

  • UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。

  • 两者通过React-Redux提供connect方法联系起来。

展示组件(Presentational component)和容器组件(Container component)之间有何不同?

  • 展示组件关心组件看起来是什么,展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只会关心 UI 状态而不是数据的状态。

  • 容器组件关心组件是如何运作的,容器组件会为展示组件或者其他容器组件提供数据和行为,他们会调用 Flux actions,并将其作为回调提供给展示组件,容器组件经常是有状态的,因为他们是(其它组件的)数据源。

描述 Flux 与 MVC?

  • 传统的 MVC 模式在分离数据(Model)、UI(View)和逻辑(Controller)方面工作得很好,但是 MVC 架构经常遇到两个主要问题:

    1. 数据流不够清晰:跨视图发生的级联更新常常会导致混乱的事件网络,难于调试
    2. 缺乏数据完整性:模型数据可以在任何地方发生突变,从而在整个 UI 中产生不可预测的结果
  • 使用Flux 模式的复杂用户界面

    1. 不再遭受级联更新
    2. 任何给定的 react 组件都能够根据 store 提供的数据重建其状态
    3. Flux 模式还通过限制对共享数据的直接访问来加强数据完整性

简述 Flux 思想?

  • Flux 的最大特点,就是数据的"单向流动"

    1. 用户访问 view
    2. view 发出用户的 action
    3. dispatch 收到 action,要求 store 进行相应的更新
    4. store 更新后,发出一个"change"事件
    5. view 收到"change"事件,更新页面

什么是高阶组件(Higher Order Component)?

  • 高阶组件是一个以组件为参数并返回一个新组件的函数。最常见的可能是 Redux 的connect 函数,connect 接收一个 function 作为参数,返回值表示当前组件中可以使用到的 redux 里面的数据。除了简单分享工具库,HOC 最好的方式是共享 React 组件之间的行为,如果你发现在不同的地方写了大量代码来做同一件事时,就应考虑将代码重构为可重用的 HOC。基本上,这是一个模式,是从 React 的组合特性中衍生出来的,称其为纯组件,因为它们可以接受任何动态提供的子组件,但不会修改或复制输入组件中的任何行为
const EnhancedComponent=higherOrderComponent(WrappedComponent);
  • HOC 可用于以下许多用例

    1. 代码重用、逻辑和引导抽象

    2. 渲染劫持

    3. state 抽象和操作

    4. props 处理

了解 redux 么,说一下 redux 吧?

  • redux 是一个应用数据流框架,主要解决了组件间状态共享的问题,原理是集中式管理,可以让数据更可控,react 中所有数据处理都在 redux 中进行,三个核心方法,action、store 和 reducer。

  • 在 redux 中遵循的原则

    1. 一个项目只能有一颗数据树。

    2. 所有的数据改变都需要在 reducer 中进行。

    3. 所有的 action 都是简单的对象。

    4. store 用来存储数据

  • redux 工作流程是:view 调用 store 的 dispatch 接收 action 传入的 store,reducer 进行 state 操作,view 通过 store 提供的 getState 获取最新的数据。

  • Flux 也是用来进行数据操作的,有四个组成部分,action、dispatch、view 和 store。

  • Flux 工作流程是:view 发出一个 action,派发器接收 action,让 store 进行数据更新,更新完成以后 store 发出 change,view 接受 change 更新视图。

  • Redux 和 Flux 很像,主要区别在于 Flux 有多个可以改变应用状态的 store,在 Flux 中 dispatch 被用来传递数据到注册的回调事件,但是在 redux 中只能定义一个可更新状态的 store、redux 把 store 和 dispatcher 合并,结构更加清晰简单。

  • 新增 state,对状态的管理更加明确,通过 redux 流程更加规范,减少手动编码量,提高了编码效率,同时缺点是当数据更新时,有时候组件不需要,但也要重新绘制,有些影响效率,一般情况下,我们在构建多交互,多数据流的复杂项目应用时才会使用它们。

redux 有什么缺点?

  1. 一个组件所需要的数据,必须由父组件传过来,而不能像 flux 中直接从 store 中取。
  2. 当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新 render,可能会有效率影响,或者需要写复杂的 shouldComponentUpdate 进行判断。

React 中的 StrictMode(严格模式)是什么?

  • react 的 StrictMode 是一种辅助组件,可以帮助咱们编写更好的 react 组件,可以使用包装一组组件,并且可以帮咱们以下检查

    1. 验证内部组件是否遵循某些推荐做法,如果没有,会在控制台给出警告
    2. 验证是否使用的已经废弃的方法,如果有,会在控制台给出警告
    3. 通过识别潜在的风险预防一些副作用

什么是 prop drilling,如何避免?

  • 在构建 react 应用程序时,在多层嵌套组件来使用另一个嵌套组件提供的数据,最简单的方法是将一个 prop 从每个组件一层层的传递下去,从源组件传递到深层嵌套组件,这就叫 prop drilling

  • prop drilling 的主要缺点是原本不需要数据的组件变得不必要的复杂,并且难以维护。

  • 为了避免 prop drilling,一种常用的方法是使用 React Context,通过定义提供数据的 Provider 组件,并允许嵌套的组件通过 Consumer 组件或 useContext Hook 使用上下文数据。通过 Provider 组件可以把 store 也就是整个 redux 和实例绑定

什么是 React Context?

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

如何避免组件的重新渲染?

  • React 中最常见的问题之一是组件不必要的重新渲染,React 提供了两个方法,非常有用:

    1. React.memo():这可以防止不必要地重新渲染函数组件
    2. PureComponent:这可以防止不必要地重新渲染类组件
  • 这两种方法都依赖于对传递组件的 props 的浅比较,如果 props 没有改变,那么组件将不会重新渲染,虽然这两种工具都非常有用,但是浅比较会带来额外的性能损失,因此如果使用不当,这两种方法都会对性能产生负面影响。

  • 通过使用 React Profiler,可以在使用这些方法前后对性能进行测量,从而确保通过进行给定的更改来实际改进性能

什么是 React Fiber?

  • Fiber 是 React16 中新的协调引擎或重新实现核心算法,它的主要目标是支持虚拟 DOM 的增量渲染

  • React Fiber 的目标是增强其在动画、布局和手势等领域的适用性,并为不同类型的更新分配优先级,以及新的并发原语。它的主要特性是增量渲染:能够将渲染工作分割成块,并将其分散到多个帧中。

在 React 中使用构造函数和 getInitialState 有什么区别?

  • 构造函数和 getInitialState 之间的区别就是 ES6 和 ES5 本身的区别,在使用 ES6 类时,应该在构造函数中初始化 state,并在使用 React.createClass 时定义 getInitialState 方法。
class MyComponent extends React.Component{
    constructor(props){
        super(props);
        this.state={/*initial state*/};
    }
}

等价于

const MyComponent==React.createClass({
    getInitialState(){
        return {/*initial state*/}
    }
})

如何有条件地向 React 组件添加属性?

  • 对于某些属性 react 非常聪明,如果传递给它的值是虚值,可以省略该属性,例如:
const InputComponent=React.createClass({
    render:function(){
        const required=true;
        const disabled=false;

        return(
            <input type="text" disabled={disabled} required={required} />
        )
    }
})

渲染结果:

            <input type="text" required />
  • 另一种可能的方法是:
    const condition = true;
    const component=(
        <div
         value="foo"
         {...(condition&&{disabled:true})}>
    )

createElement和cloneElement有什么区别?

  • React.createElement():JSX语法就是用React.createElement()来构建react元素的,它接收三个参数:
    1. 第一个参数可以是一个标签名,如div、span或者react组件;
    2. 第二个参数为传入的属性;
    3. 第三个以及之后的参数,皆为组件的子组件
React.createElement(
    type,
    [props],
    [...children]
)
  • React.cloneElement()与React.createElement()相似,不同的是它传入的第一个参数是一个react元素,而不是标签名或组件。新添加的属性会并入原有的属性,传入到返回的新元素中,而旧的子元素将被替换
React.cloneElement(
    element,
    [props],
    [...children]
)

React项目用过什么脚手架?

  • craet-react-app、Yeoman等

没想好题目…自定义属性.?

  • 当应用程序在开发者模式下运行时,react将自动检查咱们在组件设置的所由于性能影响而禁用它。有props,以确保它们具有正确的数据类型。对于不正确的类型,开发模式下会在控制台中生成警告消息,而在生产模式中由于性能影响而禁用它,强制的props用isRequired定义的。

e.g: 一组预定义的prop类型:
React.PropTypes.string
React.PropTypes.number
React.PropTypes.func
React.PropTypes.node
React.PropTypes.bool
例如,我们为用户组件定义了如下的propTypes

    import ProTypes from 'prop-types';

Class User extends React.Component{
    render(){
        return(
            <h1>Welcome,{this.props.name}</h1>
            <h2>Age,{this.props.age}</h2>
        )
    }
}

User.propTypes={
    name:PropTypes.string.isRequired,
    age:PropTypes.number.isRequired
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值