28、鸿蒙Harmony Next开发:不依赖UI组件的全局气泡提示 (openPopup)和不依赖UI组件的全局菜单 (openMenu)、Toast

目录

不依赖UI组件的全局气泡提示 (openPopup)

弹出气泡

创建ComponentContent

绑定组件信息

设置弹出气泡样式

更新气泡样式

关闭气泡

在HAR包中使用全局气泡提示

不依赖UI组件的全局菜单 (openMenu)

弹出菜单

创建ComponentContent

绑定组件信息

设置弹出菜单样式

更新菜单样式

关闭菜单

在HAR包中使用全局菜单

Toast

使用建议

即时反馈模式对比

创建即时反馈

显示关闭即时反馈


不依赖UI组件的全局气泡提示 (openPopup)

气泡提示(Popup)在使用时依赖绑定UI组件,否则无法使用。从API version 18开始,可以通过使用全局接口openPopup的方式,在无UI组件的场景下直接或封装使用,例如在事件回调中使用或封装后对外提供能力。

弹出气泡

通过openPopup可以弹出气泡。

promptAction.openPopup(contentNode, { id: targetId }, {enableArrow: true
}).then(() => {console.info('openPopup success');}).catch((err: BusinessError) => {console.error('openPopup error: ' + err.code + ' ' + err.message);})

创建ComponentContent

通过调用openPopup接口弹出其气泡,需要提供用于定义自定义弹出框的内容ComponentContent。其中,wrapBuilder(buildText)封装自定义组件,new Params(this.message)是自定义组件的入参,可以缺省,也可以传入基础数据类型。

private contentNode: ComponentContent<Object> = new ComponentContent(uiContext, wrapBuilder(buildText), this.message);

如果在wrapBuilder中包含其他组件(例如:Popup、Chip组件),则ComponentContent应采用带有四个参数的构造函数constructor,其中options参数应传递{ nestingBuilderSupported: true }。

