【Jetpack】Navigation 导航组件 ⑤ ( NavigationUI 类使用 )

文章目录

  • 一、NavigationUI 类简介
  • 二、NavigationUI 类使用流程
    • 1、创建 Fragment
    • 2、创建 NavigationGraph
    • 3、Activity 导入 NavHostFragment
    • 4、创建菜单
    • 5、Activity 界面开发 NavigationUI 的主要逻辑 ( 重点 )
      • a、添加 Fragment 布局
      • b、处理 Navigation 导航逻辑 ( 重点 )
      • c、启用菜单选项
      • d、使用菜单进行 NavigationUI 导航
      • e、支持导航回退功能
  • 三、完整源码示例 - NavigationUI 类使用
    • 1、Fragment 相关源码
      • a、FragmentA 界面的 Kotlin 源码和布局文件
      • b、FragmentB 界面的 Kotlin 源码和布局文件
    • 2、NavigationGraph 相关源码
    • 3、MainActivity 主界面相关源码 ( 重点 )
    • 4、执行结果


代码地址 :

  • CSDN ( 本博客代码快照 | 推荐下载 0 积分 ) : https://download.csdn.net/download/han1202012/88251933
  • GitHub ( 可能已经覆盖 ) : https://github.com/han1202012/Navigation

NavigationUI 类支持一些系统自带的控件 , 配置后 , 自动跳转 Fragment 界面的功能 , 使用起来非常简洁 , 支持的可配置 Navigation 跳转的控件有 :

  • ActionBar
  • ToolBar
  • CollapsingToolbarLayout
  • Menu

在 Android 开发中 , NavigationUI 是 用于构建 和 管理应用程序导航界面 的重要工具 , 可以极大地提高开发效率 ;





一、NavigationUI 类简介



NavigationUI 是 Google 官方提供的 用于管理 Navigation 导航的组件 , 属于 Android 系统的 Jetpack 工具包 ;

借助 NavigationUI 可以很方便的 创建和组织应用程序的导航界面 ;

如 : 构建复杂的导航结构,垂直或水平的主菜单 , 侧边栏 , 抽屉导航栏等 ;


开发者 可以通过 NavigationUI 轻松地管理页面的转换和导航 ;

NavigationUI 提供了一些静态方法来处理 顶部应用栏 / 抽屉式导航栏 / 底部导航栏中 的界面导航 ;


本篇博客中介绍一种使用场景 : 使用 AppBar 中的菜单选项控制 Navigation 界面跳转 ;

在 Activity 中 , 使用 Navigation 组件 切换 Fragment 界面时 , 除了进行界面切换之外 , 不同的界面对应的顶部 标题栏 AppBar 需要进行相应的改变 ;

Navigation 组件中 , 提供了 NavigationUI 类 , 统一管理 Fragment 页面切换相关的 UI 改变 ;





二、NavigationUI 类使用流程



本章节介绍使用 AppBar 中的菜单选项控制 Navigation 界面跳转 的流程 ;


1、创建 Fragment


创建两个 Fragment , 分别作为要 互相跳转 的 两个界面 ;

右键点击包名 , 选择 " New / Fragment / Fragment (Blank) " 选项 ,

在这里插入图片描述

在弹出的界面中 , 输入 Fragment 名称 , 创建新的 Fragment ;

在这里插入图片描述

创建 Fragment 时 , 会自动生成对应的 布局文件 :

在这里插入图片描述


注意 : 该操作比较坑 , 生成 Fragment 时 , 会自动添加 Kotlin 语言插件的 Gradle 依赖 , 必要时可以删除该依赖 ; 自动生成的依赖没有配置 Maven 源 , 会报错 ;

