2020最全的前端面试大全

一、HTML和CSS

1、css动画实现:

animation(动画):keyframes提供了更多的控制;可以指定播放次数或是无限循环;可以定义动画的中间状态

transition(过渡):需要事件来触发;是一次性的,不能重复发生;只能定义开始和结束状态,不能自定义中间状态;

transform(变形):元素的缩放、旋转、移动和倾斜

translate(移动):transform的移动属性

2、移动端自适应方案:

1)rem:相对于根元素的字体大小单位,em是相对于父级元素字体大小的单位,flexible

2)vw:postcss-px-to-viewport可以自动转换vw

3)媒体查询:处理特定状态

4)<meta content="width=device-width,initial-scal=1.0,maximum-scale=1.0,user-scalable=0;" name="viewpott" />

没有设置viewport会出现:网页被缩小,字体很丑,排版错乱;有了viewport能通过缩放让浏览器完全显示整个网页

3、垂直居中:line-height+text-align;absolute+transform;flex+aligin-items+justify-content;table-cell

4、flex都有哪些属性:flex-direction主轴方向、flex-wrap换行、justify-content主轴对其方式(flex-start/flex-end/center/space-between/space-around)、align-items交叉轴对齐方式、align-content多根轴线对齐方式

5、选择器优先级:!import>内联样式>id选择器>class选择器>tag选择器>*(通配符)>继承>默认

伪类选择器::link>:visited>:focus>:hover>:active fist-of-type、last-of-type、only-of-type、only-child、nth-child、:enable、:disable、:checked

6、link和import的区别:

1)link是html标签,不仅可以加载css,还可以定义rss、rel等属性,import是css导入样式的方法;

2)link标签引入的css同时加载,import引入的css在页面加载完毕之后加载

3)link可以使用js来动态引入,import不行

7、SVG和Canvas:svg是使用xml描述2d图形,canvas是通过js来绘制2d图形的

8、盒子模型:宽度=content+padding+border+margin

9、position的值有哪些?static(文档流)relative(相对定位)absolute(绝对定位:不为static的父级元素)fixed(固定定位:可视窗口)

10、绘制三角形的原理:把高度和宽度设置为0,然后设置边框样式

11、display有哪些参数?block(块显示)inline-block(行内)none(隐藏)inline(内联-行内)table(表格显示)list-item(项目列表)

12、行内元素和块级元素有啥区别?行内元素只有左右的margin和padding,不能设置宽和高,宽高取决于内部内容;块级元素允许设置宽高,padding、margin,但不允许左右存在其他元素

13、H5新特性?

1)语义化标签?常见语义化标签:h1-h6、p、header、title、footer、nav、section、article、table、ul、dt、strong;有利于不同设备解析(盲人阅读器),区分哪些优先阅读;有利于搜索引擎的抓取;有利于团队的开发维护;

2)新表单类型:input新增type:email、number、url、range、search、color、tel、date;新增属性:min、max、autofocus、multiple、required、pattern

3)视频和音频:<video><audio>

4)canvas绘图和svg矢量图形

14、h5网页怎么显示真实的1px边框和12px字体大小?

1)使用box-shodow来模拟边框:但是会有阴影颜色变浅

2)背景色渐变,一半有颜色一半设置透明

3)伪类+transform:用before或after做border,并transform的scale缩小一半

15、三栏布局实现方式:

1)float:left;float:right;margin-left,margin-right(main标签最后加载)

2)BFC:float:left;float:right;overflow:hidden(main标签最后加载)

3)外层设置display:table,width:100%;内部标签设置display:table-cell

4)绝对定位:左右设置absolute,中间的设置margin

16、BFC:块级格式上下文,是页面上一个独立的容器,容器中的子元素不会影响到外面元素;

二、JS

1、高阶函数:函数可以作为参数传递;函数可以作为返回值输出

2、闭包?:

函数执行作用域内的变量,被另一个作用域引用,造成该变量不能在函数执行后销毁,就形成了闭包

使用场景:原生的setTimeout传递的第一个函数无法带参数,可以利用闭包实现传参;回调、事件绑定;封装私有变量

3、作用域:执行上下文中声明的变量和声明的作用范围,分为块级作用域和函数作用域

4、isNAN、escape、 eval 、 parseFloat等js系统方法总结