@Builder
export function buildText(params: Params) {Popup({// 类型设置图标内容icon: {image: $r('app.media.app_icon'),width: 32,height: 32,fillColor: Color.White,borderRadius: 10} as PopupIconOptions,// 设置文字内容title: {text: `This is a Popup title 1`,fontSize: 20,fontColor: Color.Black,fontWeight: FontWeight.Normal} as PopupTextOptions,// 设置文字内容message: {text: `This is a Popup message 1`,fontSize: 15,fontColor: Color.Black} as PopupTextOptions,// 设置按钮内容buttons: [{text: 'confirm',action: () => {console.info('confirm button click');},fontSize: 15,fontColor: Color.Black,},{text: 'cancel',action: () => {console.info('cancel button click');},fontSize: 15,fontColor: Color.Black},] as [PopupButtonOptions?, PopupButtonOptions?]})
}let contentNode: ComponentContent<Object> = new ComponentContent(uiContext, wrapBuilder(buildText), this.message, { nestingBuilderSupported: true });

绑定组件信息

通过调用openPopup接口弹出气泡,需要提供绑定组件的信息TargetInfo。若未传入有效的target,则无法弹出气泡。

let frameNode: FrameNode | null = this.ctx.getFrameNodeByUniqueId(this.getUniqueId());
let targetId = frameNode?.getChild(0)?.getUniqueId();

设置弹出气泡样式

通过调用openPopup接口弹出气泡,可以设置PopupCommonOptions属性调整气泡样式。

private options: PopupCommonOptions = { enableArrow: true };

更新气泡样式

通过updatePopup可以更新气泡的样式。支持全量更新和增量更新其气泡样式,不支持更新showInSubWindow、focusable、onStateChange、onWillDismiss和transition。

promptAction.updatePopup(contentNode, {enableArrow: false
}, true).then(() => {console.info('updatePopup success');}).catch((err: BusinessError) => {console.error('updatePopup error: ' + err.code + ' ' + err.message);})

关闭气泡

通过调用closePopup可以关闭气泡。

promptAction.closePopup(contentNode).then(() => {console.info('closePopup success');}).catch((err: BusinessError) => {console.error('closePopup error: ' + err.code + ' ' + err.message);})

由于updatePopup和closePopup依赖content来更新或者关闭指定的气泡,开发者需自行维护传入的content。

在HAR包中使用全局气泡提示

以下示例通过HAR包封装一个Popup,从而对外提供气泡的弹出、更新和关闭能力。

// library/src/main/ets/components/MainPage.etsimport { BusinessError } from '@kit.BasicServicesKit';
import { ComponentContent, TargetInfo, PromptAction } from '@kit.ArkUI';export class PromptActionClass {private promptAction: PromptAction | null = null;private contentNode: ComponentContent<Object> | null = null;private options: PopupCommonOptions | null = null;private target: TargetInfo | null = null;private isPartialUpdate: boolean = false;public setPromptAction(promptAction: PromptAction) {this.promptAction = promptAction;}public setContentNode(node: ComponentContent<Object>) {this.contentNode = node;}public setTarget(target: TargetInfo) {this.target = target;}public setOptions(options: PopupCommonOptions) {this.options = options;}public setIsPartialUpdate(isPartialUpdate: boolean) {this.isPartialUpdate = isPartialUpdate;}public openPopup() {if (this.promptAction != null) {this.promptAction.openPopup(this.contentNode, this.target, this.options).then(() => {console.info('openPopup success');}).catch((err: BusinessError) => {console.error('openPopup error: ' + err.code + ' ' + err.message);})}}public closePopup() {if (this.promptAction != null) {this.promptAction.closePopup(this.contentNode).then(() => {console.info('closePopup success');}).catch((err: BusinessError) => {console.error('closePopup error: ' + err.code + ' ' + err.message);})}}public updatePopup(options: PopupCommonOptions) {if (this.promptAction != null) {this.promptAction.updatePopup(this.contentNode, options, this.isPartialUpdate).then(() => {console.info('updatePopup success');}).catch((err: BusinessError) => {console.error('updatePopup error: ' + err.code + ' ' + err.message);})}}
}
// entry/src/main/ets/pages/Index.etsimport { PromptActionClass } from "library";
import { ComponentContent, PromptAction } from '@kit.ArkUI';class Params {text: string = "";promptActionClass: PromptActionClass = new PromptActionClass();constructor(text: string, promptActionClass: PromptActionClass) {this.text = text;this.promptActionClass = promptActionClass;}
}@Builder
function buildText(params: Params) {Column() {Text(params.text).fontSize(20).margin({ top: 10 })Button('Update').margin({ top: 10 }).width(100).onClick(() => {params.promptActionClass.updatePopup({enableArrow: false,});})Button('Close').margin({ top: 10 }).width(100).onClick(() => {params.promptActionClass.closePopup();})}.width(130).height(150)
}@Entry
@Component
struct Index {@State message: string = "hello";private uiContext: UIContext = this.getUIContext();private promptAction: PromptAction = this.uiContext.getPromptAction();private promptActionClass: PromptActionClass = new PromptActionClass();private targetId: number = 0;private contentNode: ComponentContent<Object> =new ComponentContent(this.uiContext, wrapBuilder(buildText), new Params(this.message, this.promptActionClass));private options: PopupCommonOptions = { enableArrow: true };build() {Column() {Button("openPopup").margin({ top: 50, left: 100 }).onClick(() => {let frameNode: FrameNode | null = this.uiContext.getFrameNodeByUniqueId(this.getUniqueId());let targetId = frameNode?.getChild(0)?.getUniqueId();if (targetId == undefined) {this.targetId = 0;} else {this.targetId = targetId;}this.promptActionClass.setPromptAction(this.promptAction);this.promptActionClass.setContentNode(this.contentNode);this.promptActionClass.setOptions(this.options);this.promptActionClass.setIsPartialUpdate(false);this.promptActionClass.setTarget({ id: this.targetId });this.promptActionClass.openPopup();})}}
}

 

不依赖UI组件的全局菜单 (openMenu)

菜单控制 (Menu)在使用时依赖绑定UI组件,否则无法使用。从API version 18开始,可以通过使用全局接口openMenu的方式,在无UI组件的场景下直接或封装使用,例如在事件回调中使用或封装后对外提供能力。

弹出菜单

通过openMenu可以弹出菜单。

promptAction.openMenu(contentNode, { id: targetId }, {enableArrow: true
}).then(() => {console.info('openMenu success');}).catch((err: BusinessError) => {console.error('openMenu error: ' + err.code + ' ' + err.message);})

创建ComponentContent

通过调用openMenu接口弹出菜单,需要提供用于定义自定义弹出框的内容ComponentContent。其中,wrapBuilder(buildText)封装自定义组件,new Params(this.message)是自定义组件的入参,可以缺省,也可以传入基础数据类型。

private contentNode: ComponentContent<Object> = new ComponentContent(uiContext, wrapBuilder(buildText), this.message);

如果在wrapBuilder中包含其他组件(例如:Popup、Chip组件),则ComponentContent应采用带有四个参数的构造函数constructor,其中options参数应传递{ nestingBuilderSupported: true }。

@Builder
export function buildText(params: Params) {Menu({// 类型设置图标内容icon: {image: $r('app.media.app_icon'),width: 32,height: 32,fillColor: Color.White,borderRadius: 10} as MenuIconOptions,// 设置文字内容title: {text: `This is a Menu title 1`,fontSize: 20,fontColor: Color.Black,fontWeight: FontWeight.Normal} as MenuTextOptions,// 设置文字内容message: {text: `This is a Menu message 1`,fontSize: 15,fontColor: Color.Black} as MenuTextOptions,// 设置按钮内容buttons: [{text: 'confirm',action: () => {console.info('confirm button click');},fontSize: 15,fontColor: Color.Black,},{text: 'cancel',action: () => {console.info('cancel button click');},fontSize: 15,fontColor: Color.Black},] as [MenuButtonOptions?, MenuButtonOptions?]})
}let contentNode: ComponentContent<Object> = new ComponentContent(uiContext, wrapBuilder(buildText), this.message, { nestingBuilderSupported: true });

绑定组件信息

通过调用openMenu接口弹出菜单,需要提供绑定组件的信息TargetInfo。若未传入有效的target,则无法弹出菜单。

let frameNode: FrameNode | null = this.ctx.getFrameNodeByUniqueId(this.getUniqueId());
let targetId = frameNode?.getChild(0)?.getUniqueId();

设置弹出菜单样式

通过调用openMenu接口弹出菜单,可以设置MenuOptions属性调整菜单样式。title属性不生效。preview参数仅支持设置MenuPreviewMode类型。

private options: MenuOptions = { enableArrow: true, placement: Placement.Bottom };

更新菜单样式

通过updateMenu可以更新菜单的样式。支持全量更新和增量更新其菜单样式,不支持更新showInSubWindow、preview、previewAnimationOptions、transition、onAppear、aboutToAppear、onDisappear和aboutToDisappear。

promptAction.updateMenu(contentNode, {enableArrow: false
}, true).then(() => {console.info('updateMenu success');}).catch((err: BusinessError) => {console.error('updateMenu error: ' + err.code + ' ' + err.message);})

关闭菜单

通过调用closeMenu可以关闭菜单。

promptAction.closeMenu(contentNode).then(() => {console.info('openMenu success');}).catch((err: BusinessError) => {console.error('openMenu error: ' + err.code + ' ' + err.message);})

由于updateMenu和closeMenu依赖content来更新或者关闭指定的菜单,开发者需自行维护传入的content。

在HAR包中使用全局菜单

可以通过HAR包封装一个Menu,从而对外提供菜单的弹出、更新和关闭能力。

Toast

即时反馈(Toast)是一种临时性的消息提示框,用于向用户显示简短的操作反馈或状态信息。​它通常在屏幕的底部或顶部短暂弹出,随后在一段时间后自动消失。即时反馈的主要目的是提供简洁、不打扰的信息反馈,避免干扰用户当前的操作流程。

可以通过使用UIContext中的getPromptAction方法获取当前UI上下文关联的PromptAction对象,再通过该对象调用showToast创建并显示文本提示框。

为了安全考虑,例如Toast恶意遮挡其他页面,Toast只能显示在当前的UI实例中,应用退出后,不会单独显示在桌面上。

使用建议

  • 合理使用弹出场景,避免过度提醒用户。
  • 可以针对以下常用场景使用即时反馈操作,例如,当用户执行某个操作时及时结果反馈,用来提示用户操作是否成功或失败;或是当应用程序的状态发生变化时提供状态更新等。
  • 注意文本的信息密度,即时反馈展示时间有限,应当避免长文本的出现。
  • Toast控件的文本应该清晰可读,字体大小和颜色应该与应用程序的主题相符。除此之外,即时反馈控件本身不应该包含任何可交互的元素,如按钮或链接。
  • 杜绝强制占位和密集弹出的提示。
  • 即时反馈作为应用内的轻量通知,应当避免内容布局占用界面内的其他元素信息,如遮盖弹出框的展示内容,从而迷惑用户弹出的内容是否属于弹出框。再或者频繁性的弹出信息内容,且每次弹出之间无时间间隔,影响用户的正常使用。也不要在短时间内频繁弹出新的即时反馈替代上一个。即时反馈的单次显示时长不要超过 3 秒钟,避免影响用户正常的行为操作。
  • 遵从系统默认弹出位置。
  • 即时反馈在系统中默认从界面底部弹出,距离底部有一定的安全间距,作为系统性的应用内提示反馈,请遵守系统默认效果,避免与其他弹出类组件内容重叠。特殊场景下可对内容布局进行规避。

即时反馈模式对比

即时反馈提供了两种显示模式,分别为DEFAULT(显示在应用内)、TOP_MOST(显示在应用之上)。

在TOP_MOST类型的Toast显示前,会创建一个全屏大小的子窗(手机上子窗大小和主窗大小一致),然后在该子窗上计算Toast的布局位置,最后显示在该子窗上。具体和DEFAULT模式Toast的差异如下:

差异点DEFAULTTOP_MOST
是否创建子窗
层级显示在主窗内,层级和主窗一致,一般比较低显示在子窗中,一般比主窗层级高,比其他弹窗类组件层级高,比软键盘和权限弹窗层级低
是否避让软键盘软键盘抬起时,必定上移软键盘的高度软键盘抬起时,只有toast被遮挡时,才会避让,且避让后toast底部距离软键盘高度为80vp
UIExtension内布局以UIExtension为主窗中布局,对齐方式与UIExtension对齐以宿主窗口为主窗中布局,对齐方式与宿主窗口对齐
import { promptAction } from '@kit.ArkUI';@Entry
@Component
struct Index {build() {Column({ space: 10 }) {TextInput()Button() {Text("DEFAULT类型Toast").fontSize(20).fontWeight(FontWeight.Bold)}.width('100%').onClick(() => {this.getUIContext().getPromptAction().showToast({message: "ok,我是DEFAULT toast",duration: 2000,showMode: promptAction.ToastShowMode.DEFAULT,bottom: 80});})Button() {Text("TOPMOST类型Toast").fontSize(20).fontWeight(FontWeight.Bold)}.width('100%').onClick(() => {this.getUIContext().getPromptAction().showToast({message: "ok,我是TOP_MOST toast",duration: 2000,showMode: promptAction.ToastShowMode.TOP_MOST,bottom: 85});})}}
}

创建即时反馈

适用于短时间内提示框自动消失的场景

import { PromptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';@Entry
@Component
struct toastExample {private uiContext: UIContext = this.getUIContext();private promptAction: PromptAction = this.uiContext.getPromptAction();build() {Column() {Button('Show toast').fontSize(20).onClick(() => {try {this.promptAction.showToast({message: 'Hello World',duration: 2000})} catch (error) {let message = (error as BusinessError).message;let code = (error as BusinessError).code;console.error(`showToast args error code is ${code}, message is ${message}`);};})}.height('100%').width('100%').justifyContent(FlexAlign.Center)}
}

显示关闭即时反馈

适用于提示框提留时间较长,用户操作可以提前关闭提示框的场景。

import { LengthMetrics, PromptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';@Entry
@Component
struct toastExample {@State toastId: number = 0;private uiContext: UIContext = this.getUIContext();private promptAction: PromptAction = this.uiContext.getPromptAction();build() {Column() {Button('Open Toast').type(ButtonType.Capsule).height(100).onClick(() => {try {this.promptAction.openToast({message: 'Toast Massage',duration: 10000,}).then((toastId: number) => {this.toastId = toastId;});} catch (error) {let message = (error as BusinessError).message;let code = (error as BusinessError).code;console.error(`OpenToast error code is ${code}, message is ${message}`);};})Blank().height(50);Button('Close Toast').height(100).type(ButtonType.Capsule).onClick(() => {try {this.promptAction.closeToast(this.toastId);} catch (error) {let message = (error as BusinessError).message;let code = (error as BusinessError).code;console.error(`CloseToast error code is ${code}, message is ${message}`);};})}.height('100%').width('100%').justifyContent(FlexAlign.Center)}
}

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

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

相关文章

让老旧医疗设备“听懂”新语言:CAN转EtherCAT的医疗行业应用

在医疗影像设备的智能化升级中&#xff0c;通信协议的兼容性常成为工程师的“痛点”。例如&#xff0c;某医院的移动式X射线机采用CAN协议控制机械臂&#xff0c;而主控系统基于EtherCAT架构。两者协议差异导致数据延迟高达5ms&#xff0c;影像定位精度下降&#xff0c;甚至影响…

ubuntu基础搭建

ubuntu上docker的搭建 https://vulhub.org/zh 网站最下面找到开始使用&#xff0c;有搭建的命令//安装docker&#xff0c;连接失败多试几次 curl -fsSL https://get.docker.com | sh //验证Docker是否正确安装&#xff1a; docker version //还要验证Docker Compose是否可用&am…

动态规划 + DFS + 记忆化!Swift 解 LeetCode 329 的实战笔记

文章目录摘要描述题解答案题解代码分析代码解析示例测试及结果时间复杂度空间复杂度总结摘要 这篇文章带你用 Swift 实战一道非常经典的 DFS 记忆化搜索题目 —— LeetCode 329《矩阵中的最长递增路径》。看似一个简单的“走格子”游戏&#xff0c;实则考察了搜索顺序、剪枝策…

046_局部内部类与匿名内部类

一、局部内部类&#xff08;Local Inner Class&#xff09; 1.1 定义与基本概念 局部内部类是定义在方法、构造器或代码块内部的类&#xff0c;其作用域仅限于所在的局部范围&#xff08;定义它的方法、构造器或代码块&#xff09;&#xff0c;超出该范围则无法访问。 它的核心…

Jenkins Pipeline 中使用 JsonSlurper 报错:cannot find current thread

Jenkins Pipeline 中使用 JsonSlurper 报错&#xff1a;cannot find current thread&#x1f31f; 背景⚠ 问题重现&#x1f9e0; 原因解析&#xff1a;CPS 与非 CPS 安全方法冲突✅ 解决方案一&#xff1a;使用 NonCPS 注解&#xff08;经典方案&#xff09;✅ 解决方案二&…

Go 语言循环语句详解

Go 语言循环语句详解 在编程语言中&#xff0c;循环语句是实现重复执行某些代码块的关键元素。Go 语言作为现代编程语言之一&#xff0c;提供了多种循环结构来满足不同的编程需求。本文将详细讲解 Go 语言中的循环语句&#xff0c;包括 for、while 和 goto 语句&#xff0c;帮助…

day30——零基础学嵌入式之进程间通信1.0

一、进程间通信7种方式1.传统的进程间通信方式&#xff08;1&#xff09;管道①无名管道&#xff1a;②有名管道&#xff1a;&#xff08;2&#xff09;③信号&#xff08;3&#xff09;system Ⅴ 》系统Ⅴ 进程间通信方式 inner Process Comunication④共享内存 &#xff…

408考研逐题详解:2010年第33题——网络体系结构

2010年第33题 下列选项中&#xff0c;不属于网络体系结构所描述的内容是&#xff08; &#xff09; A. 网络的层次 \qquad B. 每层使用的协议 \qquad C. 协议的内部实现细节 \qquad D. 每层必须完成的功能 解析 本题属于计算机网络基础知识的范畴&#xff0c;考查网络体系结构…

VR 远程系统的沉浸式协作体验​

在传统的远程协作中&#xff0c;团队成员往往通过二维的视频画面进行交流&#xff0c;这种方式虽然能实现基本的沟通&#xff0c;但缺乏真实感和互动性。而 VR 远程系统的出现&#xff0c;彻底改变了这一局面。戴上 VR 设备&#xff0c;员工们仿佛置身于同一个真实的办公室空间…

记录DataGrip 2025.1.3破解失败后,无法重启问题修复

记录DataGrip 2025.1.3破解失败后&#xff0c;无法重启问题修复安装过程复盘异常场景解决方式总结安装过程 在官网下载了最新版本2025.1.3。安装成功后&#xff0c;使用30天试用方式&#xff0c;打开datagrip。 复盘异常场景 网上搜索破解教程进行破解。找了一个需要现在ja…

私有服务器AI智能体搭建配置选择记录

在搭建私有服务器上的AI智能体时&#xff0c;需要从多个方面进行选择和规划&#xff0c;以确保系统性能、安全性、可扩展性等方面满足需求。1. 硬件选择 服务器配置&#xff1a; CPU&#xff1a;选择高性能多核CPU&#xff08;如Intel Xeon或AMD EPYC系列&#xff09;&#xff…

SDC Specical check setting的描述 - false path

在上一篇文中描述了SDC的基本语法&#xff0c;其中关于时序异常约束并没有进行详细的描述&#xff0c;但是在正常的设计中&#xff0c;一般这种异常的设置反而是需要特别关注的&#xff0c;主要包括&#xff1a;1. 虚假路径- false path不需要满足任何时序要求的路径&#xff1…

【Python练习】048. 编写一个函数,实现简单的命令行接口,接受用户输入并响应

048. 编写一个函数,实现简单的命令行接口,接受用户输入并响应 在 Python 中,可以通过 input() 函数创建一个简单的命令行接口,接受用户输入并根据输入内容进行响应。 示例代码 def simple_command_line_interface():"""实现一个简单的命令行接口,接受用…

软件工厂语境下的知识系统选型:兼顾合规性与集成深度

在过去几十年间&#xff0c;制造业从“工匠手作”迈向“工业流水线”&#xff0c;完成了生产效率的巨大飞跃。当软件开发也面临交付复杂性、合规要求与协作成本不断上升的现实&#xff0c;“软件工厂”的理念逐步兴起。 在这场“开发现代化”的转型中&#xff0c;知识管理被重新…

C语言-一维数组,二维数组

数组 数组的引入如果要在程序中保存一个人的年龄&#xff1f;如何保存&#xff1f; 答&#xff1a;创建一个基于int类型的变量&#xff0c;举例&#xff1a;int age 22如果要在程序中保存一个人的三门课的成绩&#xff1f;如何保存&#xff1f; 答&#xff1a;创建三个基于flo…

如何区别HTML和HTML5?

要区分 HTML&#xff08;通常指 HTML4 及更早版本&#xff09;和 HTML5&#xff0c;主要可以从以下关键方面进行比较&#xff1a;一、文档声明区别 <!-- HTML4 文档声明 --> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http:/…

Java实战:实时聊天应用开发(附GitHub链接)

一、前置技术项目介绍&#xff1a; 项目为局域网沟通软件&#xff0c;类似内网通&#xff0c;核心功能包括昵称输入、聊天界面展示在线人数&#xff08;实时更新&#xff09;、群聊&#xff0c;也可扩展私聊、登录注册、聊天记录存储等功能&#xff0c;结尾附GitHub链接。项目涉…

linux 的list_for_each_entry

linux的宏定义提高了代码的简洁性&#xff0c;但有时候的命名不够完美。比如list_for_each_entry&#xff0c;看名字只知道是遍历list&#xff0c;但一看里面的三个变量参数&#xff0c;有点懵逼。/*** list_for_each_entry - iterate over list of given type* pos: …

分布式面试点

目录 1.分布式理论 为什么CAP不可兼得呢? 2.CAP对应的模型和应用 3.Base理论 4,有哪些分布式锁的案例 5.分布式事务 6.Seata 分布式一致性算法 1. 准备阶段&#xff08;Prepare Phase&#xff09; 2. 接受阶段&#xff08;Accept Phase&#xff09; 3. 学习阶段&…

Neo4j系列---【Linux离线安装neo4j】

Linux离线安装neo4j 1.官方安装文档 地址&#xff1a;https://neo4j.com/docs/operations-manual/current/installation/linux/tarball/ 2.如果浏览器无法访问 修改neo4j.conf,开放所有ip访问 # 允许所有IP地址访问 server.default_listen_address0.0.0.0 3.创建开机自启动服务…