前端面试题

本文整理了一系列前端面试常见的技术问题,涵盖闭包、原型链、数据类型、排序算法、深浅拷贝、Vue组件生命周期、Promise、模块化、性能优化、跨域解决方案、Vue的this指向、VueX理解和VueRouter等多个方面,旨在帮助开发者巩固基础知识并了解面试重点。
摘要由CSDN通过智能技术生成

只是自己整理的一点点面试题,如果有补充或修改的可以在评论区发表,大家一起整理、一起学习

1. 闭包
1. 闭包是能够访问其他函数内部变量的函数。
2. 闭包一般会在封装模块的时候,通过函数自执行函数的方式进行实现;或者在模仿块级作用域的时候实现
3. 闭包的优点是:
    a、能够在离开函数之后继续访问该函数的变量,变量一直保存在内存中。
    b、闭包中的变量是私有的,只有闭包函数才有权限访问它。不会被外面的变量和方法给污染。
闭包的缺点是:
    a、会增加对内存的使用量,影响性能。
    b、不正确的使用闭包会造成内存泄漏。

2.原型链
 有限的实例对象和原型之间组成有限链,就是用来实现共享属性和继承的
继承的起点是 对象的原型(Object prototype)

3.数据类型
原始数据类型:string  number  undefined  null  boolean
引用数据类型:Object  array

4.冒泡排序
1、比较相邻的两个元素,如果前一个比后一个大,则交换位置。
2、比较完第一轮的时候,最后一个元素是最大的元素。
3、这时候最后一个元素是最大的,所以最后一个元素就不需要参与比较大小。

5.数组排序
冒泡排序法 选择排序法 插入排序法 快速排序法

6.深浅拷贝
假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,
那就是深拷贝,自食其力。
浅拷贝:
1)for···in只循环第一层  
2)Object.assign方法 
3)直接用=赋值
深拷贝:
1)递归去拷贝所有层级属性
2)通过JSON对象来实现深拷贝
3)通过jQuery的extend方法实现深拷贝
4)lodash函数库实现深拷贝
5)Reflect法
6)手动实现深拷贝
7)如果对象的value是基本类型的话,也可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象
8)用slice实现对数组的深拷贝
9)用concat实现对数组的深拷贝
10)直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。
11)使用扩展运算符实现深拷贝

7.this指向
a.如果是一般函数,this指向全局对象window;
b.在严格模式下"use strict",为undefined.
c.对象的方法里调用,this指向调用该方法的对象.
d.构造函数里的this,指向创建出来的实例.

