HarmonyOS NEXT开发进阶(五):装饰器讲解
一、@Provide @Consume
父组件与子组件的子组件(官方叫法:后代组件)双向同步数据(即,父组件与后代组件可以相互操作 @Provide 修饰的数据)
注意:@Provide 与 @Consume声明的变量名必须一致。
import {TestChild } from './TestChild'
@Entry //这是一个页面
@Component // 页面中有一个视图容器,即根布局 Row()
struct Index {@Provide msg: string = '混沌'count: number = 0build(){Row(){Column( {space : 20} ) {Text(this.msg).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.msg = 'Hello World ' + (this.count++)})TestChild()}.width('100%')}.height('100%')}
}
TestChild 嵌套 TestChild2, TestChild2嵌套TestChild3
@Component
export struct TestChild{build(){TestChild2(){.width('100%').backgroundColor(Color.Red).align(Alignment.Center)}}
}@Component
export struct TestChild2{build(){TestChild3()}
}@Component
export struct TestChild3{@Consume msg: stringcount: number = 0build(){Column(){Text(this.msg).fontSize(30)Button('TestChild2 更新文字内容').onClick( ()=>{this.msg = 'HarmonyOS - Child' + (this.count++)}) }.backgroundColor(Color.Pink)}
}
二、@Observed @ObjectLink
父组件与嵌套对象或数组进行双向向同步数据。
说明:实际业务研发中,封装好多类(与 @Component 修饰的组件无关),这个时候,如果要让父组件和 嵌套对象进行数据同步,前边所介绍的所有装饰器是无法做到的。
子组件中
@ObjectLink装饰器装饰的状态变量用于接收@Observed装饰的类实例,和父组件中对应的状态变量建立双向数据绑定。单独使用
@Observed是没有任何作用的,需要搭配@ObjectLink或者@Prop初始状态。
// 引起此问题初始化代码
@State b: ClassB = new ClassB(new ClassA(0));
// 修改
@State a: ClassA = new ClassA(0)
@State b: ClassB = new ClassB(a)import {ClassA, ClassB, TestChild } from './TestChild'
@Entry //这是一个页面
@Component //页面中有一个视图容器,即根布局 Row()
struct Index {@State b: ClassB = new ClassB(new ClassA(0));build() {Row() {Column( {space : 20} ) {Text(this.b.a.c + '').fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.b.a.c += 1;})TestChild({a: this.b.a})}.width('100%')}.height('100%')}
}@Component
export struct TestChild {@ObjectLink a: ClassA;build(){Column(){Text(this.a.c + '').fontSize(30)Button('TestChild2 更新文字内容').onClick( ()=>{this.a.c += 1;} )}.backgroundColor(Color.Pink)}
} @Observed
export class ClassA {public c: number;constructor(c: number) {this.c = c;}
}export class ClassB {public a: ClassA;constructor(a: ClassA) {this.a = a;}
}
三、@Watch
关注某个变量状态发生变化。
注意📢:监听的这个变量不要放在回调方法中,让其发生二次变化,容易导致死循环。
import {ClassA, ClassB, TestChild } from './TestChild'@Entry //这是一个页面
@Component //页面中有一个视图容器,即根布局 Row()
struct Index {@State msg: string = '混沌'@State index: number = 0;build(){Row(){Column( {space : 20} ) {Text(this.msg + ' ' + this.index).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.index++})TestChild({count: this.index})}.width('100%')}.height('100%')}
}
NOTE:使用 @Prop 修饰的原因:感知父组件改变 count 值。
@Component
export struct TestChild{@Prop @Watch('onCountUpdated') count: number;@State total: number = 0;// @Watch 回调onCountUpdated(propName: string): void {this.total += 1;}build(){Column(){Text('HarmonyOS - Child' + this.total).fontSize(30)Button('TestChild2 更新文字内容').onClick( ()=>{this.count++})}.backgroundColor(Color.Pink)}
}
四、@LocalStorageLink @LocalStorageProp
LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility内,页面间共享状态。
LocalStorage在场景使用过程中包含了两个装饰器,即@LocalStorageLink 和 @LocalStorageProp。
import { TestChild } from './TestChild';// 创建新实例并使用给定对象初始化
let storage = new LocalStorage({ 'PropA': 47 });// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct Index {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') count: number = 1;build(){Row(){Column( {space : 20} ){Text('混沌 ' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.count++})TestChild() }.width('100%')}.height('100%')}
}@Component
export struct TestChild {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') count: number = 1;build() {Column( {space : 20} ) {Text('HarmonyOS - Child' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('TestChild2 更新文字内容').onClick( ()=>{this.count++}) }.width('100%').backgroundColor(Color.Pink)}
}
总结,本例展示了:
- 使用构造函数创建
LocalStorage实例storage; - 使用
@Entry装饰器将storage添加到 Index 顶层组件中; @LocalStorageLink绑定LocalStorage对给定的属性,建立双向数据同步;
import { TestChild } from './TestChild';// 创建新实例并使用给定对象初始化
let storage = new LocalStorage({ 'PropA': 47 });// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct Index {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageProp('PropA') count: number = 1;build() {Row() {Column( {space : 20} ) {Text('混沌 ' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('Parent 更新文字内容').onClick( ()=>{this.count++})TestChild() }.width('100%')}.height('100%')}
}let storage = LocalStorage.GetShared()@Component
export struct TestChild{// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') count: number = 1;build() {Column( {space : 20} ) {Text('HarmonyOS - Child' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('TestChild2 更新文字内容').onClick( ()=>{this.count++})}.width('100%').backgroundColor(Color.Pink)}
}
@LocalStorageLink(key)是和LocalStorage中key对应的属性建立双向数据同步:
本地修改发生,该修改会被写回LocalStorage中;
LocalStorage中的修改发生后,该修改会被同步到所有绑定LocalStorage对应key的属性上,包括单向(@LocalStorageProp和通过prop创建的单向绑定变量)、双向(@LocalStorageLink和通过link创建的双向绑定变量)变量。
这个例子中TestChild组件使用了@LocalStorageLInk, 当其值发生变化时,会同时影响到父布局使用到 @LocalStorageProp 装饰器的变量值,即 子组件的变量通过LocalStorage可以影响到相应的父组件变量值,但父组件的相关变量值是无法影响到子组件的变量值
五、@StorageLink @StorageProp
AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。
AppStorage在场景使用过程中包含了两个装饰器,即@StorageLink 和 @StorageProp
和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享,还相当于整个应用的“中枢”,持久化数据PersistentStorage和环境变量Environment都是通过和AppStorage中转,才可以和UI交互。
注⚠️:AppStorage 和 LocalStorage是互不影响的!
import { TestChild } from './TestChild';
AppStorage.SetOrCreate('PropA', 47);// 创建新实例并使用给定对象初始化
let storage = new LocalStorage();// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct Index {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@StorageLink('PropA') count: number = 1;@LocalStorageLink('PropA') countL: number = 1;build() {Row(){Column( {space : 20} ) {Text('AppStorage ' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('更新AppStorage内容').onClick( ()=>{this.count++})Text('LocalStorage ' + this.countL).fontSize(30).fontWeight(FontWeight.Bold)Button('更新LocalStorage内容').onClick( ()=>{this.countL++})TestChild() }.width('100%')}.height('100%')}
}@Component
export struct TestChild {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@StorageLink('PropA') count: number = 1;build(){Column( {space : 20} ) {Text('HarmonyOS - Child' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('TestChild2 更新文字内容').onClick( ()=>{this.count++})}.width('100%').backgroundColor(Color.Pink) }
}
六、@Builder
@Builder 用于UI元素复用,开发者可以将重复使用的UI元素抽象成一个方法,在build方法里调用。
总结
- 值引用方式,可以感知父组件的状态变化;
- 值传递方式,无法感知父组件的状态变化;
@Entry
@Component
struct Index {@State count: number = 1;@Builder BuilderOne($$: { paramA1: number }) {Column() {Text(`组件1值引用: ${$$.paramA1} `).fontSize(20)}.width('100%').backgroundColor(Color.Pink)}@Builder BuilderTwo(paramA1: number) {Column() {Text(`组件2值传递: ${paramA1} `).fontSize(20)}.width('100%').backgroundColor(Color.Pink)}build() {Row() {Column({ space: 20 }) {Text('混沌 ' + this.count).fontSize(30).fontWeight(FontWeight.Bold)Button('更新').onClick(() => {this.count++})this.BuilderOne({ paramA1: this.count })this.BuilderTwo(this.count)}.width('100%')}.height('100%')}
}
七、@BuilderParam
当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。
import Prompt from '@system.prompt';
import { TestChild } from './TestChild';@Entry
@Component
struct Index {@Builder BuilderOne() {TestChild( {msg: 'BuilderOne 视图'} ) {Text('1').fontColor(Color.Red)}}@Builder BuilderTwo() {Stack(){TestChild( {msg: 'BuilderTwo 视图'} ) {Text('1').fontColor(Color.Red)Text('2').fontColor(Color.Red)}}.onClick( () => {Prompt.showToast({message: '点了 BuilderTwo'})})}@BuilderParam aBuilder0: () => void = this.BuilderOne@BuilderParam aBuilder1: () => void = this.BuilderTwobuild(){Column({ space: 20 }) {this.aBuilder0()this.aBuilder1()TestChild( {msg: '中国'} ) {Text('1').fontColor(Color.Red)})}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}}@Component
export struct TestChild {msg: string@BuilderParam aB0: () => {}build(){Column( {space : 20} ) {this.aB0()Text('TestChild上下有 '+ this.msg).fontSize(20).fontWeight(FontWeight.Bold) this.aB0() }.width('100%').backgroundColor(Color.Pink)}
}
@BuilderParam 既可以指向一个对象, 也可以指向@Builder修饰的方法;
带占位的自定义视图是没法响应onClick事件的,所以在上面的示例中,将子组件外边再添加了一个容器组件,用来进行点击事件响应
八、@Styles
如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,可使用装饰器@Styles。
import Prompt from '@system.prompt';@Entry
@Component
struct Index {//仅支持公共属性@Styles fancy() {.width(200).height(300).backgroundColor(Color.Pink).onClick(() => {Prompt.showToast({message: 'I am fancy'})})}build() {Column({ space: 20 }) {Text('Styles').textAlign(TextAlign.Center).fancy()}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}
}
总结
@Styles当前仅支持通用属性;@Styles修饰的方法不支持参数;- 引用**@Styles** 修饰的方法时,建议放在最后,比如:
Text().fancy().textAlign(....)应该变为Text().textAlign(....) .fancy()
九、@Extend
用于扩展原生组件样式。
注意⚠️:
- 原生指的是
ArkTS写的组件扩展,不是新定义增加不存在的属性:
import Prompt from '@system.prompt';//仅支持公共属性
@Styles function fancy() {.width(200).height(300).backgroundColor(Color.Pink).onClick(() => {Prompt.showToast({message: 'I am fancy'})})
}@Extend(Text) function superFancy(size:number, onClick?: () => void) {.fontSize(size).textAlign(TextAlign.Center).fancy().onClick(onClick)
}@Entry
@Component
struct Index {onClickHandler() {Prompt.showToast({message: 'fancy出去了'})}build(){Column({ space: 20 }) {Text('Styles').superFancy(30, this.onClickHandler.bind(this))}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}
}
总结
@Extend在@Styles基础上,增加了传参特性;@Extend必须定义为全局;- 支持封装指定组件的私有属性和私有事件和预定义相同组件的
@Extend的方法;
十、@Concurrent
在使用TaskPool时,执行的并发函数需要使用该装饰器修饰,否则无法通过相关校验。
import taskpool from '@ohos.taskpool';@Concurrent
function add(num1: number, num2: number): number {return num1 + num2;
}async function ConcurrentFunc(): Promise<void> {try {let task: taskpool.Task = new taskpool.Task(add, 1, 2);console.info("taskpool res is: " + await taskpool.execute(task));}catch (e) {}
}@Entry
@Component
struct Index {@State message: string = 'Hello World'build(){Row(){Column(){Text(this.message).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {ConcurrentFunc();})}.width('100%')}.height('100%')}
}
十一、拓展阅读
- 《HarmonyOS 进阶专栏》
相关文章:
HarmonyOS NEXT开发进阶(五):装饰器讲解
一、Provide Consume 父组件与子组件的子组件(官方叫法:后代组件)双向同步数据(即,父组件与后代组件可以相互操作 Provide 修饰的数据) 注意:Provide 与 Consume声明的变量名必须一致。 import {TestChild } from .…...
【编译原理】往年题汇总(山东大学软件学院用)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀编译原理_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. …...
【漏洞复现】F5 BIG-IP Next Central Manager SQL注入漏洞(CVE-2024-26026)
免责声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。工具来自网络,安全性自测,如有侵权请联系删除。本次测试仅供学习使用,如若非法他用,与平台和本文作…...
设计模式-创建型-单例模式
1. 单例模式简介 单例模式(Singleton Pattern)是一种常见的创建型设计模式,它确保一个类只有一个实例,并提供全局访问点。在很多情况下,我们只希望某个类在整个应用程序中有一个唯一的实例,且该实例需要在…...
VBA技术资料MF243:利用第三方软件复制PDF数据到EXCEL
我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…...
【2024最新】基于Python+Mysql+django的水果销售系统Lw+PPT
作者:计算机搬砖家 开发技术:SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:Java精选实战项…...
一种寻路的应用
应用背景 利用长途车进行货物转运的寻路计算。例如从深圳到大连。可以走有很多条长途车的路线。需要根据需求计算出最合适路线。不同的路线的总里程数、总价、需要的时间不一样。客户根据需求进行选择。主要有一些细节: 全国的长途车车站的数据的更新: …...
编译openssl遇到错误Parse errors: No plan found in TAP output的解决方法
在编译openssl时 tar -zxvf openssl-1.1.1p.tar.gz cd openssl-1.1.1p ./config --prefix/usr --openssldir/etc/ssl --shared zlib make make test 遇到错误 Parse errors: No plan found in TAP output 解决方法: yum install perl-Test-Simple...
一文大白话讲清楚防抖和节流,设计封装防抖和节流,以及防抖和节流的应用场景
文章目录 一文大白话讲清楚防抖和节流,设计封装防抖和节流,以及防抖和节流的应用场景1. 防抖和节流的背景2. 节流3. 节流的应用场景4. 防抖5. 防抖应用场景 一文大白话讲清楚防抖和节流,设计封装防抖和节流,以及防抖和节流的应用场…...
Windows开启IIS后依然出现http error 503.the service is unavailable
问题背景 已启用IIS服务,配置步骤可以参考Windows10 IIS Web服务器安装配置 问题描述 在这一步浏览网站时,并没有出现默认首页,而是 http error 503 the service is unavailable 问题解决 参考 成功解决http error 503.the service is un…...
C++的封装(十四):《设计模式》这本书
很多C学习者学到对C语言有一定自信后,会去读一下《设计模式》这本书。希望能够提升自己的设计水平。 据我所知,围绕C语言出了很多书。因为正好赶上泡沫经济时代。大家一拥而上,自己半懂不懂就出书,抢着出书收割读者,出…...
牛客周赛73B:JAVA
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 \hspace{15pt}小红拿到了正整数 xxx ,她希望你找到一个长度为 kkk 的区间,满足区间内恰好有 nnn 个数是 xxx 的倍数。你能帮帮她吗? 输入描述: …...
【Ubuntu 20.4安装截图软件 flameshot 】
步骤一: 安装命令: sudo apt-get install flameshot 步骤二: 设置快捷方式: Ubuntu20.4 设置菜单,点击 号 步骤三: 输入软件名称, 软件快捷命令(flameshot gui)&am…...
剑指Offer|LCR 014. 字符串的排列
LCR 014. 字符串的排列 给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的某个变位词。 换句话说,第一个字符串的排列之一是第二个字符串的 子串 。 示例 1: 输入: s1 "ab" s2 "eidbaooo" 输出: True 解…...
【Agent】Chatbot、Copilot与Agent如何帮助我们的提升效率?
人工智能(AI)技术的迅猛发展正在深刻改变我们的生活和工作方式。你是否曾想过,未来的工作场景会是什么样子?AI的崛起不仅仅是科技的进步,更是我们生活方式的革命。今天,我们将深入探讨三种主要的AI能力&…...
QT笔记- QTreeView + QFileSystemModel 当前位置的保存与恢复 #选中 #保存当前索引
保存当前位置 QString currentPath model->filePath(view->currentIndex()); // 获得当前位置路径 恢复位置 view->setCurrentIndex(model->index(currentPath)); // 设置此路径所在位置为当前位置...
OpenResty开发环境搭建
简介 OpenResty 是一个基于 Nginx的高性能 Web 平台,用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。官方地址:http://openresty.org/cn/ 具备下列特点: 具备Nginx的完整功能基于Lua语言进行扩展&#…...
linux提示结构需要清理
1. df -hT 查看出问题的文件夹所在的挂载磁盘及文件格式 2. umount 挂载磁盘,如果提示在忙, lsof 目录查看正在使用的进程,将其kill掉 3. 修复磁盘 根据文件格式修复磁盘fsck.ext4 /dev/sda1 或者 xfs_repair /dev/sda1 4. 重启系统 “结构需要清理…...
【扩展卡尔曼滤波理论推导与实践】【理论】【2/3 公式推导】
目录 非线性系统泰勒展开卡尔曼滤波卡尔曼增益模型误差协方差矩阵 公式总结 本节默认你能够完整推导标准卡尔曼滤波,将会简化一些推导的描述。如果你还不会完整推导标准卡尔曼滤波,请先从 【卡尔曼滤波理论推导与实践】系列开始看起。 非线性系统 扩展…...
springboot494基于java的综合小区管理系统(论文+源码)_kaic
摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统综合小区管理系统信息管理难度大,容错率低&am…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...