5、js数据类型

基础数据类型:undefined、null、number、boolean、string

object(引用类型)中还包括:array、function、date、regExp、error、arguments对象

基础类型和引用类型的区别:一个存在堆内存,一个在栈内存;一个是值的引用,一个是地址

typeof 能检测除了null以外的数据类型,null时返回object,除了function能返回function以外,其他都返回object

Object.prototype.toString.call() 能检测所有类型

强制类型转换:

String()、Number()、Boolean()、parseInt()

一元加减操作符等同于Number();加法操作符如果一个字符串一个数字,会合成字符串;非与或;相等和不相等;全等和不全等;关系操作符

6、proxy理解:代理,new Proxy(target,handler)当代理对象中的某个值被访问或是更新就会触发相应的get和set方法

7、js继承方式:原型链继承、构造函数继承、组合继承

8、node的事件方法:emitter.addListener() emitter.emit() emitter.on() emitter.removeListener()

9、Promise:用于解决回调地狱,用于处理异步编程:new Promise().then().then().catch();

状态值:pending(等待中)fulfilled(已完成)rejected(已拒绝)

async/await也是基于promise实现的

generator:yield暂停代码,next()继续执行代码

三兄弟:promise.all()全部完成输出完成,一个拒绝直接输出拒绝; promise.race()一个完成或拒绝就输出结果;promise.allSettled()所有的完成或决绝的结果对应输出

promise和settimeout有什么区别 => this.$nexttick

settimeout还是最后,因为本质上讲settimeout反回的异步函数,是一个全新的任务队列,就必须等待之前的所有任务队列全部执行完毕才会执行,所以总体来讲,三个中settimeout性能最差,会导致2次浏览器重绘

console.log(1);
setTimeout(()=>{
console.log(2)
},100)
Promise.resolve().then(()=>{
console.log(3);
})
console.log(4)

10、函数防抖和节流:持续触发事件resize、scroll、mousemove避免频繁执行函数

防抖debounce:触发事件后在n秒内函数只能执行一次

节流throttle:连续触发事件但是n秒内只执行一次,停止触发事件还会再执行一次;时间戳版和定时器版

11、如何理解原型和原型链?构造函数是什么?

每个对象在创建的时候就会与之关联的另一个对象,这个对象就是原型,每一个对象都会从原型继承属性;原型链就是由相互关联的原型组成的链状结构;

每一个构造函数都有一个prototype指针指向他的原型,构造函数被实例化之后具有一个proto属性指向构造函数的原型

构造函数constructor本身就是一个函数,用于创建对象,使用new来生成实例(使用instanceof来确认实例与原型的继承关系)

12、this、apply、call、bind:改变this指向

this永远指向最后调用它的那个对象,匿名函数的this永远指向window,vue中的this指向Vue实例

改变this指向的方法:箭头函数:this始终指向函数定义时的this,而不是执行时;函数内部使用let _this = this;

apply和call类似,传入参数不同,apply是数组,call是参数列表;bind是创建一个新的函数,需要手动调用

13、this指向问题?在严格模式和非严格模式的区别?

1)全局作用域下的this:都指向window;

2)全局作用域下函数中的this:严格模式指向undefined,非严格模式指向window;箭头函数都指向window;

3)对象中的函数中的this:指向调用这个函数的对象

4)构造函数中的this:指向实例对象

5)事件处理中的this:指向触发事件的目标对象

13、es中新类型symbol:1)作为对象属性的唯一标识符,防止对象属性发生冲突,避免在属性名相等的时候发生属性覆盖:[Symbol('name')]: ''; Object.getOwnPropertySymbols(target);2)用来代替常量,const TYPE_1 = Symbol();3)定义类的私有属性/方法

14、js设计模式:

1)构造函数模式:用构造函数来生成对象

2)工厂模式:jquery中的$选择器就是工厂模式创建的

3)单例模式:一个类智能创建一个实例,比如vuex和redux中的store

4)代理模式:proxy对象拦截操作

5)观察者模式:vue响应式,eventEmitter

6)适配器模式:实现兼容性

7)装饰器模式:为对象添加新功能,不改变原有的结构和功能,将函数的核心功能和装饰功能区分开

8)迭代器模式:ES6中的Map、Set等,for...of

9)外观模式:封装一个统一的事件处理中心

