HarmonyOS官网案例解析——保存应用数据

介绍

本篇Codelab将介绍如何使用基础组件Slider,通过拖动滑块调节应用内字体大小。要求完成以下功能:

  1. 实现两个页面的UX:主页面和字体大小调节页面。
  2. 拖动滑块改变字体大小系数,列表页和调节页面字体大小同步变化。往右拖动滑块字体变大,反之变小。
  3. 字体大小支持持久化存储,再次启动时,应用内字体仍是调节后的字体大小。

最终效果图如图所示:

https://gitee.com/runitwolf/sloop-pic-go/raw/master/image/202312212240377.gif

一、相关概念

  • 字体大小调节原理:通过组件Slider滑动,获取滑动数值,将这个值通过首选项进行持久化,页面的字体通过这个值去改变大小。
  • 首选项:首选项为应用提供Key-Value键值型的数据处理能力,支持应用持久化轻量级数据,并对其修改和查询。

二、完整实例

gitee源码地址

ps:官网的案例很简单,但是有很多地方值得我们借鉴。

官方对案例解析

<HarmonyOS第一课>保存应用数据

三、零基础实战开发

一、用数组的方法值得借鉴

  1. 现新建一个bean类
export default class SettingData{settingName:stringsettingImage:Resource
}
  1. 新建HomeViewModel.etx
import SettingData from './SettingData'export class HomeViewModel {settingArr: SettingData[] = []initSettingData(): SettingData[] {if (this.settingArr.length === 0) {let settingData = new SettingData()settingData.settingName = '显示和亮度'settingData.settingImage = $r('app.media.ic_display_and_brightness')this.settingArr.push(settingData)settingData = new SettingData();settingData.settingName = '声音';settingData.settingImage = $r('app.media.ic_voice');this.settingArr.push(settingData);settingData = new SettingData();settingData.settingName = '应用管理';settingData.settingImage = $r('app.media.ic_app_management');this.settingArr.push(settingData);settingData = new SettingData();settingData.settingName = '存储';settingData.settingImage = $r('app.media.ic_storage');this.settingArr.push(settingData);settingData = new SettingData();settingData.settingName = '隐私';settingData.settingImage = $r('app.media.ic_privacy');this.settingArr.push(settingData);settingData = new SettingData();settingData.settingName = '设置字体大小';settingData.settingImage = $r('app.media.ic_setting_the_font_size');this.settingArr.push(settingData);}return this.settingArr}
}
export default new HomeViewModel()

在index.ets中直接使用即可使用方法如下

 settingArr = HomeViewModel.initSettingData();//settingArr[x],x为数组的索引,直接使用就可以获取设定的数据

1."标题"页面实现

import { TitleBarComponent } from '../view/TitleBarComponent'@Entry
@Component
struct Index {build() {Column() {TitleBarComponent({ isBack: false, title: '设置' })}.width('100%').height('100%')}
}
import router from '@ohos.router'
@Component
export struct TitleBarComponent {isBack:boolean = truetitle:string = ''build() {Row() {if (this.isBack){Image($r('app.media.ic_public_back')).width(24).height(24).margin({ right: 4 }).onClick(() => {router.back()})}Text(this.title).fontColor(Color.Black).fontSize($r('sys.float.ohos_id_text_size_headline8')).fontWeight(FontWeight.Medium).margin({ left: 8 })}.width('100%').height('7.2%').padding({ left: 16 })}
}

在这里插入图片描述

2."显示和亮度"页面实现