8.跨域解决
跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。
1、 通过jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域
广义的跨域:
1.) 资源跳转: A链接、重定向、表单提交
2.) 资源嵌入: <link>、<script>、<img>、<frame>等dom标签,还有样式中background:url()、@font-face()等文件外链
3.) 脚本请求: js发起的ajax请求、dom和js对象的跨域操作等
同源策略/SOP(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

9.性能优化
1. 减少HTTP请求次数
2. 使用CDN
3. 避免空的src和href
4. 为文件头指定Expires
5. 使用gzip压缩内容
6. 把CSS和JS放到顶部
7. 避免使用CSS表达式
8. 将CSS和JS放到外部文件中
9. 权衡DNS查找次数
10. 精简CSS和JS
11. 避免跳转
12. 配置ETags

10.兼容性解决
1.不同浏览器的标签默认的外补丁和内补丁不同 
解决:*{margin:0;padding:0;}
2.块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大 
解决:在float的标签样式控制中加入 display:inline;将其转化为行内属性
3.设置较小高度标签(一般小于10px),在IE6,IE7,遨游中高度超出自己设置高度
解决:给超出高度的标签设置overflow:hidden;或者设置行高line-height 小于你设置的高度。
4.行内属性标签,设置display:block后采用float布局,又有横行的margin的情况,IE6间距bug
解决:在display:block;后面加入display:inline;display:table;
5.图片默认有间距
解决:使用float属性为img布局
6.标签最低高度设置min-height不兼容
解决:如果我们要设置一个标签的最小高度200px,需要进行的设置为:{min-height:200px; height:auto !important; height:200px; overflow:visible;}

11.vue生命周期
 vue每个组件都是独立的,每个组件都有一个属于它的生命周期,从一个组件创建、数据初始化、挂载、
更新、销毁,这就是一个组件所谓的生命周期。

12.传值方式
属性传值(props)
$refs
$parent
通知传值(广播传值)
本地传值
路由传值

13.计算属性和监听区别
  computed:
  1. computed 具有缓存功能,可以监听对象某个具体属性。
  2.变量不在 data中定义,而是定义在computed中。
  3.根据一个现有数据去生成一个新数据,并且这两个数据会永久的建立关系,还会建立缓存,
当无关数据改变的  时候,不会重新计算而是直接使用缓存中的值。
  watch:
  1.watch 监听的是已经在 data 中定义的变量, 当该变量变化时,会触发 watch 中的方法
  2.watcher,当需要在数据变化时执行异步或开销较大的操作时,这时watch是非常有用的
  3.watch可以进行深度监听,监听对象的变化。
  4.只能监听简单数据类型,如果监听复杂数据类型,如对象,无法监听对象具体某个属性。

14.数据双向绑定原理(vue的响应式)
  1.vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的,也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;
  2.核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法;
  3.介绍一下Object.defineProperty()方法
 (1)Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义其上属性的对象) prop (要定义或修改的属性) descriptor (具体的改变方法)
 (2)简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法

15.vuex理解
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
核心属性为:state,getter,mutation,action,module
 state:存储数据,存储状态;用 this.$store.state 来访问;对应vue里面的data;存放数据方式为响应式,
vue组件从store中读取数据,如数据发生变化,组件也会对应的更新。
 getters:可以认为是 store 的计算属性,相当于 vue中的 computed,依赖于 state里面的值。
 mutations:用于修改状态,store里面的数仅能通过mutations里面的方法改变,但是必须是同步的。更改 vuex 的 store 中的 状态的唯一方法是提交 mutation,也就是$store.commit。
 actions:包含任意异步操作,用它处理完后再触发mutations来改变状态。
 module:将 store 分割成模块,每个模块都具有state、mutation、action、getter、甚至是嵌套子模块。

16.keep-live
keep-alive是一个抽象组件:它自身不会渲染一个DOM元素,也不会出现在父组件链中;使用keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

17.nextick
 在下次DOM更新循环结束之后执行延迟回调,在修改数据之后立即执行这个方法,获取更新后的DOM

18.promise封装
Promise 是异步编程的一种解决方案
第一步是在函数内部构造一个 promise 实例,第二步是部署函数执行完去改变 promise 的状态为已完成,
第三步就是返回这个 promise 实例。每个 promise 实例都有3种状态,分别为 pending(未完成)、
resolved(已完成,成功)、rejected(已拒绝,失败)。

19.模块化理解
  a.模块化就是为了减少系统耦合度,提高高内聚,减少资源循环依赖,增强系统框架设计。
 b.让开发者便于维护,同时也让逻辑相同的部分可复用
 c.模块化开发:针对js、css,以功能或业务为单元组织代码。js方面解决独立作用域、依赖管理、
  api暴露、按需加载与执行、安全合并等问题,css方面解决依赖管理、组件内部样式管理等问题。

20.ajax原理
Ajax的工作原理相当于在用户和服务器之间加了—个中间层(AJAX引擎),使用户操作与服务器响应异步化。
并不是所有的用户请求都提交给服务器。像—些数据验证和数据处理等都交给Ajax引擎自己来做,,
只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求                                                     。

21.对象的深度监听
 vue中提供了在watch监听时设置deep:true 就可以实现对对象的深度监听;
 利用computed配合watch实现单个属性的深度监听;