10)状态模式:state、promise

11)命令模式:将请求封装成一个对象

15、深拷贝(对象):JSON.parse(JSON.stringify(obj));递归赋值,js里的变量永远是值传递,只有对象的引用才会有深拷贝问题

16、new:新生成一个对象;链接到原型;绑定this;返回return中的值

17、变量提升?函数声明可以被提升,赋值变量后的函数没有被提升

18、require和import的区别

require运行时加载,可以运用在代码任何地方;import编译时加载,效率更高,不一定要写在开头,具有提升效果;

require遵循commonjs,本质是赋值过程,输入时必须查找对象属性;import遵循es6,本质是解构过程;require实际是加载了整个模块,然后从模块中读取某个方法,而import是加载了需要的方法,其他的不加载

19、let、var、const

let/const块级作用域,暂存死区(不存在变量提升),不允许重复声明

const一旦声明必须赋值(也可以用symbol赋值),不能用null占位,声明后不能再修改,如果声明的是复合类型数据,可以修改其属性

20、js严格模式:

1)不允许给没有声明的变量赋值,不能对变量调用delete,不能使用标识符做变量名

2)不允许给只读对象属性赋值,不可配置属性不能使用delete,不可扩展的对象不能添加属性,属性名必须唯一

3)命名函数的参数必须唯一,函数参数与arguments独立,只能在脚本顶级和函数内部声明函数,if语句中不能声明

4)eval()在包含上下文中不再创建变量或函数

5)抑制this,严格模式下的this始终指向指定的值

21、柯里化:首先填充几个参数,再返回一个新的函数,为函数预置通用参数

const add = function add(x) {
	return function (y) {
		return x + y
	}
}
const add1 = add(1)
add1(2) === 3
add1(20) === 21

22、数组操作:map、forEach、filter、some(或)、every(与)、join(连接字符串)、push/pop(末尾入)、unshift/shift(头部入)、sort/reverse(排序/翻转,改变原数组)、

contact(连接数组,不影响原数组)、slice(start,end)返回截断后的新数组,不改变原数组、splice(start,number,value)返回删除元素组成的数组,value为插入项,改变原数组

indexOf/lastIndexOf(查找数组项,放回对应下标)、reduce/reduceRight(求和)、flat(数组扁平化,多维数组-》一维数组)

数组乱序:arr.sort(()=>{return Math.random() - 0.5})

23、函数声明和函数表达式的区别?函数声明在js解析时可以函数提升,函数表达式只能在赋值之后才能使用

24、事件委托是什么?利用事件流的冒泡特性把子节点的事件绑定父节点上,然后回调里面使用事件对象进行区分;可以利用一个事件处理程序来完成某一类型的所有事件;减少内存消耗,减少dom操作

26、js加载位置:

三、VUE

  1. MVVM的理解:Model-View-ViewModel数据驱动视图:双向数据绑定 (MVC-Model-View-Controller)单向通信
  2. vue生命周期:beforeCreate、created(完成provide/inject和状态的初始化)、beforeUpdate、updated、beforeMount、mounted(将render函数转化为vnode,创建真实dom)、activated(被keep-alive包裹的组件,created和mounted不会被触发)、deactivated(离开当前激活的组件)、beforeDestory、destoryed
  3. vue双向绑定原理--js实现双向绑定:主要是通过object对象的defineProperty属性,重写data的setter和getter函数,在get函数中更改原数据,在set函数中更改视图
  4. 输入框内容变化,data数据变化,view=》model;data数据变化,显示文本变化,model=》view;相当于getter、setter
  5. vue组件间通讯:props/$emit;eventBus($on/$emit/$off);vuex;provide/inject(跨组件通信);slot插槽;ref;
  6. computed和watch:computed是计算属性,更多用于计算值的场景,在getter执行后会缓存;watch更多是观察作用,用于观察props $emit或本组件的值,当数据变化时执行后续操作,无缓存性,页面重新渲染时值不变化也会执行
  7. vue动态组件:<component :is= />
  8. vue动态路由实现:router.addRoutes() 路由传参:/:id query:{} params:{}
  9. keep-alive工作原理:用于保存组件的渲染状态,避免组件反复创建和渲染;通常用于动态组件和router,include定义缓存白名单,exclude定义缓存黑名单,max定义缓存组件上限
  10. vue-router钩子函数:beforeEach()全局前置守卫,进入路由之前调用;afterEach()全局后置守卫,进入路由之后调用;beforeResolve()全局解析守卫;
  11. vuex使用:组件通过dispatch一个action,action通过commit一个mutation,mutation来改变state,最后重新执行render生成新的vnode,刷新组件
  12. action和mutation的区别:mutation是同步函数,action是异步函数,mutation是修改state的唯一途径,action不进行状态的直接更改,而是通过commit触发mutation,可以同时提交多个mutation
  13. dom在哪个vue的生命周期渲染完成的?
  14. 如何解决修改数据页面不刷新的问题?为何出现该问题? this.$set,vue.js无法检测到对象属性的增加和修改,vue在初始化实例时将对象属性转化为getter/setter,所以属性必须在data对象上才能让vue.js转化它
  15. vue中的template如何理解?
  16. axios和ajax的区别
  17. ajax是针对MVC编程,不符合现在MVVM潮流;axios是promise的实现版本,符合es规范,提供了一些并发请求接口
  18. nextTick: 在下次dom更新循环结束之后再执行