buildscript {dependencies {classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0-RC2'}
}

2、创建 NavigationGraph


创建完 Fragment 之后 , 才能开始创建 NavigationGraph , 否则没有对应的 Fragment 选项 ;

创建 NavigationGraph ,

右键点击 res 目录 , 选择 " New / Android Resource File " 选项 ,

在这里插入图片描述

在弹出的 " New Resource File " 对话框中 , 设置 文件名 , 资源类型 , 目录名称 ;

在这里插入图片描述

下面开始编辑 NavigationGraph , 进入 Design 模式后 , 会提示 Design editor is unavailable until after a successful project sync , 这是因为创建 Fragment 之后 , 还没有进行第一次编译 ,

在这里插入图片描述

选择 " 菜单栏 / Build / Make Project " 选项 , 编译一次应用 ;

在这里插入图片描述

编译成功之后 , 就可以使用 NavigationGraph 的 Design 模式 ;

在这里插入图片描述

点击 " New Destination " 按钮 , 添加两个 Fragment 到 NavigationGraph 中 ;

在这里插入图片描述

将两个 Fragment 添加到 NavigationGraph 中 , 不需要做其它配置 ;

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/my_navigation_graph"app:startDestination="@id/fragmentA"><fragmentandroid:id="@+id/fragmentA"android:name="kim.hsl.app2.FragmentA"android:label="fragment_a"tools:layout="@layout/fragment_a" /><fragmentandroid:id="@+id/fragmentB"android:name="kim.hsl.app2.FragmentB"android:label="fragment_b"tools:layout="@layout/fragment_b" />
</navigation>

在这里插入图片描述

设置默认的 Fragment , 在根标签 navigation 中 ,

app:startDestination="@id/fragmentA"

配置 , 用于配置默认的初始 Fragment 是哪一个 ;


3、Activity 导入 NavHostFragment


进入 Launcher 界面 MainActivity 的布局中 , 删除布局中的其它元素 ;

将 NavHostFragment 拖入到 布局中 ,
在这里插入图片描述

拖入空间到布局后 , 松开鼠标 , 会弹出如下 " Navigation Graph " 对话框 , 选择要拖入的 NavigationGraph , 然后点击右下角 " OK " 按钮 ;

在这里插入图片描述

拖入后 , 为该空间添加约束 , 最终源码如下 :

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><!--<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />--><androidx.fragment.app.FragmentContainerViewandroid:id="@+id/fragmentContainerView"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="match_parent"android:layout_height="match_parent"app:defaultNavHost="true"app:navGraph="@navigation/my_navigation_graph"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"  /></androidx.constraintlayout.widget.ConstraintLayout>

4、创建菜单


右键点击 res 目录 , 选择 " New / Android Resource File " 选项 ,

在这里插入图片描述

在弹出的 " New Resource File " 对话框中 , 选择 资源类型为 Menu 菜单类型 , 目录名称是 menu , 然后输入 文件名 , 点击 " OK " 按钮 , 创建菜单 ;

在这里插入图片描述

创建完毕后 , 在该菜单配置文件中 , 配置 android:id="@+id/fragmentB" , 其含义是跳转到 NavigationGraph 中 id 为 fragmentB 对应的 Fragment 界面中 , 也就是跳转到 FragmentB 界面 , 触发该菜单选项 , 就会跳转到 FragmentB 界面 ;

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@+id/fragmentB"android:icon="@mipmap/ic_launcher"android:title="跳转到 Fragment B"/>
</menu>

5、Activity 界面开发 NavigationUI 的主要逻辑 ( 重点 )



a、添加 Fragment 布局


在 Activity 的布局文件中 , 添加如下代码 , 不建议在 Design 界面直接拖动 NavHostFragment , 生成的代码报错 , 直接拷贝下面的代码即可 ;

app:navGraph="@navigation/my_navigation_graph" 修改成你自己创建的 NavigationGraph 即可 ;

name 属性必须设置成 android:name="androidx.navigation.fragment.NavHostFragment" 样式的 ;

    <fragmentandroid:id="@+id/fragmentContainerView"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="match_parent"android:layout_height="match_parent"app:navGraph="@navigation/my_navigation_graph"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"  />

b、处理 Navigation 导航逻辑 ( 重点 )


首先 , 获取 NavController , 从布局文件中定义的 Fragment 布局中获取 ;

        // 1. 获取 NavControllernavController = Navigation.findNavController(this, R.id.fragmentContainerView)

然后 , 创建 AppBarConfiguration , 这是之后绑定 Navigation 与 AppBar 的重要参数 ;

        // 2. 创建 AppBarConfigurationappBarConfiguration = AppBarConfiguration.Builder(navController.graph).build()

再后 , 将 Navigation 导航 与 AppBar 进行关联 , 关联后 , 就可以使用 菜单 选项进行界面跳转了 ;

        // 3. 将 Navigation 导航 与 AppBar 进行关联NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)

最后 , 监听 Navigation 页面切换状态 , 如果通过 Navigation 切换了界面 , 会触发 DestinationChangedListener 监听器的 onDestinationChanged 函数 ;

        // 4. 监听页面切换状态navController.addOnDestinationChangedListener{/*相当于重写了下面的函数public fun onDestinationChanged(controller: NavController,destination: NavDestination,arguments: Bundle?)*/navController: NavController, navDestination: NavDestination, bundle: Bundle? ->

c、启用菜单选项


重写 Activity 的 onCreateOptionsMenu 方法 , 加载资源文件中的菜单 ,

此时 只加载菜单 , 此时不能跳转 , 需要重写 onOptionsItemSelected 方法才可以 ;

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {super.onCreateOptionsMenu(menu)// 加载资源文件中的菜单// 只加载菜单 , 此时不能跳转 , 需要重写 onOptionsItemSelected 方法才可以menuInflater.inflate(R.menu.my_menu, menu)return true}

d、使用菜单进行 NavigationUI 导航


只显示菜单是不行的 , 还需要设置菜单的行为 , 重写了该方法 , 菜单选项才能生效 ,

NavigationUI.onNavDestinationSelected(item, navController) 代码的含义是 : 优先使用 NavigationUI 进行导航 ,

如果跳转失败 , 再使用传统的方式执行默认动作 , 代码为 super.onOptionsItemSelected(item) ;

    override fun onOptionsItemSelected(item: MenuItem): Boolean {// 重写了该方法 , 菜单选项才能生效// 优先使用 NavigationUI 进行导航 , 如果跳转失败 , 再使用传统的方式return NavigationUI.onNavDestinationSelected(item, navController)|| super.onOptionsItemSelected(item)}

e、支持导航回退功能


默认状态下通过 Navigation 导航 , 跳转到 FragmentB 后是无法返回的 , 如果想要返回, 需要重写 onSupportNavigateUp 方法 ;

NavigationUI.navigateUp(navController, appBarConfiguration) 的作用就是将 Navigation 导航切换界面 , 记录到回退栈中 ;

    // 默认状态下进入 FragmentB 后是无法返回的// 如果想要返回, 需要重写 onSupportNavigateUp 方法override fun onSupportNavigateUp(): Boolean {return NavigationUI.navigateUp(navController, appBarConfiguration)|| super.onSupportNavigateUp()}




三、完整源码示例 - NavigationUI 类使用




1、Fragment 相关源码



a、FragmentA 界面的 Kotlin 源码和布局文件


FragmentA 基本是默认代码 , 删除了参数传递相关的逻辑 , 显得更加简洁 ;


FragmentA 代码 :

package kim.hsl.app2import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragmentclass FragmentA : Fragment() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {// Inflate the layout for this fragmentreturn inflater.inflate(R.layout.fragment_a, container, false)}
}

布局文件 :

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".FragmentA"><!-- TODO: Update blank fragment layout --><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:text="FragmentA" /></FrameLayout>

b、FragmentB 界面的 Kotlin 源码和布局文件


在该界面中 , 设置了 隐藏 AppBar 中的 菜单按钮 的功能 , 跳转到 FragmentB 之后 , 右上角 就不再显示菜单按钮 ;


FragmentB 代码 :

package kim.hsl.app2import android.os.Bundle
import android.view.*
import androidx.fragment.app.Fragmentclass FragmentB : Fragment() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {// 确保 onCreateOptionsMenu 函数执行setHasOptionsMenu(true)// 为 Fragment 加载布局return inflater.inflate(R.layout.fragment_b, container, false)}override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {// 清空菜单menu.clear()super.onCreateOptionsMenu(menu, inflater)}
}

FragmentB 的布局文件 :

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".FragmentB"><!-- TODO: Update blank fragment layout --><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:text="FragmentB" /></FrameLayout>

2、NavigationGraph 相关源码


在这里配置两个 Fragment , 不需要配置跳转动作 , 只需要在此处定义 Fragment 即可 ;

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/my_navigation_graph"app:startDestination="@id/fragmentA"><fragmentandroid:id="@+id/fragmentA"android:name="kim.hsl.app2.FragmentA"android:label="fragment_a"tools:layout="@layout/fragment_a" /><fragmentandroid:id="@+id/fragmentB"android:name="kim.hsl.app2.FragmentB"android:label="fragment_b"tools:layout="@layout/fragment_b" />
</navigation>

3、MainActivity 主界面相关源码 ( 重点 )


package kim.hsl.app2import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.navigation.NavController
import androidx.navigation.NavDestination
import androidx.navigation.Navigation
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUIclass MainActivity : AppCompatActivity() {lateinit var navController: NavControllerlateinit var appBarConfiguration: AppBarConfigurationoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 1. 获取 NavControllernavController = Navigation.findNavController(this, R.id.fragmentContainerView)// 2. 创建 AppBarConfigurationappBarConfiguration = AppBarConfiguration.Builder(navController.graph).build()// 3. 将 Navigation 导航 与 AppBar 进行关联NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)// 4. 监听页面切换状态navController.addOnDestinationChangedListener{/*相当于重写了下面的函数public fun onDestinationChanged(controller: NavController,destination: NavDestination,arguments: Bundle?)*/navController: NavController, navDestination: NavDestination, bundle: Bundle? ->Log.i("octopus", "OnDestinationChangedListener 监听器中 onDestinationChanged 函数触发")}}override fun onCreateOptionsMenu(menu: Menu?): Boolean {super.onCreateOptionsMenu(menu)// 加载资源文件中的菜单// 只加载菜单 , 此时不能跳转 , 需要重写 onOptionsItemSelected 方法才可以menuInflater.inflate(R.menu.my_menu, menu)return true}override fun onOptionsItemSelected(item: MenuItem): Boolean {// 重写了该方法 , 菜单选项才能生效// 优先使用 NavigationUI 进行导航 , 如果跳转失败 , 再使用传统的方式return NavigationUI.onNavDestinationSelected(item, navController)|| super.onOptionsItemSelected(item)}// 默认状态下进入 FragmentB 后是无法返回的// 如果想要返回, 需要重写 onSupportNavigateUp 方法override fun onSupportNavigateUp(): Boolean {return NavigationUI.navigateUp(navController, appBarConfiguration)|| super.onSupportNavigateUp()}
}

配套的 布局文件 :

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><!--<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />--><fragmentandroid:id="@+id/fragmentContainerView"android:name="androidx.navigation.fragment.NavHostFragment"android:layout_width="match_parent"android:layout_height="match_parent"app:navGraph="@navigation/my_navigation_graph"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"  /></androidx.constraintlayout.widget.ConstraintLayout>

配套的 menu 布局文件 :

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@+id/fragmentB"android:icon="@mipmap/ic_launcher"android:title="跳转到 Fragment B"/>
</menu>

4、执行结果


进入界面 , 显示默认的 FragmentA ,

在这里插入图片描述

点击右上角菜单栏 , 弹出 " 跳转到 FragmentB " 按钮 , 点击该菜单选项 , 跳转页面 ,

在这里插入图片描述

此时跳转到了 FragmentB 页面 , 并且触发了监听器 ,

在这里插入图片描述

点击回退按钮 , 回到了 FragmentA 界面 , 又触发了监听器 ;

在这里插入图片描述

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

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

相关文章

螺旋矩阵-2

import numpy as np def func(n):rotate_list np.zeros(n * n).reshape(n, n).tolist()flag rightx 0y 0i 1while i < n * n:if flag right:try:if rotate_list[y][x] 0:rotate_list[y][x] ix 1i 1else:# 不为0时改变递增方向flag downx - 1y 1except Exception…

设计模式--工厂模式(Factory Pattern)

一、 什么是工厂模式 工厂模式&#xff08;Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一种创建对象的接口&#xff0c;但是将对象的实例化过程推迟到子类中。工厂模式允许通过调用一个共同的接口方法来创建不同类型的对象&#xff0c;而无需暴露对…

android 下载网络文件

工具类 import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; import android.os.Environment; import android.util.Log;import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import …

Ajax复习

Ajax复习 一、简介 ​ AJAX 全称为 Asynchronous JavaScript And XML&#xff0c;就是异步的 JS 和 XML。 ​ 一句话总结&#xff1a;无刷新通信。 二、 特点 优点 无刷新通信 允许你根据用户事件来更新部分页面内容 缺点 没有浏览历史&#xff0c;不能回退 存在跨域问题…

中国肉羊产业链调研与投资评估析报告(2023版)

内容简介&#xff1a; 肉羊是适应外界环境较强的家畜之一&#xff0c;食性广、耐粗饲、抗逆性强。饲养肉羊投资少、周转快、效益稳、回报率高。近年来&#xff0c;国内外羊肉市场发生了一些变化&#xff0c;为肉羊产业的发展提供了巨大空间&#xff0c;使肉羊生产正成为一个黄…

Python爬虫武汉市二手房价格数据采集分析:Linear Regression、XGBoost和LightGBM|代码分享...

全文链接&#xff1a;http://tecdat.cn/?p31958 分析师&#xff1a;Yan Liu 我国有大量的资金都流入了房地产行业&#xff0c;同时与其他行业有着千丝万缕的联系&#xff0c;可以说房地产行业对推动我国深化改革、经济发展、工业化和城市化具有不可磨灭的作用&#xff08;点击…

[OpenWrt 22.03] SDK package添加一个软件包

进入 OpenWrt 源码目录,并进入 package 目录:cd openwrt/package创建一个新目录,命名为 hello :mkdir hello进入到 hello 目录中,并创建以下目录结构:├── Makefile └── src└── hello.c其中 src 目录中的 hello.c 和 Makefile 是源代码和编译 Makefile。 编写 Ma…

java八股文面试[java基础]——字节码

字节码技术应用 字节码技术的应用场景包括但不限于AOP&#xff0c;动态生成代码&#xff0c;接下来讲一下字节码技术相关的第三方类库&#xff0c;第三方框架的讲解是为了帮助大家了解字节码技术的应用方向&#xff0c;文档并没有对框架机制进行详细分析&#xff0c;有兴趣的可…

为什么海外专利申请含金量高?

为什么海外专利申请含金量高&#xff1f;通常&#xff0c;具有较大市场价值的发明才需要在国外申请专利保护&#xff0c;专利的海外申请数量是衡量经济和创新价值的重要指标&#xff0c;即专利全球性指标。我国海外专利申请量比重过低&#xff0c;说明专利的创造性未达到国外专…

注解和class对象和mysql

注解 override 通常是用在方法上的注解表示该方法是有重写的 interface 表示一个注解类 比如 public interface override{} 这就表示是override是一个注解类 target 修饰注解的注解表示元注解 deprecated 修饰某个元素表示该元素已经过时了 1.不代表该元素不能用了&…

查漏补缺 - 构造函数,原型,this,原型链,继承

目录 1&#xff0c;构造函数2&#xff0c;原型3&#xff0c;this4&#xff0c;原型链1&#xff0c;特点2&#xff0c;Object.prototype.toString()3&#xff0c;instanceof 运算符4&#xff0c;Object.getPrototypeOf()5&#xff0c;创建空原型对象6&#xff0c;面试题 5&#…

Vue2向Vue3过度核心技术自定义指令

目录 1 自定义指令1.指令介绍2.自定义指令3.自定义指令语法4.指令中的配置项介绍5.代码示例6.总结 2 自定义指令-指令的值1.需求2.语法3.代码示例 3 自定义指令-v-loading指令的封装1.场景2.需求3.分析4.实现5.准备代码 1 自定义指令 1.指令介绍 内置指令&#xff1a;v-html、v…

【无需公网IP】在树莓派上搭建Web站点

目录 1.概述 2.使用 Raspberry Pi Imager 安装 Raspberry Pi OS 3.设置 Apache Web 服务器 3.1测试 web 站点 3.2安装静态样例站点 3.3将web站点发布到公网 3.4安装 Cpolar 3.5cpolar进行token认证 3.6生成cpolar随机域名网址 3.7生成cpolar二级子域名 3.8将参数保存…

C++ 组合类

所谓组合类便是一个类中含有其他类的对象: #include <iostream> #include <string.h> using namespace std;class dog { public:dog() {}dog(const char *n, int age, const char *v) : age(age){strcpy(this->name, n);strcpy(this->var, v);}// 显示这条狗…

PG 权限实例

如果角色已经存在, 可以采用如下方法进行删除 psql -U pgsql -d postgresreassign owned by r_read to pgsql; drop owned by r_read; drop user if exists r_read;reassign owned by r_read_write to pgsql; drop owned by r_read_write; drop user if exists r_read_write;…

基于Android的课程教学互动系统 微信小程序uniapp

教学互动是学校针对学生必不可少的一个部分。在学校发展的整个过程中&#xff0c;教学互动担负着最重要的角色。为满足如今日益复杂的管理需求&#xff0c;各类教学互动程序也在不断改进。本课题所设计的springboot基于Android的教学互动系统&#xff0c;使用SpringBoot框架&am…

接口幂等性设计的最佳实现

一、什么是幂等 二、为什么需要幂等 三、接口超时了&#xff0c;到底如何处理&#xff1f; 四、如何设计幂等 全局的唯一性ID 幂等设计的基本流程 五、实现幂等的8种方案 selectinsert主键/唯一索引冲突 直接insert 主键/唯一索引冲突 状态机幂等 抽取防重表 token令牌 悲观锁…

【Go 基础篇】Go语言结构体基本使用

在Go语言中&#xff0c;结构体是一种重要的数据类型&#xff0c;用于定义和组织一组不同类型的数据字段。结构体允许开发者创建自定义的复合数据类型&#xff0c;类似于其他编程语言中的类。本文将深入探讨Go语言中结构体的定义、初始化、嵌套、方法以及与其他语言的对比&#…

ASP.NET Core 的日志系统

ASP.NET Core 提供了丰富日志系统。 可以通过多种途径输出日志&#xff0c;以满足不同的场景&#xff0c;内置的几个日志系统包括&#xff1a; Console&#xff0c;输出到控制台&#xff0c;用于调试&#xff0c;在产品环境可能会影响性能。Debug&#xff0c;输出到 System.Di…

浅析编程中的语法糖

1、理解语法糖 1.1.什么是语法糖&#xff1f; 语法糖是一种编程语言的特性&#xff0c;它并不引入新功能&#xff0c;而是通过提供更简洁、易读的语法形式&#xff0c;使代码编写和理解变得更加轻松。它有点像是一种“甜蜜”的语法&#xff0c;让我们在不改变底层逻辑的情况下…