22.在哪处理登录过期或错误信息
 在项目中src\utils目录下的request.js文件中进行处理

23.$route和$router区别
router是VueRouter的实例方法,相当于一个全局的路由器对象,作用是进行路由跳转的!
就像jQuery里的window.location一样,起到的是导航的作用。
route相当于当前激活的路由对象,包含当前url解析得到当前的路径、参数、query对象等。

24.怎样更改vuex里state的值
可以直接this.$store .state去赋值,但不建议,可以使用$store.commit。

25.var、let和cost的区别
var声明的变量会挂载在window上,而let和const声明的变量不会
var声明变量存在变量提升,let和const不存在变量提升
let和const声明形成块作用域,同一作用域下let和const不能声明同名变量,而var可以
const声明必须赋值,声明后不能修改,复合类型数据,可修改属性

26.数组的操作方法
 push()   向数组的尾部添加一个或多个的数据
 pop()      将数组尾部的数据删除4
 unshift()  向数组的头部添加一个或多个元素 
 shift()    删除数组头部元素
 splice( start length ) 表示从start位置处  删除  指定length的数据  start:就是下标  length :长度
 slice(start,end)  截取从start位置 到 end-1 位置处的数据     返回截取后的数据
 join(字符) 将数组中的数据通过 某个 字符 连接起来   返回一个字符串
 reverse()  数组的反转  返回的是反转后的数组(改变原数组)
 数组中的排序方法数组名.sort()当没有参数时,默认是按照  字符  进行  升序排序
 indexOf(参数)判断某个数据在数组中是否存在,如果存在就返回数组的下标  如果不存在就返回-1
 forEach()遍历数组  没有返回值
 filter() 过滤  返回满足某个条件的数组中的数据  返回值是一个数组
 map()映射 :  遍历数组---操作数组---返回数组
 reduce()归并   返回最后一次操作的结果    计算数组的和

27.es6理解
1.新增模板字符串(为JavaScript提供了简单的字符串插值功能)
2.箭头函数 (箭头函数继承而来的this指向永远不变)
3.for-of (用来遍历数据----例如数组中的值)
4.argument对象可被不定参数和默认参数完美代替
5.ES6将对象纳入规范,提供了原生的Promise对象
6.增加了let和const命令,用来声明变量
7.增加了块级作用域
(let命令实际就增加了块级作用域)
8.还有就是引入module模块的概念

28.vue-router有哪几种导航钩子
  全局导航钩子:router.beforeEach(to,from,next)
  组件内的钩子beforeRouteEnter (to, from, next) beforeRouteUpdate (to, from, next) beforeRouteLeave (to, from,   next)
  单独路由独享组件 beforeEnter: (to, from, next)

29.vue2和vue3区别
1.默认目录结构的变化
 vue-cli2.0与3.0在目录结构方面,有明显的不同
 vue-cli3.0移除了配置文件目录,config 和 build 文件夹
 同时移除了 static 静态文件夹,新增了 public 文件夹,打开层级目录还会发现, index.html 移动到 public 中
2.配置项
 3.0 config文件已经被移除,但是多了.env.production和env.development文件,除了文件位置,实际配置起来和2.0没什么不同
 没了config文件,跨域需要配置域名时,从config/index.js 挪到了vue.config.js中,配置方法不变
3.渲染
 Vue2.x使用的Virtual Dom实现的渲染
 Vue3.0不论是原生的html标签还是vue组件,他们都会通过h函数来判断,如果是原生html标签,在运行时直接通过Virtual Dom  来直接渲染,同样如果是组件会直接生成组件代码
4.数据监听
 Vue2.x大家都知道使用的是es5的object.defineproperties中getter和setter实现的,而vue3.0的版本,是基于Proxy进行监听的,其实基于proxy监听就是所谓的lazy by default,什么意思呢,就是只要你用到了才会监听,可以理解为‘按需监听’,官方给出的诠释是:速度加倍,同时内存占用还减半。