四、React

1、react的优点:

1)遵循从上到下的单向响应数据流,减少重复代码;

2)使用虚拟DOM来更新真正的dom,减少DOM操作成本,提高效率;

3)JSX语法(对es支撑很友好)

2、react如何获取真正的dom:ReactDOM.findDOMNode()或this.$refs

3、react生命周期:

1)设置默认属性defaultProps;2)设置初始化状态state;3)componentWillMount()组件即将被渲染;4)render()组件渲染;

5)componentDidMount()组件渲染后触发,此时有了真正的Dom;6)componentWillReceiveProps()组件接受到属性;

7)shouldComponentUpdate()组件接收到新属性或状态改变时触发;8)componentWillUpdate()组件即将被更新;

9)componentDidUpdate()组件更新完成,页面产生新的dom;10)componentWillUnmount()组件销毁时触发;

4、react组件是通过什么去判断是否刷新的:通过判断state是否变化

5、bind函数的位置:写在render方法里会导致组件状态变更时重复触发bind函数的执行,严重影响性能;写在constructor中仅在组件初始化时调用,绑定自身作用域,缺点是每个事件都要绑定一次,写起来比较麻烦

6、虚拟dom:用js这种抽象化的方式来渲染dom树结构,实现了跨平台的能力;其核心是diff算法,减少了js操作真实dom所带来的性能消耗

7、diff算法:对比新老dom的变化,将变化的部分更新到视图中;遍历虚拟dom,对比节点的属性及子节点,只修改变化的地方,其他的保持不变;

8、key值:作用是给每个节点做唯一标识,使得diff算法能够正确识别节点并对其进行更新操作,可以更高效的更新虚拟dom;不推荐用index下标来表示key值,在数组中间追加元素时会导致后面的节点都重新渲染,最好使用id来作为唯一标识

9、react-router:BrowserRouter和HashRouter都会创建history对象,项目中有服务器的web请求我们就用的BrowserRouter

用<Switch>组件将多个<Route>包裹在一起用于渲染第一个路径匹配的route

标签渲染<Link to="/" >Home</Link> 重定向<Redirect to="/index" />

10、redux:react状态管理机制,将数据统一存储在store状态树中,组件通过调用dispatch方法触发一个action来更新store树,其他组件可以通过订阅store中的状态值来刷新视图

核心:provider:顶级组件来存放store,使得所有组件都可以在redux的控制下;connect:mapStateToProps将redux的值映射到props中,mapDispatchToProps将dispatch变成props直接使用

11、react组件通信:自上而下单向数据流,一层一层传递props,不需要props的就有context来实现数据共享,定义全局数据

1)props:利用props获取父组件方法直接调用

2)context:利用React.createContext()创建全局可以访问的值,使用provider和customer模式,在顶层的provider中传入value

3)eventEmitter:可以引入events包,通过注册事件和触发事件来实现通信new EventEmitter();addListener();removeListener();

4)路由传参:params:this.props.match.params.(刷新页面不会丢失)query:this.props.location.query.(刷新丢失,可传对象)

state:this.props.location.query.state.(Hash中刷新页面丢失,可传对象)search:this.props.location.search

