HarmonyOS面试宝典:25年最新面试题合计(算比较全的了 记得点个关注)
🐝 重要出现频率高
■ 基础
鸿蒙基于前端的typescript所以也会问到 当然还有很多 这里列举了较为频率高的。
CSS选择器 🐝
CSS选择器优先级
权重顺序: !important > 行内样式 > ID > 类、伪类、属性 > 标签 > 通配符 > 继承 > 浏览器默认属性
权重大小
CSS3新特性 🐝
属性选择器选择器
圆角
阴影
渐变
多列布局
css自定艺术性
等等
谈谈你对盒模型的理解 🐝
问:什么是盒模型?
问: 标准盒模型、怪异盒模型
定位 position
static 默认值,没有定位,元素出现在正常的文档流中;
relative 相对定位,相对位置为 自身默认位置;
absolute绝对定位,相对位置为 最近父非static的元素,没有就是body/可见视口/浏览器窗口;
fixed固定定位,对象位置为 body/可见视口/浏览神龙教主器窗口;
sticky粘性定位,该定位基于用户滚动的位置;
static 默认
relative、absolute 淘宝京东轮播图左右箭头、分页器、热卖商品、新品等等
fixed 传统网站两侧滚动广告、还有右下角客服、返回顶部等等
sticky 网站导航栏 例如 https://www.discuz.net/
水平垂直居中 🐝
方法1:【移动推荐】利用flex弹性布局 justify-content/ align-items center
方法2:【需要宽高】利用position定位 top/left 50% margin-top/left 负自身一半
方法3:【需要宽高】利用position定位 top/right/bottom/left =0 然后 margin: auto
方法4:【留心兼容】利用position定位 transform translate(-50%,-50%)
方法5:【留心兼容】利用position定位 calc((100% - 100px) / 2);
等等
两栏布局 🐝
方法1:左固定浮动、右触发BFC
方法2:左固定浮动、右margin-left
方法3:左固定定位、右margin-left
方法4:父弹性盒、左固定、右flex:1
等等
弹性布局 flex布局 🐝
https://www.zhangxinxu.com/wordpress/2018/10/display-flex-css3-css/#flex-direction
容器属性
子项属性
flex-direction: row | row-reverse | column | column-reverse;
order
flex-wrap: nowrap | wrap | wrap-reverse;
flex-grow
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
flex-shrink
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
flex-basis
align-items: stretch | flex-start | flex-end | center | baseline;
flex: none | auto | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
align-content: stretch | flex-start | flex-end | center | space-between | space-around | space-evenly;
align-self
弹性和布局后,可以给子项上添加
order 子项排序、 默认0 子项原位置
flex-grow
flex-grow属性定义子项放大比例或分配容器的剩余空间,默认为0,即如果存在剩余空间,也不放大。
写1剩余空白间隙大家等分
写2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
flex-shrink 子项收缩规则、默认1 当空间不足时都将等比例缩小,写0则不缩小
flex-basis 子项分配剩余空间之前神龙教主默认大小、默认值是auto,就是自动子项本来大小。有设置width则占据空间就是width,没有设置就按内容宽度来
flex属性是flex-grow,flex-shrink和flex-basis的缩写。
flex默认值等同于flex:0 1 auto;
flex:none等同于flex:0 0 auto;
flex:auto等同于flex:1 1 auto;
flex:1等同于flex:1 1 0;
谈谈你对flex:1的理解 🐝
它是flex-grow,flex-shrink和flex-basis的缩写。剩余空间大家等分,空间不足等比缩小,子项分配剩余空间之前用本身大小
网格布局 Grid 布局
网格布局是将页面中的元素划分成一个个各自,然后控制小格子进行合并
https://www.zhangxinxu.com/wordpress/2018/11/display-grid-css-css3/
网格和弹性盒布局区别
维度:
弹性盒布局是一维布局模神龙教主型,适合用于沿着一个方向(水平或垂直)排列元素。
网格布局是二维布局模型,可以同时控制行和列,更适合复杂的布局结构。
控制:
弹性盒布局通过设置容器的属性来控制子元素的排列方式、对齐方式、间距等。
网格布局通过定义网格的行列数量、大小、对齐方式等属性来实现布局。
灵活性:
弹性盒布局更适合于动态内容或不规则布局,可以根据内容的大小和数量自动调整布局。
网格布局更适合于网格状的布局,可以精确控制每个网格的大小和位置。
兼容性:
弹性盒布局的兼容性较好,适用于大多数现代浏览器。
网格布局的兼容性也在不断改善,但相对于弹性盒布局,在一些老版本的浏览器上可能存在兼容性问题。
CSS三角形怎么实现
宽度、高度设为0,然后设置边框样式全透明
■ 鸿蒙基础 ArkUI
版本
推荐23年10-12月左右!!!!
接触鸿蒙多久了,什么时候开始的,项目用的api几
用过 api 几个阶段
回答:api9、api11、api12都用过
分析
内容溢出如何解决 🐝
特殊的场景:展开收起评论 需要计算、文字跑马灯
Text里面是否可以写子组件
可以写Span子组件
如何复用样式
通过装饰器 @Styles、@Extend
@Styles、@Extend有什么区别
@Extend更强 支持font-size、font-weigth等等、并且可以传递参数
有几种布局方式 🐝
鸿蒙中常用的布局方式
ArkTs你说一下有几种布局方式?
轮播图问题
用过轮播图吗,有没有遇到什么问题,比如卡顿的情况
使用轮播组件的时候有没有遇到过其他问题吗?怎么解决的
网格布局,层叠布局的应用场景
绝对定位和相对定位
用过相对布局吗?说一下相对布局
绝对定位和相对定位的区别? 这俩个谁是以父容器定位的
在鸿蒙里面官方推荐使用什么布局
总元素节点为20个Text的情况下,来对比其性能消耗。通过Profiler工具获取其首帧绘制时间进行对比。对比结果如下表:
对比指标
Column/Row
Stack
Flex
RelativeContanier
Grid/GridItem
首帧绘制
7.13ms
7.34ms
11.71ms
9.13ms
12.62ms
Measure
2.63ms
2.70ms
7.59ms
3.59ms
8.68ms
Layout
0.74ms
0.77ms
0.83ms
0.77ms
0.92ms
■ 鸿蒙进阶 ArkTS
💕 week1 变量/判断/循环/函数等
let、const
面试题1:let和const区别
面试题2:const真的不能修改吗
面试题3:暂时性死区
面试题4:let和const如何选
面试题5:var和let区别
说出JS数据类型有哪些 🐝
原始类型/基本类型:null、undefined、boolean、number、string、symbol、bigint
对象类型/引用类型/复杂/复合类型:
JS引用类型object、array还有哪些
如何把数据强制转换为数值型
说明:面试概率低、工作概率高
语法:parseInt、parseFloat、Number
说出数据转换为布尔型的结果
null、undefined、0、NaN、空字符串结果是false、其他都是true
说出数据转换为字符串型的结果
都字符串
String(内容)、内容.toString()
说出数据转换为数值型的结果
Number(数据)
数据
结果
null
0
undefined
NaN
true/false
1/0
123/NaN
123/NaN
''/'123'/'123a'
0/123/NaN
null 和 undefined 有什么区别? 🐝
undefined 表示未定义,新定义的变量没有赋值就是undefined
null表示清空,当一个变量不用的时候,除了等待网页关闭销毁,也可以把它赋值为null。此时游览器会进行一个回收也就是清空内存。
了解1
typeof(null)会是一个object。最初这么设计的原因为:通常用作一个空引用一个空对象的预期,就像一个占位符。typeof的这种行为已经被确认为一个错误,虽然提出了修正,出于后兼容的目的,这一点已经保持不变。
了解2
为什么 0.1 + 0.2 !== 0.3? 你如何解决这个问题? 🐝❄️
因为 0.1 这样的数值用二进制表示你就会发现无法整除,
最后算下来会是0.0001100110011001...由于存储空神龙教主间有限,位数是无限的,只能取近似。
代码:0.1 + 0.2 == 0.3 // false
代码:0.625 + 0.625 == 1.25 // true
进制转换规则:https://www.runoob.com/w3cnote/decimal-decimals-are-converted-to-binary-fractions.html
十进制整数 -> 转二进制
十进制小数 -> 转二进制
推荐解决: 浮点数转化成整数
实战使用:购物车结算时,商品价格(33.01)-优惠券价格(5),本应该是28.01,但是实际的结果是28.009999999999998
es6 解决办法
四舍五入
采用四舍五入方法,取了一个 10 位小数
使用第三方库
💕 week2 对象/数组/内置对象/es6/正则
说出变量在内存中的分配 🐝
栈:存 原始类型【名字】&【数据】、对象类型的【名字】&【堆地址】
堆:对象类型数据
说出变量赋值内存分配 🐝
原始类型:变量赋值,栈开辟内存直接存数据 -> 数据互补影响对象类型:变量赋值,栈开辟内存,存放神龙教主堆地址 -> 数据相互影响
切记切记切记:上课讲的形参也会出现传值、传地址问题
@State装饰器响应式失效原因、如何解决 🐝❄️
鸿蒙规定一维数据变化有响应式,二维没有
解决:修改一维数据 或者 通过 @Observed、@ObjectLink装饰一下 放到子组件中用
或者
v2版@ObservedV2 @Trace
判断是否是数组 🐝
方法1:通过语法 Array.isArray()
方法2:instanceof
方法3:原型链(constructor)
..... We
如何交换两个变量的值
临时变量法
加减法
解构赋值法 week3
数组法
对象法
等等太多了
说出数组有哪些方法 🐝
·数据操作:shift/unshift/pop/push
遍历数据: forEach/map/filter/find/findIndex
工作常用:concat/join/indexOf/includes
学习常用:reverse/splice
了解:sort
说出数组哪些方法会改变原数据
数据操作:shift/unshift/pop/push
学习常用:reverse/splice
了解:sort
如何实现数组去重 🐝
方法1:通过es6新增的Set数据结构、和展开运算符去重 [...new Set(重复数组)] week3
方法2:通过filter配合indexOf实神龙教主现数组去重
方法3:定义空数组,通过forEach遍历重复的数组,通过indexOf判断当前值是否在数组中,不在就push
方法4:定义空数组,通过forEach遍历重复的数组,通过includes判断当前值是否在数组中,不在就push
方法5:利用对象的属性去重
方法6:....
说出字符串常用方法
工作常用:数组、查找、替换、截取、大小、空格
split、replace、substr、toUpperCase/toLowerCase、trim、slice
学习:.length、lastIndexOf、repeat
正则
匹配手机号:/^1\d{10}$/.test(数据)
匹配邮箱:/^\w{2,20}@\w{2, 20}.(com|org|cn|edu)$/.test(数据)
匹配中文:/[1]+$/.test(数据)
去所有空格:str.replaceAll(' ', '') 或 str.replace(/\s/g, '')
购物车去非数字:str.replace(/\D/g, '')
es6新增语法
https://github.com/tc39/proposals/blob/main/finished-proposals.md
💕 week3 面向对象/事件
事件有哪些
通用事件按照触发类型来分类,包括触屏事件、键鼠事件、焦点事件和拖拽事件。
触屏事件:手指或手写笔在触屏上的单指或单笔操作。
键鼠事件:包括外设鼠标或触控板的操作事件和外设键盘的按键事件。
鼠标事件是指通过连接和使用外设鼠标/触控板操作时所响应的事件。
按键事件是指通过连接和使用外设键盘操作时所响应的事件。
焦点事件:通过以上方式控制组件焦点的能力和响应的事件。
拖拽事件:由触屏事件和键鼠事件发起,包括手指/手写笔长按组件拖拽和鼠标拖拽。
事件分发:描述触控类事件(不包括按键,焦点)响应链的命中收集过程。
手势事件由绑定手势方法和绑定的手势组成,绑定的手势可以分为单一手势和组合手势两种类型,根据手势的复杂程度进行区分。
绑定手势方法:用于在组件上绑定单一手势或组合手势,并声明所绑定的手势的响应优先级。
单一手势:手势的基本单元,是所有复杂手势的组成部分。
组合手势:由多个单一手势组合而成,可以根据声明的类型将多个单一手势按照一定规则组合成组合手势,并进行使用。
💕 week4 服务器请求 callback、promise、http、async/await
谈谈你对HTTP理解
HTTP周边:强制缓存、协商缓存
强制缓存:就是文件直接从本地缓存中获取,不需要发送请求。
响应头 Cache-Control : 86400
expires
协商缓存/对比缓存
在响应头部 Response Headers 中,有两种资源标识:
Last-Modified 资源的最后修改时间,对应请求头为 If-Modified-Since ;
Etag 资源的唯一标识,所谓唯神龙教主一,可以想象成时人类的指纹,具有唯一性;但 Etag 的本质是一个字符串;对应请求头为 If-None-Match 。
Last-Modified 和 Etag
当响应头部 Response Headers 同时存在 Last-Modified 和 Etag 的值时,会优先使用 Etag ;
Last-Modified 只能精确到秒级;
如果资源被重复生成,而内容不变,则 Etag 更精确。
https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fupload-images.jianshu.io%2Fupload_images%2F5727550-fd8811d7defb8956.png&refer=http%3A%2F%2Fupload-images.jianshu.io&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1650391279&t=0419cce2bf932f3c0e83594c4d177742
get和post有什么区别
谈谈你对http、https的理解,有什么区别
谈谈你对Event Loop理解
遇到异步代码会交给其他线程处理,然后放到队列中,
事件循环主要是从队列中取出代码放到执行栈中交给js引擎线程处理
说出宏任务、微任务各有哪些
单词含义:I input 输入、 O output 输出
用户角度IO操作:鼠标键盘-是计算机输入信息,显示器-是输出设备
电脑角度IO操作:CPU、内存与其他设备之间数据转移过程就是IO操作,例如数据从磁盘读到内存,或者内存写到磁盘
编程角度IO操作:进程读取数据操作
宏任务:
微任务
说出先执行宏任务还是微任务
1宏n微
谈谈你对promise的理解
概念:ES6异步编程解决方案
作用:常用于封装ajax异步请求
说一下promise原理
底层创建了Promise构造函数,并且给该构造函数绑定了then、catch、finally等原型方法,和reject、resolve、all、race等静态方法。
说一下promise几个状态
进行中、成功了、失败了
追问:为什么状态不可逆
回答:底层Promise构造函数中会判断当前是否是pending进行中状态,不是就会终止代码执行 所以不可逆
追问:状态之间怎么转换?
回答:通过promise的then机制,来实现状态切换
Promise.all、Promise.allSettled区别
Promise.all( 数组里面是一个个Promise对象 ) 有一个失败就走失败
Promise.allSettled( 数组里面是一个个Promise对象 ) 没有失败
Promise.race、Promise.any区别
Promise.race( 数组里面是一个个Promise对象 ) 根据第一个最快返回的决定状态
Promise.any( 数组里面是一个个Promise对象 ) 有一个成功就是then 都失败 才是catch
谈谈你对同步异步的理解
会被加入到队列的代码称之为异步代码,例如 http、setTimeout/setInterval、Promise.then 等等,他们不按书写✍🏻顺序执行打印结果的代码
按照书写顺序执行打印的代码称之为同步代码
谈谈你对async,await的理解
通过async修饰function、await修饰promise,
底层将await后面的表达式会先执行一遍,再将await下一行代码加入到微任务中。
■ 鸿蒙核心
🥥 实战常问 🐝🐝🐝🐝🐝🐝🐝
装饰器
组件通信
生命周期
状态管理
数据持久化
进程线程
Stage 模型
Web 服务
组件导航
服务卡片
一次开发,多端部署
分层架构
🍃 api9、api12区别
ArkTS类型更加严格
@Prop api12可以设置默认值、并且可以支持对象。
API12的文档和示例可能会更加丰富和完善,有助于开发者更快地掌握新特性并开始开发。
生态系统变化 -> API12发布时,鸿蒙的生态系统可能已经变得更加成熟,有更多的第三方应用和服务可供集成。
其他小细节
🍃 路由
-
跳转模式、和区别
-
实例模式
-
谈谈你对页面栈的理解和特点
-
页面栈的最大容量,超过会怎么样
页面栈的最大容量为32个页面。
报错 =》 解决:如果超过这个限制,可以调用router.clear方法清空历史页面栈,释放内存空间。
- 路由传参
🍃 自定义构建函数
- @Builder传参响应式失效如何解决
可以不传直接组件状态
或者引用传参(就是传对象)
- 如何实现全局Builder
wrapBuilder函数把@Builder包括导出就行
- 如何侦听@State数据变化
@Watch
-
@BuilderParam是什么作用,其中的this指向是什么
-
@Builder 是做什么的,和组件有什么区别
-
Builder里自定义传递参数,有两个传递方式,是哪两种;追问:参数类型和参数声明必须一致吗?能传undefined、null吗?
-
如何封装全局@Builder
🍃 装饰器 ⭐️
-
装饰器有哪些
-
装饰器区别
-
@Link和@Prop区别🐝🐝
-
@state和@prop的区别
-
嵌套类型用什么装饰器
@Observed/@ObjectLink嵌套类对象属性变化
-
如果内部对象的数据变换,会实时刷新吗?🐝🐝
-
@prop,@Link需要初始化吗
-
@Provide装饰器和@Consume装饰器得理解
-
@State能修饰复杂的数据类型吗?或者说嵌套对象
可以
- @watch是用来干什么的 追问:监听到了会做什么操作呢
侦听数据变化的,减少视图层写事件 -> 看需求
- @Watch作用,第一次加载是否会调用
侦听状态变化,不会
-
@State原理
-
@ObjectLink的事件原理有了解过吗?
-
鸿蒙装饰器作用和原理
大概就是通过属性装饰器函数进行封装,
内部通过defineProperty劫持数据变化
🍃 组件状态共享/组件通信 ⭐️
-
组件件的通信有几种方式🐝
-
父向子传传有几种写法🐝
-
鸿蒙跨层级的组件通信
🍃 生命周期 ⭐ ️
-
分别说出组件、页面、UIAbility生命周期和场景 🐝🐝
-
自定义组件的生命周期
-
aboutToAppear在什么时候执行
build之前
🍃 状态管理 ⭐️
状态管理有哪些🐝🐝
AppStorage和Localstorage区别、哪里用?
v2新增了哪些装饰器,为什么升级,有什么用🐝🐝
🍃 数据持久化 ⭐️
数据持久化用过哪些? 🐝🐝
首选项如何实现持久化 🐝🐝
首选项和PersistentStorage区别
PersistentStorage进行数据持久化,和preferences用户首选项使用场景?
非UI页面使用用户首选项时context如何获取
可以在UIAbility里通过AppStorage或LocalStorage里存储context,然后在非ArkUI页面里使用。
this.context
getContext(this)
通过用户首选项实现数据持久化之后,如果App更新版本,之前首选项的数据是否会保留
持久化之后的数据是存在文件中的,App更新版本之后是存在的。
关系型数据库(RelationalStore)如何实现
键值型数据接口(KV-Store)如何实现
跨模块、跨进程时如何保证正常读取首选项中数据?
跨模块:
由于context不同,获取到的是不同的首选项实例,因此会导致在跨模块、多页面等场景下取不到数据。此时可以考虑通过单例类在EntryAbility中存一个全局的context,或者使用应用级context。
跨进程:
不同进程一般只有在同沙箱的场景才能访问到一个preference文件,多进程可以通过dataGroupId在多个进程间共用一个preference文件。
首选项存储如果多个任务同时写入、并发的情况能保证数据的准确性吗
首选项无法保证进程并发安全,会有文件损坏和数据丢失的风险,不支持在多进程场景下使用。
对于多线程操作首选项和数据库是不是线程安全的?还是每一个线程独立的
是线程安全的。
用户首选项是线程安全的吗
首选项是线程安全的,所以多线程访问可以保证数据一致性,但只支持同进程,不支持多进程。
不依赖接口 用手机存储 怎么存储
自己通过文件管理直接写数据然后获取出来
🍃 进程线程 ⭐️
- 谈谈你对进程线程的理解 🐝🐝
进程:
进程是正在执行的程序的实例,它是系统资源分配的基本单位。
进程是一个独立的程序运行环境
是系统进行资源分配的基本单位
线程:
线程是进程内部的执行单位
是操作系统能够进行运算调度的最小单位。
- 鸿蒙线程之间内存共享吗?
不共享
ArkTS采用消息通信的Actor并发模型 所以具有内存隔离特性
java是内存共享的并发模型
-
鸿蒙arkts是单线程还是多线程、为什么是单线程呢
-
鸿蒙 stage 是单线程还是多线程
ArkTS是单线程的,单线程可以避免锁机制
- 鸿蒙如何实现多线程 🐝🐝
taskpool、worker
- 进程/线程通信🐝🐝
通信场景
能力支持
同Ability通信
Emitter、EventHub、CommonEvent
跨Ability通信
Emitter、EventHub、CommonEvent
跨线程通信
Emitter、CommonEvent、Worker、Taskpool
跨进程通信
CommonEvent、IPC&RPC
dataShare跨应用通信:用于应用管理其自身数据,同时支持同个设备上不同应用间的数据共享。
- taskpool和worker区别 🐝🐝
短时任务用TaskPool、长时任务用worker
场景对比
TaskPool和Worker均支持多线程并发能力。由于TaskPool的工作线程会绑定系统的调度优先级,并且支持负载均衡(自动扩缩容),而Worker需要开发者自行创建,存在创建耗时以及不支持设置调度优先级,故在性能方面使用TaskPool会优于Worker,因此大多数场景推荐使用TaskPool。
TaskPool偏向独立任务维度,该任务在线程中执行,无需关注线程的生命周期,超长任务(大于3分钟且非长时任务)会被系统自动回收;而Worker偏向线程的维度,支持长时间占据线程执行,需要主动管理线程生命周期。
常见的一些开发场景及适用具体说明如下:
运行时间超过3分钟(不包含Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时)的任务。例如后台进行1小时的预测算法训练等CPU密集型任务,需要使用Worker。场景示例可参考常驻任务开发指导。
有关联的一系列同步任务。例如在一些需要创建、使用句柄的场景中,句柄创建每次都是不同的,该句柄需永久保存,保证使用该句柄进行操作,需要使用Worker。场景示例可参考使用Worker处理关联的同步任务。
需要设置优先级的任务。例如图库直方图绘制场景,后台计算的直方图数据会用于前台界面的显示,影响用户体验,需要高优先级处理,需要使用TaskPool。
需要频繁取消的任务。例如图库大图浏览场景,为提升体验,会同时缓存当前图片左右侧各2张图片,往一侧滑动跳到下一张图片时,要取消另一侧的一个缓存任务,需要使用TaskPool。
大量或者调度点较分散的任务。例如大型应用的多个模块包含多个耗时任务,不方便使用Worker去做负载管理,推荐采用TaskPool。场景示例可参考批量数据写数据库场景。
TaskPool和Worker的实现特点对比
实现
TaskPool
Worker
内存模型
线程间隔离,内存不共享。
线程间隔离,内存不共享。
参数传递机制
采用标准的结构化克隆算法(Structured Clone)进行序列化、反序列化,完成参数传递。支持ArrayBuffer转移和SharedArrayBuffer共享。
采用标准的结构化克隆算法(Structured Clone)进行序列化、反序列化,完成参数传递。支持ArrayBuffer转移和SharedArrayBuffer共享。
参数传递
直接传递,无需封装,默认进行transfer。
消息对象唯一参数,需要自己封装。
方法调用
直接将方法传入调用。
在Worker线程中进行消息解析并调用对应方法。
返回值
异步调用后默认返回。
主动发送消息,需在onmessage解析赋值。
生命周期
TaskPool自行管理生命周期,无需关心任务负载高低。
开发者自行管理Worker的数量及生命周期。
任务池个数上限
自动管理,无需配置。
同个进程下,最多支持同时开启64个Worker线程,实际数量由进程内存决定。
任务执行时长上限
3分钟(不包含Promise和async/await异步调用的耗时,例如网络下载、文件读写等I/O任务的耗时),长时任务无执行时长上限。
无限制。
设置任务的优先级
支持配置任务优先级。
不支持。
执行任务的取消
支持取消已经发起的任务。
不支持。
线程复用
支持。
不支持。
任务延时执行
支持。
不支持。
设置任务依赖关系
支持。
不支持。
串行队列
支持。
不支持。
任务组
支持。
不支持。
- Worker和TaskPool的线程数量是否有限制
TaskPool内部会动态调整线程个数,不支持设置数量,只需要往线程池中抛任务,确保高优先级任务的及时执行。
Worker的线程个数最多64个,如果Worker超过规定个数,会创建失败。
在使用时,TaskPool与Worker两者独立,不相互影响,因此Worker在达到上限数量时,不会影响TaskPool。Worker是固定数量,当前是64个。TaskPool线程池的数量会根据硬件条件、任务负载等情况动态调整。
- 鸿蒙有几个进程线程
系统的进程模型如下图所示。
通常情况下,应用中(同一Bundle名称)的所有UIAbility、ServiceExtensionAbility和DataShareExtensionAbility均是运行在同一个独立进程(主进程)中,如下图中绿色部分的“Main Process”。
UIAbility 页面能力 窗口 -> 加载页面
ServiceExtensionAbility 后台服务扩展能力,提供后台运行并对外提供相应能力。
DataShareExtensionAbility 数据共享扩展能力,用于对外提供数据读写服务。
应用中(同一Bundle名称)的所有同一类型ExtensionAbility(除ServiceExtensionAbility和DataShareExtensionAbility外)均是运行在一个独立进程中,如下图中蓝色部分的“FormExtensionAbility Process”、“InputMethodExtensionAbility Process”、其他ExtensionAbility Process。
FormExtensionAbility:卡片扩展能力,提供卡片开发能力。
WorkSchedulerExtensionAbility:延时任务扩展能力,允许应用在系统闲时执行实时性不高的任务。
InputMethodExtensionAbility:输入法扩展能力,用于开发输入法应用。
AccessibilityExtensionAbility:无障碍服务扩展能力,支持访问与操作前台界面。
FileShareExtensionAbility:文件共享扩展能力,用于应用间的文件分享。预留能力,仅系统应用支持。
等等
WebView拥有独立的渲染进程,如下图中黄色部分的“Render Process”。
鸿蒙加载h5网页
图1 进程模型示意图
Stage模型下的线程主要有如下三类:
主线程
执行UI绘制。
管理主线程的ArkTS引擎实例,使多个UIAbility组件能够运行在其之上。
管理其他线程的ArkTS引擎实例,例如使用TaskPool(任务池)创建任务或取消任务、启动和终止Worker线程。
分发交互事件。
处理应用代码的回调,包括事件处理和生命周期管理。
接收TaskPool以及Worker线程发送的消息。
TaskPool Worker线程
用于执行耗时操作,支持设置调度优先级、负载均衡等功能,推荐使用。
Worker线程
用于执行耗时操作,支持线程间通信。
TaskPool与Worker的运作机制、通信手段和使用方法可以参考TaskPool和Worker的对比。
- 主线程有哪些职责呢
主线程
执行UI绘制。
管理主线程的ArkTS引擎实例,使多个UIAbility组件能够运行在其之上。
管理其他线程的ArkTS引擎实例,例如使用TaskPool(任务池)创建任务或取消任务、启动和终止Worker线程。
分发交互事件。
处理应用代码的回调,包括事件处理和生命周期管理。
接收TaskPool以及Worker线程发送的消息。
- 如何实现异步开发/并发/处理
Promise和async/await
- 谈谈你对pormise的理解,有几个状态
异步编程解决方案
romise有三种状态:pending(进行中)、fulfilled(已完成)和rejected(已拒绝)。Promise对象创建后处于pending状态,并在异步操作完成后转换为fulfilled或rejected状态。
- promise和async、await关系
promise是异步编程解决方案
async/await是一种用于处理异步操作的Promise语法糖,使得编写异步代码变得更加简单和易读。通过使用async关键字声明一个函数为异步函数,并使用await关键字等待Promise的解析(完成或拒绝),以同步的方式编写异步操作的代码。
一般做项目接口返回的数据都保存在promise中,咱们通过async/await就可以获取出来
- 异步处理和主线程有什么关系、如何通信
异步操作的设计初衷就是为了减少对主线程(UI线程)的影响,从而提升应用的响应性和用户体验。
通信直接修改@State状态就行
- 你的项目中有没有用到多线程
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/multithread-develop-case-V5
- promise 并发是单线程还是多线程
遇到pormise会放到微任务队列,然后等js线程执行完毕,再由event loop事件循环对象把promise数据交给js线程处理
- 子线程和主线程的优先级及任务执行策略是什么
主线程作为UI线程,拥有最高优先级。在负载较高时,执行会更快;负载较低时,效率差别不大。
子线程可以通过优先级设置,任务优先级等影响调度。
- 在多线程并发场景中,如何实现安全访问同一块共享内存
可以使用共享对象SharedArrayBuffer实现。SharedArrayBuffer对象存储的数据在同时被修改时,需要通过Atomics原子操作保证其同步性,即下个操作开始之前务必需要等到上个操作已经结束。
🍃 文件基础服务
谈谈你对沙箱的理解
应用沙箱是一种以安全防护为目的的隔离机制,避免数据受到恶意路径穿越访问。在这种沙箱的保护机制下,应用可见的目录范围即为“应用沙箱目录”。
对于每个应用,系统会在内部存储空间映射出一个专属的“应用沙箱目录”,它是“应用文件目录”与一部分系统文件(应用运行必需的少量系统文件)所在的目录组成的集合。
应用沙箱限制了应用可见的数据范围。在“应用沙箱目录”中,应用仅能看到自己的应用文件以及少量的系统文件(应用运行必需的少量系统文件)。因此,本应用的文件也不为其他应用可见,从而保护了应用文件的安全。
应用可以在“应用文件目录”下保存和处理自己的应用文件;系统文件及其目录对于应用是只读的;而应用若需访问用户文件,则需要通过特定API同时经过用户的相应授权才能进行。
沙箱目录和缓存清除机制
cache 应用缓存目录(应用cache目录大小超过配额或者系统空间达到一定条件,自动触发清理该目录下文件;随应用卸载而清理)
preferences 用户首选项(随应用卸载而清理)
temp 应用临时文件路径(应用退出后即清理。保存应用的临时生成的数据,主要包括数据库缓存、图片缓存、临时日志文件、以及下载的应用安装包文件等。此路径下存储使用后即可删除的数据)
files 默认长期保存的文件路径;随应用卸载而清理。
图片上传
1、使用Picker选择媒体库的图片与视频 (返回一个临时的图片地址 file:// 咱们可以直接预览 也可以继续向后走 拿到服务器地址再预览)
2、把图片拷贝到应用的缓存目录 (不支持直接通过相册本地路径请求接口,仅支持通过缓存目录上传 context.cacheDir)
3、上传文件 request.uploadFile到服务器
拍照上传
附件上传
文件下载
资源目录存媒体库
沙箱文件存媒体库
http://tmp00002.zhaodashen.cn/jd.png
🍃 程序访问控制
申请权限
a 在配置文件中声明权限
b 校验当前是否已经授权 checkAccessToken
c 动态向用户申请授权 requestPermissionsFromUser
d 处理授权结果 requestPermissionOnSetting 如果用户授权,则可以继续访问目标操作。 如果用户拒绝授权,则需要提示用户必须授权才能访问当前页面的功能,并引导用户到系统应用“设置”中打开相应的权限。 在common架构base模块下封装授权文件
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/request-user-authorization-V5#开发步骤
地理位置
1-配置申请位置权限 同时申请ohos.permission.APPROXIMATELY_LOCATION和ohos.permission.LOCATION 获取到精准位置,精准度在米级别。
2-检查全局位置开关是否打开 geoLocationManager.isLocationEnabled();
2.1 没开 atManager.requestGlobalSwitch(getContext(this), abilityAccessCtrl.SwitchType.LOCATION) 拉起全局设置位置开关页
2.2 开了 继续
3-获取当前位置 geoLocationManager.getCurrentLocation(request) 可以获取用户经度纬度
4-可以继续通过geoLocationManager.getAddressesFromLocation()地理编码转化为可读性较强地址
获取设备的位置信息,需要有位置权限,位置权限申请
按照步骤申请权限 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/location-guidelines-V13
持续定位
持续定位。多用于导航、运动轨迹、出行等场景。
首先要实例化ContinuousLocationRequest对象,用于告知系统该向应用提供何种类型的位置服务,以及位置结果上报的频率。
设置locationScenario:
建议locationScenario参数优先根据应用的使用场景进行设置,该参数枚举值定义参见UserActivityScenario,例如地图在导航时使用NAVIGATION参数,可以持续在室内和室外场景获取位置用于导航。
设置interval:
表示上报位置信息的时间间隔,单位是秒,默认值为1秒。如果对位置上报时间间隔无特殊要求,可以不填写该字段。
以地图导航场景为例,调用方式如下:
如果不主动结束定位可能导致设备功耗高,耗电快;建议在不需要获取定位信息时及时结束定位。
geoLocationManager.off('locationChange', locationCallback);
完整代码
后台定位-长时任务
应用退至后台后,在后台需要长时间运行用户可感知的任务,如播放音乐、导航等。为防止应用进程被挂起,导致对应功能异常,可以申请长时任务,使应用在后台长时间运行。在长时任务中可以申请多种类型的任务,并对任务类型进行更新。应用退后台执行业务时,系统会做一致性校验,确保应用在执行相应的长时任务。同时,系统有与长时任务相关联的通知栏消息,用户删除通知栏消息时,系统会自动停止长时任务。
需要申请ohos.permission.KEEP_BACKGROUND_RUNNING权限,配置方式请参见声明权限。
声明后台模式类型。
在module.json5配置文件中为需要使用长时任务的UIAbility声明相应的长时任务类型(配置文件中填写长时任务类型的配置项)。
创建BackgroundTaskUtil.ets文件封装长短时任务
示例代码
🍃Stage模型 UIAbility ⭐️
UIAbility的理解
UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口。一个应用可以包含一个或多个UIAbility组件。
UIAbility 有几种启动方式🐝🐝
UIAbility的启动模式是指UIAbility实例在启动时的不同呈现状态。针对不同的业务场景,系统提供了三种启动模式:
singleton(单实例模式)
multiton(多实例模式)
specified(指定实例模式)
说明:standard是multiton的曾用名,效果与多实例模式一致。
UIAbility生命周期区别,使用场景🐝🐝
多个 uiability 之间是如何通信的
startAbility传参 onCreate、onNewWant获取
AppStorage
emitter
FA模型、Stage模型区别
项目
FA模型
Stage模型
应用组件
- 组件分类
- PageAbility组件:包含UI,提供展示UI的能力。详细介绍请参见PageAbility组件概述
。- ServiceAbility组件:提供后台服务的能力,无UI。详细介绍请参见ServiceAbility组件概述
。- DataAbility组件:提供数据分享的能力,无UI。详细介绍请参见DataAbility组件概述
。2. 开发方式通过导出匿名对象、固定入口文件的方式指定应用组件。开发者无法进行派生,不利于扩展能力。
- 组件分类
- UIAbility组件:包含UI,提供展示UI的能力,主要用于和用户交互。详细介绍请参见UIAbility组件概述
。- ExtensionAbility组件:提供特定场景(如卡片、输入法)的扩展能力,满足更多的使用场景。详细介绍请参见ExtensionAbility组件概述
。2. 开发方式采用面向对象的方式,将应用组件以类接口的形式开放给开发者,可以进行派生,利于扩展能力。
进程模型
有两类进程:1. 主进程2. 渲染进程详细介绍请参见进程模型
。
有三类进程:1. 主进程2. ExtensionAbility进程3. 渲染进程详细介绍请参见进程模型
。
线程模型
- ArkTS引擎实例的创建一个进程可以运行多个应用组件实例,每个应用组件实例运行在一个单独的ArkTS引擎实例中。2. 线程模型每个ArkTS引擎实例都在一个单独线程(非主线程)上创建,主线程没有ArkTS引擎实例。3. 进程内对象共享:不支持。详细介绍请参见线程模型
。 - ArkTS引擎实例的创建一个进程可以运行多个应用组件实例,所有应用组件实例共享一个ArkTS引擎实例。2. 线程模型ArkTS引擎实例在主线程上创建。3. 进程内对象共享:支持。详细介绍请参见线程模型
。
应用配置文件
使用config.json描述应用信息、HAP信息和应用组件信息。详细介绍请参见应用配置文件概述(FA模型)
。
使用app.json5描述应用信息,module.json5描述HAP信息、应用组件信息。详细介绍请参见应用配置文件概述(Stage模型)
。
应用通信/跨设备通信🐝🐝
拉起指定应用 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/app-linking-startup-V5
处理链接
拉起指定类型的应用
module.json5
code
显示Want和隐式Want区别?
显式Want:在启动目标应用组件时,调用方传入的want参数中指定了abilityName和bundleName,称为显式Want。
显式Want通常用于应用内组件启动。
隐式Want:在启动目标应用组件时,调用方传入的want参数中未指定abilityName,称为隐式Want。
显式Want在启动目标应用组件时,显式指定了能力名称(abilityName)和包名称(bundleName),通常用于应用内组件启动。隐式Want未指定这些信息,主要通过动作(action)、实体(entities)、URI和类型(type)等匹配目标组件,系统会根据这些属性在安装的应用中查找合适的组件
■ 鸿蒙WebView应用开发
JSX、脚手架、类组件
🐝🐝🐝vue和react区别、vue2和vue3区别
思考:如果你是面试官你问 v2和v3区别 vue和react区别 你想听到什么或者可以从几个维度去回答
回答:
第一种:拿出语法区别挨个说 例如 v3相对v2不支持过滤器、混入;....
第二种:框架层面思想上设计上、语法层面、底层原理
测试:v2、v3
框架层面思想设计上
语法层面:双向绑定、侦听器watch/watchEffect、组件实例需要暴露属性才可以外部使用public/private、生命周期、样式:deep/:global、增加teleport、emits、Fragments、Composition API、sfc script setup等等
底层原理:Object.defineProperty、Proxy; diff算法区别
测试:vue、react区别
组件化:Vue的组件化更加直接,因为组件包含了模板、逻辑和样式;而React的组件化更加灵活,它只关注逻辑,样式可以使用外部的CSS文件或库。
模板语法:Vue使用基于HTML的模板语法,而React使用JSX语法,它将HTML嵌入到JavaScript代码中。
状态管理:Vue使用名为Vuex、PInia的状态管理库,而React则使用一个名为Redux的库、和基于Redux封装的Dva模块
生态系统:React的生态系统更加庞大,拥有更多的第三方库和工具。Vue生态系统也很强大,但是相对来说较小。大厂加持
学习曲线:由于Vue的模板语法和直观的API,学习Vue相对来说比较容易。而React的JSX语法和函数式编程风格,需要一定的JavaScript知识和函数式编程理念。
移动开发:weex开发app uniapp、 rn/react native 开发app
开发团队:尤雨溪团队、Facebook
数据响应:Vue 的数据响应采用的是双向绑定方式,可以直接修改数据和视图;React 的数据响应采用的是单向数据流方式,需要手动更新数据和视图。
最终:vue 官方化; react 社区化
🐝 jsx的优点
1、JSX 更加灵活,JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化
2、Template 更多约束、类型安全的,在编译过程中就能发现错误
等等
JSX 是一种 JavaScript 语法扩展,是 React 中定义 UI 的一种方式。相对于传统的模板语言,JSX 具有以下优点:
更加直观
JSX 可以将 HTML 和 JavaScript 代码混合在一起编写,使得代码更加直观和易于理解。开发者可以在组件中轻松地编写 HTML 标记和逻辑代码,不需要在模板和代码之间来回切换。
更加灵活
JSX 可以在 JavaScript 中使用表达式和变量,可以根据逻辑动态生成组件和元素,使得开发更加灵活。JSX 可以使用 JavaScript 的所有特性,如循环、条件语句、函数调用等。
更加强大
JSX 可以使用自定义组件、事件处理器、样式、属性等功能,可以创建复杂的 UI 界面。使用 JSX 可以更好地组织代码,使得代码更加易于维护和扩展。
更加高效
JSX 可以在编译时进行优化,可以生成更加高效的 JavaScript 代码,提高应用程序的性能。JSX 编译器可以将 JSX 转换为常规的 JavaScript 函数调用,这些函数调用会创建 React 元素对象,从而提高了渲染效率。
总的来说,JSX 具有更加直观、灵活、强大和高效等优点,使得 React 开发更加便捷和高效。但是,对于一些开发者来说,可能需要一些时间来适应 JSX 的语法和编写方式。
🌛 babel原理
Babel 是一个 JavaScript 编译器,它可以将最新版的 ECMAScript 代码转换为向后兼容的代码,以便在旧版浏览器或其他 JavaScript 环境中运行。Babel 的核心功能是将 ECMAScript 代码转换为 JavaScript AST(抽象语法树),然后根据一组规则(称为插件)对 AST 进行变换,最后将变换后的 AST 转换为 JavaScript 代码。
下面是 Babel 的编译过程:
解析:将 ECMAScript 代码解析成抽象语法树(AST)。
转换:对 AST 进行转换,可以添加、修改、删除节点等操作,例如将 ES6 的箭头函数转换为 ES5 的函数表达式。
生成:根据变换后的 AST 生成新的 ECMAScript 代码。
Babel 的插件系统是 Babel 的核心,它允许开发者根据需要添加、删除和修改 AST 节点,以达到所需的转换效果。Babel 内置了很多插件,同时还有很多社区维护的插件供使用。
Babel 还有一个很重要的概念:预设(preset)。预设是一组插件的集合,可以直接用于对代码的编译。Babel 官方提供了很多预设,例如 babel-preset-env、babel-preset-react 等。预设通常是针对某种场景或应用开发的,可以减少开发者配置插件的时间和精力。
Babel 在编译时还有一些重要的概念,例如 polyfill、source map 等。polyfill 是在编译时自动添加到代码中的补丁,用于实现一些在当前 JavaScript 运行环境中不支持的特性。source map 是一种映射关系,它将编译后的代码映射回原始代码,方便开发者在调试时快速定位问题。
总之,Babel 的原理是将 ECMAScript 代码转换为抽象语法树(AST),然后根据一组规则对 AST 进行变换,最后将变换后的 AST 转换为 JavaScript 代码。Babel 的插件系统和预设是 Babel 的核心,它们可以帮助开发者实现所需的转换效果。
状态、属性、合成事件、含TypeScript
🐝🐝 setState语法是同步的还是异步的,什么时候会合并操作
react16:react控制异步/合并、非react控制同步/不合并react18:都是异步、归类合并
🌛 setState底层原理
在 React 类组件中,setState() 方法用于更新组件的状态。当调用 setState() 方法时,React 会将新的状态合并到当前的状态中,然后重新渲染组件。
setState() 方法的底层实现可以分为以下几个步骤:
将新的状态对象与当前状态对象合并 神龙教主
当调用 setState() 方法时,React 会将传入的新的状态对象与当前的状态对象进行浅合并。这意味着只有新状态对象中包含的属性会被更新,而当前状态对象中的其他属性将保持不变。
将合并后的状态对象存储到组件实例中
合并后的状态对象将被存储到组件实例的一个内部属性中。这个内部属性称为_pendingState,表示待处理的状态。
判断是否处于批量更新模式
在 React 中,可以通过 batchedUpdates() 方法将多个状态更新操作合并为一个批量更新操作,从而提高性能。当调用 setState() 方法时,React 会判断当前是否处于批量更新模式。
如果处于批量更新模式,React 会将组件实例添加到更新队列中,等到下一次批量更新时再进行更新。
如果不处于批量更新模式,React 会立即进行更新。
触发组件更新
当合并后的状态对象被存储到组件实例中后,React 会触发组件的更新流程。在更新流程中,React 会先调用组件的 shouldComponentUpdate() 方法,判断是否需要更新组件。
如果需要更新组件,React 会重新调用组件的 render() 方法,生成新的虚拟 DOM 对象。然后,React 会通过 Diff 算法比较新的虚拟 DOM 和旧的虚拟 DOM,计算出需要更新的部分,并生成更新操作。
最后,React 会将更新操作应用到真实的 DOM 上,完成组件的更新。
总的来说,setState() 方法的底层原理是将新的状态对象合并到当前状态对象中,存储到组件实例中,并触发组件的更新流程。通过这个流程,React 可以保证组件的状态和 UI 同步更新。
🐝🐝🐝 函数组件和类组件区别
函数组件:无状态也就是模型数据,无生命周期 hooks 类组件:有状态,有生命周期
🐝🐝🐝 函数组件如何状态管理
可以通过redux、或 hook是新技术
🐝🐝🐝 状态state、和属性props区别;如何选
语法角度
功能角度
🐝 谈谈你对合成事件的理解、优势、原理、和原生事件区别
是什么:React模拟原生 DOM 事件开发的一套事件系统
啥好处
如果把所有的事件处理函数都绑定在DOM上,那么在页面响应的时候就会收到影响,导致页面很慢。react为了避免这类DOM事件的滥用,同时屏蔽底层之间不同浏览器事件的系统差异,实现了一个中间层- syntheticEvent合成事件
啥原理:
React 上注册的事件最终会绑定在document这个 DOM 上,而不是 React 组件对应的 DOM(减少内存开销就是因为所有的事件都绑定在 document 上,其他节点没有绑定事件,React17事件委托的变更 React 树的根 DOM 容器中)
https://img-blog.csdnimg.cn/img_convert/945dd88ba1f47ecac1b9f27c15d8b312.png
为啥升级
和原生区别
1、事件名称命名方式不同
2、事件处理函数写法不同
阻止默认行为方式不同
样式、判断、循环、表单、ref、组件通信、跨域
🐝🐝🐝react中如何解决样式污染问题
方案1:Inline styling 行内样式
方案2:CSS Modules 默认(不可能的)
方案3:SASS/LESS Modules UMI推荐
方法4:Styled Components CRA推荐 实战相对少
🐝🐝🐝数组常用方法、数组去重至少写3种方案
二阶段面试题一堆
🐝🐝🐝为什么循环的时候要写key
1-提升性能
2-避免出现不可控bug
在 React 中,当我们使用循环渲染列表时,需要给每个列表项添加一个唯一的 key 属性,这是因为 React 在进行渲染时会利用 key 属性来判断哪些元素是新增的、哪些元素是删除的,从而进行最小化的 DOM 操作,提高性能。
具体来说,当列表项的顺序发生变化时,如果没有指定 key 属性,React 可能会将一个旧的列表项误认为是新的列表项,从而导致 DOM 操作不必要的重复。此外,如果列表项的顺序不变,但是有一些项被删除或添加,如果没有指定 key 属性,React 可能会将一个旧的列表项误认为是新的列表项,从而导致 DOM 操作不必要的重复。
因此,为了保证 React 渲染列表时的正确性和性能,需要给每个列表项添加一个唯一的 key 属性,通常使用列表项的 ID 或索引作为 key 属性的值,从而让 React 能够准确地识别每个列表项,进行最小化的 DOM 操作。神龙教主
🐝🐝🐝谈谈你对受控组件、和非受控组件的理解
受控组件:通过react控制表单的输入输出
非受控组件:通过DOM操作表单数据
🐝🐝🐝如何实现组件通信
父传子:props
父传子:children
子传父:调用父的方法
兄弟:状态提升
组件实例:ref =》 属于ref转发、ref引用实现组件通信
children属性 =》也是父传子 超文本
context
状态管理工具:redux、redux-toolkit(RTK)、mobx等
等等
🐝🐝🐝项目跨域是如何解决的?
1、谷歌插件
2、关闭浏览器安全机制
3、服务器声明允许跨域
4、前端代理 也就是修改配置文件
在vue中
a 在根目录创建vue.config.js (不用安装
b 修改api baseURL /api前缀
在react中
a 安装模块
b 在src目录创建src/setupProxy.js
c 修改api baseURL /api前缀
生命周期
🐝🐝🐝react生命周期有哪些&应用场景
问1:react生命周期有哪些
答1:挺多的挂载、更新、卸载等等,然后我常用的就是componentDidMount
问2:具体呢
答2
🐝🐝🐝react16.3新增了哪些、弃用了哪些
新增
弃用
🐝🐝🐝react用来优化性能的是哪一个生命周期,说一下实战如何优化使用
shouldComponentUpdate
避免父组件更新状态或者属性后避免子组件不必要渲染
🐝🐝🐝父组件更新状态或者属性如何避免子组件不必要渲染
通过shouldComponentUpdate
或者直接继承PureComponent
🐝🐝🐝说出新增的生命周期各自应用场景
🐝🐝父子组件mount生命周期执行顺序
函数组件、hooks、含TypeScript
🌛 谈谈你对hooks理解
React Hooks 是 React 16.8 版本中引入的一项新特性,它可以让我们在函数组件中使用 React 的状态和生命周期等功能,从而减少类组件的使用,使代码更加简洁和易于维护。神龙教主
具体来说,Hooks 提供了一些特殊的函数,如 useState、useEffect、useContext 等,这些函数可以让我们在函数组件中使用状态、副作用和上下文等功能。使用 Hooks,我们可以:
状态管理:通过 useState 函数,可以在函数组件中管理状态,而不需要使用类组件的 this.state。useState 接受一个初始状态值,返回一个数组,其中第一个元素是当前状态值,第二个元素是用于更新状态的函数。可以使用解构赋值来获取这两个值。
副作用处理:通过 useEffect 函数,可以在函数组件中处理副作用,如访问 API、更新 DOM 等。useEffect 接受两个参数,第一个参数是一个函数,用于执行副作用,第二个参数是一个数组,用于指定依赖项。当指定的依赖项发生变化时,useEffect 中的函数将被重新执行。
上下文传递:通过 useContext 函数,可以在函数组件中获取上下文信息,而不需要使用类组件的 static contextType。useContext 接受一个上下文对象,返回上下文中的值。
Hooks 还提供了一些其他函数,如 useReducer、useCallback、useMemo、useRef 等,这些函数可以让我们在函数组件中实现更复杂的逻辑和功能。
使用 Hooks 的优点是它能够使代码更加简洁和易于维护,避免了类组件中的一些繁琐的操作,如生命周期函数、this 绑定等。同时,Hooks 也能够提高代码的可读性和可测试性,使代码更加模块化和可复用。
不过,在使用 Hooks 时需要注意,它有一些规则和限制,如只能在函数组件的最顶层使用 Hooks,不能在循环和条件语句中使用 Hooks 等。另外,Hooks 也需要考虑到性能问题,避免过多地进行不必要的副作用和状态更新。
🌛 用hooks 意义
使用 Hooks 的主要意义在于它可以让我们在函数组件中使用 React 的状态、生命周期和其他功能,从而减少类组件的使用,使代码更加简洁和易于维护。
在之前的 React 版本中,我们只能通过类组件来管理状态和处理生命周期等功能。而使用类组件有一些缺点,如需要继承 React.Component、需要在构造函数中绑定 this、需要在生命周期函数中处理副作用等。这些操作使代码变得繁琐和难以理解,同时也容易出现错误。
而使用 Hooks,我们可以直接在函数组件中管理状态和处理副作用等功能,避免了类组件的一些繁琐操作。同时,Hooks 也能够提高代码的可读性和可测试性,使代码更加模块化和可复用。
除此之外,使用 Hooks 还有以下一些优点:
Hooks 可以使代码更加简洁和易于维护。
Hooks 可以提高代码的可读性和可测试性。
Hooks 可以避免一些常见的错误,如忘记绑定 this、在副作用函数中忘记清理等。
Hooks 可以使代码更加模块化和可复用,减少了代码的耦合度。
总之,使用 Hooks 可以使我们的代码更加简洁、易于维护、可读性和可测试性更好,同时也可以避免一些常见的错误,提高代码的质量和可靠性。
🐝🐝🐝 hook种类
useState:用于在函数组件中添加状态管理功能。
useEffect:用于在函数组件中处理副作用,如数据请求、事件监听等。
useContext:用于在函数组件中访问上下文数据。
useReducer:用于在函数组件中实现复杂的状态管理,类似于 Redux。
useCallback:用于在函数组件中缓存回调函数,避免无用的重新渲染。
useMemo:用于在函数组件中缓存计算结果,避免重复计算。
useRef:用于在函数组件中访问 DOM 元素或保存其他数据。
useLayoutEffect:类似于 useEffect,但会在 DOM 更新之前同步调用回调函数。
useImperativeHandle:用于在父组件中访问子组件的实例方法。
useDebugValue:用于在开发阶段输出调试信息。
这些 Hooks 种类可以使函数组件具有类似于类组件的功能,使得函数组件在处理状态、生命周期、副作用等方面更加灵活和强大。同时,Hooks 也可以帮助我们避免一些常见的错误和降低代码的耦合度,从而提高代码的可维护性和可读性。
除了常用的 Hooks 种类,还有一些其他的 Hooks 可以用于特定的场景:
useReducerWithMiddleware:用于在 useReducer 中实现中间件,类似于 Redux。
useEventCallback:用于在函数组件中缓存事件回调函数,避免因为闭包引用导致的性能问题。
useInterval:用于在函数组件中实现定时器功能。
useDebounce:用于在函数组件中实现防抖功能。
useThrottle:用于在函数组件中实现节流功能。
useAsync:用于在函数组件中实现异步请求的状态管理。
useIntersectionObserver:用于在函数组件中观察元素的可见性状态。
usePrevious:用于在函数组件中缓存上一次的状态值。神龙教主
这些 Hooks 可以帮助我们更加方便地处理特定的场景,提高代码的复用性和可读性,同时也可以使得函数组件具有更加强大和灵活的功能。除了以上列举的 Hooks,还有很多其他的自定义 Hooks 可以根据实际需求来编写,从而使得函数组件的编写更加方便和高效。
以下是一些较为高级的 React Hooks:
useLayout:用于获取组件的布局信息,包括宽度、高度、位置等。
useVirtualList:用于优化长列表的性能,只渲染可见区域的部分数据。
useMedia:用于根据媒体查询动态调整组件的样式或行为。
useDrag:用于实现拖拽功能,可以获取拖拽的状态、位置等信息。
useDrop:用于实现拖放功能,可以获取拖放目标的状态、位置等信息。
useTransition:用于实现平滑的动画效果,可以控制组件在进入、退出、更新时的动画效果。
useImmer:用于在函数组件中实现不可变数据的更新,类似于 Immer 库。
useSpeechRecognition:用于实现语音识别功能,可以获取用户的语音输入并进行相应的处理。
useBattery:用于获取设备的电池信息,包括电量、充电状态等。神龙教主
这些高级的 React Hooks 可以帮助我们实现更加复杂和灵活的功能,同时也能够避免一些常见的错误和提高代码的可维护性和可读性。但是需要注意的是,使用这些高级 Hooks 需要具有一定的 React 和 JavaScript 基础知识,并且需要根据具体场景来选择和使用合适的 Hooks。
🐝🐝🐝 你用过哪些 hooks
🐝🐝🐝 自己封装过哪些hook
useLocalStorage:将数据存储到本地存储中,包括设置、获取和删除数据。 神龙教主
useDebounce:防抖动 Hook,用于在用户输入停止后延迟一段时间再执行函数。
useFetch:用于获取数据的 Hook,包括加载中、错误和数据三种状态。
useForm:用于处理表单数据的 Hook,包括设置、获取和重置表单数据。
🐝🐝🐝 useMemo、useCallback 有什么区别
🐝 useRef 需要注意什么
🌛 useRef 和 createRef 有什么区别
等等等
\u4e00-\u9fa5 ↩︎

浙公网安备 33010602011771号