5.按需引入
 Vue2.x中new出的实例对象,所有的东西都在这个vue对象上,这样其实无论你用到还是没用到,都会跑一变。而vue3.0中可以 用ES module imports按需引入,如:keep-alive内置组件、v-model指令,等等。

  Vue 3 的 Template 支持多个根标签,Vue 2 不支持
  Vue 3 有 createApp(),而 Vue 2 的是 new Vue() createApp(组件),new Vue({template, render})
  v-model代替以前的v-model和.sync vue3中v-model的用法
  context.emit新增context.emit,与this.$emit(vue3中只能在methods里使用)作用相同

30.封装过哪些组件
 创建一个views目录和一个commen目录和一个feature目录,views目录中放页面级的组件,commen中放公共组件
(如:head(公共头组件),foot(公共底部组件)等),feature目录内放功能组件(如:swiper(轮播功能组件),
tabbar(切换功能组件)、list(上拉加载更多功能组件))
组件封装的大概过程:
使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。但是一般用脚手架开发项目,
每个 .vue单文件就是一个组件。在另一组件import 导入,并在components中注册,子组件需要数据,
可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

31、v-if和v-for为什么不建议同时用?
v-for比v-if优先级高,每一次都需要遍历整个数组,造成不必要的计算,影响性能,即使100个list中只需要使用一个
数据,也会循环整个数组
可以使用computed解决

32、vue-router的两种模式的区别?
hash模式:
  1.url路径会出现“#”号字符
  2.hash值不包括在Http请求中,它是交由前端路由处理,所以改变hash值时不会刷新页面,也不会向服务器发送请求,所以这也是单页面应用的必备。
  3.hash值的改变会触发hashchange事件
  4.当我们进行刷新操作,或者直接输入浏览器地址时,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了(刷新是网络请求,没有后端准备时会报错)。

history模式:
  1.history运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5中新增了pushState()和replaceState()方法,它们提供了对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会马上向后端发送请求。
  2.history的这种模式需要后台配置支持。比如:当我们进行项目的主页的时候,一切正常,可以访问,但是当我们刷新页面或者直接访问路径的时候就会返回404,那是因为在history模式下,只是动态的通过js操作window.history来改变浏览器地址栏里的路径,并没有发起http请求,但是当我直接在浏览器里输入这个地址的时候,就一定要对服务器发起http请求,但是这个目标在服务器上又不存在,所以会返回404
  3.hash路由支持低版本的浏览器,而history路由是HTML5新增的API
v-if和v-show的区别?
    1. v-show 只是简单的控制元素的 display 属性,而 v-if 才是条件渲染
(条件为真,元素将会被渲染,条件为假,元素会被销毁);
    2.  v-show 有更高的首次渲染开销,而 v-if 的首次渲染开销要小的多;
    3. v-if 有更高的切换开销,v-show 切换开销小;
    4. v-if 有配套的 v-else-if 和 v-else,而 v-show 没有
    5. v-if 可以搭配 template 使用,而 v-show 不行

33、vue 路由传参 query 和 params 的区别?
 1. query要用path来引入,params要用name来引入,接收参数都是类似的,分别是this.$route.query.path和
this.$route.params.name。
接收参数的时候,已经是$route而不是$router
2. query更加类似于我们ajax中get传参,params则类似于post,前者在浏览器地址栏中显示参数,后者则不显示
3. params是路由的一部分,必须要有。query是拼接在url后面的参数,没有也没关系。
4. params、query不设置也可以传参,params不设置的时候,刷新页面或者返回参数会丢失

34、vue中的父组件及子组件生命周期的执行顺序:
父组件created→父组件beforeMounted→子组件created→子组件beforeMounted→子组件mounted→父组件mounted;