5)onRef:通过props机制将组件的this实例当做参数传到父组件,父组件就可以操作子组件的方法和state

6)ref:通过ref属性获取整个子组件实例进行操作

7)redux

8)Mobx

9)flux

10)hooks:使用userReducer和context实现通讯,核心action,reducer,types

11)slot:将父组件的标签传递给子组件,子组件使用this.props.slot来获取内容

12、flux思想: 单向数据流

用户访问view;view发出用户的action;dispatcher收到action,要求store进行更新;store更新后,发出一个change事件;view收到change事件后更新页面

13、vue和react的虚拟dom有啥区别?

react和vue的虚拟dom都是一样的,都是用js对象来模拟真实dom,然后用虚拟dom的diff来最小化更新真实dom,唯一的区别是react采用的是自上而下的全量diff,vue采用的是局部订阅的模式

 

vue和react的区别:

1、虚拟dom不同:react采用的是自上而下的全量diff,vue采用的是局部订阅的模式

2、数据流:react是自上而下单向数据流,需要用setState方式去更新状态,vue双向数据绑定

3、模板渲染方式不同:react通过jsx来渲染,vue是使用html语法,通过指令v-if、v-for来渲染。在引入模板引入中,react中import的组件可以在render中直接使用,vue还需要在components中声明

4、react本身是严格的view层,MVC模式,vue是MVVM模式

五、浏览器和Http

1、cookie、sessionStorage、localStorage的区别

cookie常用于存储用户身份,登录状态等,http中自动携带,体积上限位4K,可自行设置过期时间

localStorage/sessionStorage:长久存储/窗口关闭删除,体积5M,不与服务端通信,两者只有存储期限不同,local除非手动清除否则永久保存,session页面关闭后被清除

2、各大浏览器内核:Trident(IE)、Webkit(Chrome/Safari)、Gecko(Mozilla/Firefox)、Presto()

3、web性能优化方向:

1)降低请求量(减少http请求次数,图片文件压缩,资源懒加载,按需加载,使用base64图片);

2)加快请求速度(并行加载,CDN分发);

3)缓存(离线数据缓存在localStorage中);

4)渲染(JS/CSS加载顺序优化,css放在最上面,js放在body的最下面);

5)事件节流,减少dom操作,避免回流

6)减少cookie使用,减少请求携带的大小

4、http和https的区别:https比http多了一层SSL协议,用于加密,http明文传输,无状态连接;https加密传输且身份认证,需要ca证书;http端口80,https端口443

5、301.302.303重定向

6、浏览器垃圾回收和内存泄漏:垃圾回收就是定期找出不继续使用的变量释放内存;

闭包导致父级中的变量无法被释放;定时器未正确关闭导致引用的外部变量无法被释放,事件监听没有被正确销毁;dom元素被删除时,内存中对dom的引用没有被清除;没有声明的变量无法回收

7、浏览器渲染页面流程:浏览器从请求到加载一个页面:DNS查询(域名解析:域名解析成ip地址)、TCP连接、HTTP请求响应、服务器响应、客户端渲染

客户端渲染的过程:处理html构建dom树;处理css构建css树;将dom树和css树合并渲染树;布局;绘制页面

8、浏览器事件流:

捕获(事件从window对象到document对象再到html标签一层层传到目标元素)、目标、冒泡(捕获的逆过程)

9、重绘和重排:重绘是重新绘制受影响的部分;重排是重新生成布局;重排一定会导致重绘;

触发重绘重排:dom节点的增删改;dom节点隐藏;dom节点的移动或添加动画;调整样式属性;用户调整窗口大小,滚动等操作

10、dom2事件绑定:可以添加多个处理函数,可以用addEventListener和removeEventListener来绑定和解绑事件

11、浏览器缓存:浏览器缓存基本是get方法

浏览器请求与缓存的关系流:是否有缓存、判断缓存是否过期、判断最后修改的时间

强制缓存:cache-control(no-cache不能缓存;public;private),expires

协商缓存:lastModified

12、websocket:实现客户端和远程服务端的全双工通信;http是应用层协议,封装解析传输的数据;socket不是协议,是对TCP的接口封装,是传输通道两端的接口;websocket是个持久化的协议,服务端可以主动push;new WebSocket(url); ws.onerror = fn; ws.onclose = fn; ws.onopen = fn; ws.onmessage = fn; ws.send()