import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'@Entry
@Component
struct Index {settingArr: SettingData[] = HomeViewModel.initSettingData()@State changeFontSize: number = 16build() {Column() {...//显示和亮度Row() {SettingItemComponent({setting: this.settingArr[0],changeFontSize: this.changeFontSize,itemClick: () => {//TODO}})}.blockBackground('1.5%')}.backgroundColor('#f1f3f5').width('100%').height('100%')}
}@Extend(Row) function blockBackground (marginTop: string) {.backgroundColor(Color.White).borderRadius(24).margin({ top: marginTop }).width('93.3%').padding({ top: 4, bottom: 4 })
}

思考题:这里的changeFontSize变量为什么需要用@State进行修饰,而settingArr又为什么不需要?

3."声音"页面实现

import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'@Entry
@Component
struct Index {build() {Column() {TitleBarComponent({ isBack: false, title: '设置' })...//声音Row() {SettingItemComponent({setting: this.settingArr[1],changeFontSize: this.changeFontSize,itemClick: () => {//TODO}})}.blockBackground('1.5%')}.backgroundColor('#f1f3f5').width('100%').height('100%')}
}

4.“应用管理”、"存储"等列表页面实现

import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'@Entry
@Component
struct Index {settingArr: SettingData[] = HomeViewModel.initSettingData()@State changeFontSize: number = 16build() {Column() {...Row(){this.SettingItems()}.blockBackground('1.5%')}...}@Builder SettingItems(){List(){ForEach(this.settingArr.splice(2,6),(item:SettingData,index:number)=>{ListItem(){SettingItemComponent({setting:item,changeFontSize:this.changeFontSize,itemClick:()=>{//TODO}})}}, (item:SettingData,index:number)=>JSON.stringify(item)+index)}}
}

5."设置字体大小"点击事件跳转

import router from '@ohos.router'
import PreferencesUtil from '../common/database/PreferencesUtil'
import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'@Entry
@Component
struct Index {settingArr: SettingData[] = HomeViewModel.initSettingData()@State changeFontSize: number = 16onPageShow(){PreferencesUtil.getChangeFontSize().then((value)=>{this.changeFontSize = value})}build() {....@Builder SettingItems(){List(){ForEach(this.settingArr.splice(2,6),(item:SettingData,index:number)=>{ListItem(){SettingItemComponent({setting:item,changeFontSize:this.changeFontSize,itemClick:()=>{if (index === 3) {router.pushUrl({url:"pages/SetFontSizePage"})}}})}}, (item:SettingData,index:number)=>JSON.stringify(item)+index)}}
}

在pages目录下新建SetFontSizePage子组件

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'@Entry
@Component
struct SetFontSizePage {build() {Column() {TitleBarComponent({ title: '字体大小设置' })}.width('100%').height('100%')}
}

ps:官网的案例不太友好,我们在官网的页面基础上进行功能及界面简化

6.SetFontSizePage页面创建数据

我们之前在首页HomeViewModel模型下创建过数据,我们沿用HomeViewModel模型,继续创建想要的数据

import SettingData from './SettingData'export class HomeViewModel {...fontSizeArr: SettingData[] = []...initFontSizeData():SettingData[]{this.fontSizeArr = new Array();let fontSizeArr = new SettingData()fontSizeArr.settingName = '11111111111111111111'this.fontSizeArr.push(fontSizeArr)fontSizeArr = new SettingData()fontSizeArr.settingName = '22222222222222222222'this.fontSizeArr.push(fontSizeArr)fontSizeArr = new SettingData()fontSizeArr.settingName = '33333333333333333333'this.fontSizeArr.push(fontSizeArr)fontSizeArr = new SettingData()fontSizeArr.settingName = '44444444444444444444'this.fontSizeArr.push(fontSizeArr)return this.fontSizeArr}
}
export default new HomeViewModel()

7.写SetFontSizePage中list页面

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'@Entry
@Component
struct SetFontSizePage {contentArr: SettingData[] = HomeViewModel.initFontSizeData()@State changeFontSize: number = 0onPageShow(){PreferencesUtil.getChangeFontSize().then((value)=>{this.changeFontSize = value})}build() {Column() {TitleBarComponent({ title: '字体大小设置' })List() {ForEach(this.contentArr, (item: SettingData, index: number) => {ListItem() {ItemComponent({ contentArr: item, changeFontSize: this.changeFontSize })}}, (item: SettingData, index: number) => JSON.stringify(item) + index)}}.width('100%').height('100%')}
}
import SettingData from '../viewmodel/SettingData'
@Component
export struct ItemComponent {contentArr: SettingData@Prop changeFontSize:numberbuild() {Column() {Text(this.contentArr.settingName).fontSize(this.changeFontSize).fontColor('#182431').fontWeight(FontWeight.Medium).height(48).width('100%').textAlign(TextAlign.Center)}}
}

看看list的效果图:

8.写SetFontSizePage进度条

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'@Entry
@Component
struct SetFontSizePage {...build() {Column() {...List() {...}SliderLayout({changeFontSize:$changeFontSize})}...}
}
import PreferencesUtil from '../common/database/PreferencesUtil'
@Component
export struct SliderLayout {@Link changeFontSize:numberbuild() {Column() {Text('文字大小').fontSize(14).fontColor('#182431').fontWeight(FontWeight.Medium)Row(){Text('A').fontColor('#182431').fontSize(20).fontWeight(FontWeight.Medium).textAlign(TextAlign.End).width('12.5%').padding({right:9})Slider({value:this.changeFontSize,min:14,max:22,step:2,style:SliderStyle.InSet}).showSteps(true).width('75%').onChange((value:number)=>{this.changeFontSize = value})Text('A').fontColor('#182431').fontSize(20).fontWeight(FontWeight.Medium).width('12.5%').padding({left:9})}}}
}

运行后效果图如下:
在这里插入图片描述

至此,我们发现滑动进度条,页面的大小变了,但是返回页面后再次进入,数据没有保存。

四、保存应用数据

<HarmonyOS第一课>保存应用数据(官网文档)

根据官网的文档,我们新建PreferencesUtil工具类

import dataPreferences from '@ohos.data.preferences';
import { GlobalContext } from '../utils/GlobalContext';
import Logger from '../utils/Logger';const TAG = '[PreferencesUtil]';
const PREFERENCES_NAME = 'myPreferences';
const KEY_APP_FONT_SIZE = 'appFontSize';/*** The PreferencesUtil provides preferences of create, save and query.*/
export class PreferencesUtil {createFontPreferences(context: Context) {let fontPreferences: Function = (() => {let preferences: Promise<dataPreferences.Preferences> = dataPreferences.getPreferences(context, PREFERENCES_NAME);return preferences;});GlobalContext.getContext().setObject('getFontPreferences', fontPreferences);}saveDefaultFontSize(fontSize: number) {let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;getFontPreferences().then((preferences: dataPreferences.Preferences) => {preferences.has(KEY_APP_FONT_SIZE).then(async (isExist: boolean) => {Logger.info(TAG, 'preferences has changeFontSize is ' + isExist);if (!isExist) {await preferences.put(KEY_APP_FONT_SIZE, fontSize);preferences.flush();}}).catch((err: Error) => {Logger.error(TAG, 'Has the value failed with err: ' + err);});}).catch((err: Error) => {Logger.error(TAG, 'Get the preferences failed, err: ' + err);});}saveChangeFontSize(fontSize: number) {let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;getFontPreferences().then(async (preferences: dataPreferences.Preferences) => {await preferences.put(KEY_APP_FONT_SIZE, fontSize);preferences.flush();}).catch((err: Error) => {Logger.error(TAG, 'put the preferences failed, err: ' + err);});}async getChangeFontSize() {let fontSize: number = 0;let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;fontSize = await (await getFontPreferences()).get(KEY_APP_FONT_SIZE, fontSize);return fontSize;}async deleteChangeFontSize() {let getFontPreferences: Function = GlobalContext.getContext().getObject('getFontPreferences') as Function;const preferences: dataPreferences.Preferences = await getFontPreferences();let deleteValue = preferences.delete(KEY_APP_FONT_SIZE);deleteValue.then(() => {Logger.info(TAG, 'Succeeded in deleting the key appFontSize.');}).catch((err: Error) => {Logger.error(TAG, 'Failed to delete the key appFontSize. Cause: ' + err);});}
}export default new PreferencesUtil();
export class GlobalContext {private constructor() { }private static instance: GlobalContext;private _objects = new Map<string, Object>();public static getContext(): GlobalContext {if (!GlobalContext.instance) {GlobalContext.instance = new GlobalContext();}return GlobalContext.instance;}getObject(value: string): Object | undefined {return this._objects.get(value);}setObject(key: string, objectClass: Object): void {this._objects.set(key, objectClass);}
}

1.使用前提

需要在entryAbility的onCreate方法获取首选项实例

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Logger from '../common/utils/Logger';
import { GlobalContext } from '../common/utils/GlobalContext';
import PreferencesUtil from '../common/database/PreferencesUtil'export default class EntryAbility extends UIAbility {onCreate(want, launchParam) {PreferencesUtil.createFontPreferences(this.context);}...
}

2.保存数据

在应用刚启动时,设置字体默认大小

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import Logger from '../common/utils/Logger';
import { GlobalContext } from '../common/utils/GlobalContext';
import PreferencesUtil from '../common/database/PreferencesUtil'export default class EntryAbility extends UIAbility {onCreate(want, launchParam) {...// 设置字体默认大小PreferencesUtil.saveDefaultFontSize(16);}...
}

在滑动进度条后,保存进度条设置的字体大小

import PreferencesUtil from '../common/database/PreferencesUtil'
@Component
export struct SliderLayout {@Link changeFontSize:numberbuild() {...Slider({....onChange((value:number)=>{this.changeFontSize = valuePreferencesUtil.saveChangeFontSize(this.changeFontSize)})...}}}
}

3.获取保存的数据

数据都保存了,我们怎么去使用保存的数据呢?

import  PreferencesUtil  from '../common/database/PreferencesUtil'
import { ItemComponent } from '../view/ItemComponent'
import { SliderLayout } from '../view/SliderLayout'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'@Entry
@Component
struct SetFontSizePage {...@State changeFontSize: number = 0onPageShow(){PreferencesUtil.getChangeFontSize().then((value)=>{this.changeFontSize = value})}}
import router from '@ohos.router'
import PreferencesUtil from '../common/database/PreferencesUtil'
import SettingItemComponent from '../view/SettingItemComponent'
import { TitleBarComponent } from '../view/TitleBarComponent'
import HomeViewModel from '../viewModel/HomeViewModel'
import SettingData from '../viewModel/SettingData'@Entry
@Component
struct Index {...@State changeFontSize: number = 16onPageShow(){PreferencesUtil.getChangeFontSize().then((value)=>{this.changeFontSize = value})}...
}
...

效果图:
在这里插入图片描述

至此,大功告成~~~撒花

至此,所有功能已全部完成。

代码链接:https://gitee.com/runitwolf/set-app-font-size

typora笔记链接:https://gitee.com/runitwolf/set-app-font-size/blob/master/%E5%BA%94%E7%94%A8%E5%86%85%E5%AD%97%E4%BD%93%E5%A4%A7%E5%B0%8F%E8%B0%83%E8%8A%82.md

CSDN typora笔记链接 :https://download.csdn.net/download/qq_36067302/88671288

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/591197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux安装consul的两种方式(在线和离线)

目录 &#x1f4da;第一章 前言&#x1f4d7;背景&#x1f4d7;软件概述 &#x1f4da;第二章 部署&#x1f4d7;在线部署&#x1f4d5;需要root权限&#x1f4d5;执行安装命令&#x1f4d5;启动consul服务&#x1f4d5;验证consul服务 &#x1f4d7;离线部署&#x1f4d5;下载…

(九)上市企业实施IPD成功案例分享之——欧普

LED通用照明应用是LED照明应用市场的第一驱动力&#xff0c;由于LED照明技术发展迅速&#xff0c;以及成本快速下降&#xff0c;已成为全球主流照明光源。近年来&#xff0c;通过将智能控制模块嵌入LED通用照明终端&#xff0c;形成了具有自动控制、系统化控制等功能的智能照明…

听GPT 讲Rust源代码--library/panic_unwind

File: rust/library/panic_unwind/src/seh.rs 在Rust源代码中&#xff0c;rust/library/panic_unwind/src/seh.rs这个文件的作用是实现Windows操作系统上的SEH&#xff08;Structured Exception Handling&#xff09;异常处理机制。 SEH是Windows上的一种异常处理机制&#xff…

EDI 项目推进流程

EDI 需求确认 交易伙伴发来EDI对接邀请&#xff0c;企业应该如何应对&#xff1f; 首先需要确认EDI需求&#xff0c;通常包括传输协议和报文标准以及传输的业务单据类型。可以向交易伙伴发送以下内容&#xff1a; &#xff08;中文版&#xff09; 与贵司建立EDI连接需要使用…

【没有哪个港口是永远的停留~论文解读】stable diffusion

了解整个流程&#xff1a; 【第一部分】输入图像 x &#xff08;W*H*3的RGB图像&#xff09;【第一部分】x 经过编码器 生成 (latent 空间的表示) h*w*c (具体设置多少有实验)【第二部分】 逐步加噪得到 &#xff0c;和噪声标签【第二部分】由 Unet&#xff08; &#xff…

Kubernetes(k8s):Namespace详解

Kubernetes&#xff08;k8s&#xff09;&#xff1a;Namespace详解 一、Namespace简介1.1 什么是Namespace1.2 Namespace的作用1.3 命名空间的分类 二、创建和管理Namespace2.1 创建Namespace2.2 管理Namespace 三、Namespace的实战应用3.1 部署多个项目3.2 环境隔离3.3 资源配…

从零开始配置kali2023环境:配置jupyter的多内核环境

在kali2023上面尝试用anaconda3&#xff0c;anaconda2安装实现配置jupyter的多内核环境时出现各种问题&#xff0c;现在可以通过镜像方式解决 1. 搜索镜像 ┌──(holyeyes㉿kali2023)-[~] └─$ sudo docker search anaconda ┌──(holyeyes㉿kali2023)-[~] └─$ sudo …

C++初阶——权限与继承

目录 一、C权限方面的问题 1.访问权限 2.继承机制 二、Cconst引用 const引用有以下几个特点 临时对象引用 常量引用成员变量 二、c引用空间相关问题 三.auto 一、C权限方面的问题 【C入门】访问权限管控和继承机制详解_权限继承功能-CSDN博客文章浏览阅读840次。(2)但…

YOLOv8训练自己的数据集(超详细)

一、准备深度学习环境 本人的笔记本电脑系统是&#xff1a;Windows10 YOLO系列最新版本的YOLOv8已经发布了&#xff0c;详细介绍可以参考我前面写的博客&#xff0c;目前ultralytics已经发布了部分代码以及说明&#xff0c;可以在github上下载YOLOv8代码&#xff0c;代码文件夹…

LVM和磁盘配额

一&#xff1a;LVM概述&#xff1a; LVM 是 Logical Volume Manager 的简称&#xff0c;译为中文就是逻辑卷管理。 能够在保持现有数据不变的情况下&#xff0c;动态调整磁盘容量&#xff0c;从而提高磁盘管理的灵活性 /boot 分区用于存放引导文件&#xff0c;不能基于LVM创建…

MongoDB vs MySQL:项目选择哪一个数据库系统?

由于市场上有各种可用的数据库&#xff0c;用户经常会就MongoDB与MySQL进行辩论&#xff0c;以找出更好的选择。 使用MySQL等关系数据库的组织在根据不断变化的需求管理和存储数据时可能会面临一定的困难。同时&#xff0c;新公司想知道选择什么数据库&#xff0c;这样他们就不…

【ArcGIS微课1000例】0085:甘肃省白银市平川区4.9级地震震中位置图件制作

据中国地震台网正式测定,12月31日22时27分在甘肃白银市平川区发生4.9级地震,震源深度10公里,震中位于北纬36.74度,东经105.00度。 文章目录 一、白银市行政区划图1. 县级行政区2. 乡镇行政区二、4.9级地震图件制作1. 震中位置2. 影像图3. 震中三维地形一、白银市行政区划图…

【LLM 】7个基本的NLP模型,为ML应用程序赋能

在上一篇文章中&#xff0c;我们已经解释了什么是NLP及其在现实世界中的应用。在这篇文章中&#xff0c;我们将继续介绍NLP应用程序中使用的一些主要深度学习模型。 BERT 来自变压器的双向编码器表示&#xff08;BERT&#xff09;由Jacob Devlin在2018年的论文《BERT:用于语言…

数据结构初阶之栈和队列(C语言版)

数据结构初阶之栈和队列&#xff08;C语言版&#xff09; ✍栈♈栈的结构设计♈栈的各个接口的实现&#x1f47a;StackInit(初始化)&#x1f47a;push&#xff08;入栈&#xff09;&#x1f47a;pop&#xff08;出栈&#xff09;&#x1f47a;获取栈顶元素&#x1f47a;获取栈中…

软件工程期末总结

软件工程期末总结 软件危机出现的原因软件生命周期软件生命周期的概念生命周期的各个阶段 软件开发模型极限编程 可行性研究与项目开发计划需求分析结构化分析的方法结构化分析的图形工具软件设计的原则用户界面设计结构化软件设计面向对象面向对象建模 软件危机出现的原因 忽视…

7.13N皇后(LC51-H)

算法&#xff1a; N皇后是回溯的经典题 画树&#xff1a; 假设N3 皇后们的约束条件&#xff1a; 不能同行不能同列不能同斜线 回溯三部曲&#xff1a; 1.确定函数参数和返回值 返回值&#xff1a;void 参数&#xff1a; int n&#xff1a;题目给出&#xff0c;N皇后的…

骨传导蓝牙耳机什么牌子好用?为你揭晓不踩雷的骨传导耳机排行

喜欢运动的朋友们&#xff0c;你们一定不能错过骨传导耳机&#xff01;它真的是我们运动时的好帮手。为什么这么说呢&#xff1f;因为它不会像普通耳机那样塞住我们的耳朵&#xff0c;让我们在运动时感觉不舒服&#xff0c;甚至伤害耳朵。而且&#xff0c;它还可以帮助我们听到…

如何选择适用于光束分析应用的工业相机?

为光束质量分析系统选择合适的相机时&#xff0c;需要考虑许多关键特性。例如&#xff1a; ◈ 合适的波长范围&#xff1a;支持准确拍摄和测量所需波长的光束。 ◈ 高空间分辨率&#xff1a;更好地分析光束特征&#xff0c;如光束宽度、形状和强度分布。 ◈ 合适的传感器尺寸…

ClickHouse基础知识(七):ClickHouse的分片集群

副本虽然能够提高数据的可用性&#xff0c;降低丢失风险&#xff0c;但是每台服务器实际上必须容纳全量数据&#xff0c;对数据的横向扩容没有解决。 要解决数据水平切分的问题&#xff0c;需要引入分片的概念。通过分片把一份完整的数据进行切 分&#xff0c;不同的分片分布到…

Sectigo和Certum的区别

为了保护用户在互联网的隐私&#xff0c;网站使用SSL数字证书为http明文传输协议加上安全套接层&#xff0c;对网站传输数据加密。Sectigo和Certum是正规的CA认证机构&#xff0c;它们颁发的SSL证书经过市场认证&#xff0c;已经兼容大多数浏览器以及终端&#xff0c;今天就随S…