35、vue中的data为什么要写成函数:
1).是为了在重复创建实例的时候避免共享同一数据造成的数据污染  
2).写函数的原因是为了保证这个对象是独立的,如果可以保证对象是惟一的,也可以不写函数直接写对象。


36 、虚拟DOM和真实DOM的区别?
(1)虚拟DOM不会进行排版与重绘操作,虚拟DOM就是把真实DOM转换为Javascript代码
(2)真实DOM频繁排版与重绘的效率是相当低的
(3)虚拟DOM进行频繁修改,然后一次性比较并修改真实DOM中需要改的部分
总之,一切为了减弱频繁的大面积重绘引发的性能问题,不同框架不一定需要虚拟DOM,
关键看框架是否频繁会引发大面积的DOM操作

37、 vue中 key 值的作用
用于管理可复用的元素。因为Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从
头开始渲染。这么做使 Vue 变得非常快,但是这样也不总是符合实际需求。

38、什么是防抖?
防抖:用户触发事件过于频繁,只要最后一次事件的操作。
这里用input模拟一下发送请求,从下面动图可以看出我们仅仅输入四个字,就触发了几十次事件,如果说我每一次输入都和后台进行数据交互,那么将会很影响计算机的性能。
解决方法:
<script>
        var inp = document.querySelector('input')
        var timer = null
        inp.oninput = function () {
            clearTimeout(timer)
 
            timer = setTimeout(() => {
                console.log(inp.value);
            }, 500);
        }
    </script>
这里我们定义了一个timer=null 在每次执行oninput函数时先清空定时器,然后通过timer接收定时器,时间设置在500ms。(时间的话可以自己定)
也就是说在500ms内触发的定时器都被清除,只触发最后一次。当间隔时间超过500ms时才触发函数。      

39、什么是节流?
节流:控制高频事件的执行次数(事件频繁触发时,每隔多少秒触发一次)比如说监视滚动条高度。
解决方法:<script>
        var flag = true
        window.onscroll = function () {
            if (flag) {
                flag = false
                console.log('滚动条动了');
 
                setTimeout(() => {
                    flag = true
                }, 500);
            }
 
 
        }
    </script>
这里添加了一个节流阀flag,在进入时判断flag是否为真,进入后立马将阀门关闭(flag=false)然后通过定时器控制在500ms后开起阀门,实现在500ms内的事件只触发一次

40、什么是解构赋值?
解构赋值是对赋值运算符的扩展。它是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。

41、ajax的请求方式有哪些?
A、get:一般应用于从服务器获取数据(给服务器的数据少,从服务器拿的数据多),一般使用URL问号传参的方式向服务器传递内容,会限制大小、不安全、会出现缓存问题,如果想清除缓存的话就加个随机数参数,
B、post:一般应用于向服务器推送数据(给服务器的多,从服务器拿下来的少),一般使用请求主体的方式向服务器传递内容
C、put:一般应用于给服务器上增加资源文件(上传图片功能),向服务器传输内容方式与POST一致
D、DELETE:一般应用于从服务器上删除资源文件,向服务器传输内容方式与get一致
E、HEAD:一般应用于只获取服务器的响应头信息,向服务器传输内容方式与get一致

42、localstorage和sessionstage还有cookie的区别?
localstorage:localStorage的生命周期是永久的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据,否则数据永远不会消失。保存数据大小5MB。常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据
**作用域:**相同浏览器的不同标签在同源情况下可以共享localStorage
sessionstage:仅在当前会话下起作用,只要关闭当前浏览器就会被销毁。保存数据大小5MB。敏感账号一次性登录;
cookie:大小受限单个cookie保存的数据不能超过4kb。安全性较低。每次访问都要传送cookie给服务器,浪费带宽。生命周期随浏览器的关闭而结束。如果在浏览器中设置了cookie的过期时间,cookie被保存在硬盘中,关闭浏览器后,cookie数据仍然存在,直到过期时间结束才消失。