13、http请求方式:GET获取资源;POST传输数据;PUT传输文件;DELETE删除资源;HEAD获得报文首部;OPTIONS询问支持的方法

15、get和post区别:get缓存、请求长度受限,会被历史保存记录;post安全、大数据、更多编码类型

16、浏览器安全:同源策略(要求域名协议端口都相同),XSS注入攻击(转义html、过滤script标签),跨域请求伪造csrf(增加用户登录授权)

17、跨浏览器、跨终端?浏览器兼容:css样式、事件触发,响应式开发:媒体查询,多套css样式

18、前端架构?可访问性?可维护性?

1)创建gitlab和git flow工作流进行版本管理;2)埋点系统:记录页面访问量,捕捉报错等;3)使用ESlint:统一代码风格,减少低级bug,增加可阅读性和可维护性;4)Mock数据;

5)基础组件封装;6)公共样式库,统一UI风格;7)权限管理,路由守卫,单点登录;8)请求拦截

19、hash和history的区别?hash不会被包含在http请求中,对后端完全没有影响,改变hash不会重新加载页面,只要#号前面的内容正确,就不会返回404错误;history需要服务端做完整的匹配,不然就会出现404错误

20、前端处理跨域问题?配置反向代理:在vue.config.js文件中配置proxyTable、jsonp原理,cors、iframe,postMessage....

module.exports = { 
    devServer: { 
        proxy: {
             "/api": { 
                 target: "http://typhoon.zjwater.gov.cn", //设置调用的接口域名和端口 
                 changeOrigin: true, //是否跨域 
                 ws:true,  // 是否启用websocket
                 pathRewrite: { "^/api": "" } } } } } // 使用/api来代替target里面的地址

Webpack:

1、常用的loader:eslint-loader、url-loader、postcss-loader、style-loader、css-loader、sass-loader、file-loader、babel-loader、

2、基本功能及工作原理:代码转换:编译ts/es,scss;文件优化:压缩js、css代码,压缩图片;代码分割,异步加载;代码校验:代码规范校验,单元测试;

3、打包原理:将所有依赖打包成一个bundle.js,通过代码分割按需加载

4、entry:告诉webpack使用哪个模块作为构建项目的起点;output:告诉webpack在哪里输出它打包好的代码及如何命名

5、常用plugins:html-webpack-plugins(压缩html)clean-webpack-plugins(打包器清理dist目录)

6、babel:将es6代码编译成AST(抽象语法树)

canvas使用:

1、转换图片格式

function getImgToBase64(url, callback){
  let canvas = document.createElement('canvas');
  let ctx = canvas.getContext('2d');
  let img = new Image;
  img.crossOrigin = 'Anonymous';
  img.onload = function(){
    canvas.height = img.height;
    canvas.width = img.width;
    ctx.drawImage(img,0,0);
    var dataURL = canvas.toDataURL('image/jpg');     callback(dataURL);
    canvas = null;
  };
  img.src = url;
}

数组操作:

1、数组去重:Array.from(new Set([1,2,3,2,1]))或 [...new Set([1,2,3,2,1])]

2、替换数组中的元素:splice(atart, countToRemove, valueToAdd)

3、清空数组:直接将数组的长度设为0

4、获取数组中某个键值映射: arr.values() 或 Array.from(arr, ({name})=>name)

5、填充数组:let arr = new Array(10).fill(1)

6、合并数组:[...arr1, ...arr2] contact

7、两个数组的交集:[...new Set(arr1)].filter(el => arr2.includes(el))

8、删除假值:arr.filter(Boolean) 假值为:null,undefined,false,0,NAN,“”

9、从数组中获取随机值:arr[Math.floor(Math.random() * (arr.length))]

10、数组翻转:arr.reverse()

11、查找元素最后一次出现的索引:arr.lastIndexOf(1)

12、数组中所有元素相加:arr.reduce((x, y) => x+y)

 

Angular、vue、react对比:

angluar:比较完善,自带了丰富的指令,包含模板,数据双向绑定,过滤器,依赖注入等功能,对es6兼容不是很好,需要手写jq来解决某些问题,

vue:轻量级,支持双向数据绑定,不支持IE8

react:声明范式,操作虚拟DOM,单向数据流,

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值