移动端面试题:::::

1 请谈谈微信小程序主要目录和文件的作用?
project.config.json 项目配置文件,用得最多的就是配置是否开启https校验;
App.js 设置一些全局的基础数据等;
App.json 底部tab, 标题栏和路由等设置;
App.wxss 公共样式,引入iconfont等;
pages 里面包含一个个具体的页面;
index.json (配置当前页面标题和引入组件等);
index.wxml (页面结构);
index.wxss (页面样式表);
index.js (页面的逻辑,请求和数据处理等);

2 请谈谈wxml与标准的html的异同?
都是用来描述页面的结构;
都由标签、属性等构成;
标签名字不一样,且小程序标签更少,单一标签更多;
多了一些 wx:if 这样的属性以及 {{ }} 这样的表达式
WXML仅能在微信小程序开发者工具中预览,而HTML可以在浏览器内预览
组件封装不同, WXML对组件进行了重新封装,
小程序运行在JS Core内,没有DOM树和window对象,小程序中无法使用window对象和document对象。

3 请谈谈WXSS和CSS的异同?
都是用来描述页面的样子;
WXSS 具有 CSS 大部分的特性,也做了一些扩充和修改;
WXSS新增了尺寸单位,WXSS 在底层支持新的尺寸单位 rpx;
WXSS 仅支持部分 CSS 选择器;
WXSS 提供全局样式与局部样式

4 你是怎么封装微信小程序的数据请求的?
在根目录下创建utils目录及api.js文件和apiConfig.js文件;
在apiConfig.js 封装基础的get, post 和 put, upload等请求方法,设置请求体,带上token和异常处理等;
在api中引入apiConfig.js封装好的请求方法,根据页面数据请求的urls, 设置对应的方法并导出;
在具体的页面中导入;

5 小程序页面间有哪些传递数据的方法?
使用全局变量实现数据传递
页面跳转或重定向时,使用url带参数传递数据
使用组件模板 template传递参数
使用缓存传递参数
使用数据库传递数据

6 请谈谈小程序的双向绑定和vue的异同?
大体相同,但小程序直接this.data的属性是不可以同步到视图的,必须调用this.setData()方法!

7 请谈谈小程序的生命周期函数?
onLoad() 页面加载时触发,只会调用一次,可获取当前页面路径中的参数。
onShow() 页面显示/切入前台时触发,一般用来发送数据请求;
onReady() 页面初次渲染完成时触发, 只会调用一次,代表页面已可和视图层进行交互。
onHide() 页面隐藏/切入后台时触发, 如底部 tab 切换到其他页面或小程序切入后台等。
onUnload() 页面卸载时触发,如redirectTo或navigateBack到其他页面时。

8 简述微信小程序原理?
小程序本质就是一个单页面应用,所有的页面渲染和事件处理,都在一个页面内进行,但又可以通过微信客户端调用原生的各种接口;
它的架构,是数据驱动的架构模式,它的UI和数据是分离的,所有的页面更新,都需要通过对数据的更改来实现;
它从技术讲和现有的前端开发差不多,采用JavaScript、WXML、WXSS三种技术进行开发;
功能可分为webview和appService两个部分;
webview用来展现UI,appService有来处理业务逻辑、数据及接口调用;
两个部分在两个进程中运行,通过系统层JSBridge实现通信,实现UI的渲染、事件的处理等。

9 请谈谈原生开发小程序、wepy、mpvue 的对比?
如果是新项目,且没有旧的 h5 项目迁移,则考虑用小程序原生开发,好处是相比于第三方框架,坑少。
而如果有 老的 h5 项目是 vue 开发 或者 也有 h5 项目也需要小程序开发,则比较适合 wepy 或者 mpvue 来做迁移或者开发,近期看wepy几乎不更新了,所以推荐美团的mpvue。
而如果团队前端强大,自己做一套框架也没问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值