Jetpack Compose 从入门到精通

Jetpack Compose 从入门到精通

一、基础篇

1. 什么是 Compose

Jetpack Compose 是 Google 推出的Android 原生声明式 UI 框架,替代传统 XML + View 体系:

  • 命令式 UI(XML):先布局文件,代码 findViewById 找控件,调用 setText/setVisibility 修改状态
  • 声明式 UI(Compose):用纯 Kotlin 函数描述界面,状态驱动 UI 自动刷新,数据变界面自动重绘

核心优势:

  1. 代码更少,无 xml、无 id、无 findViewById、无 inflate
  2. 天然适配 Kotlin 特性(lambda、高阶函数、空安全)
  3. 内置主题、暗黑模式、动画、手势、组件库
  4. 跨平台复用逻辑(Desktop Compose、iOS Compose Multiplatform)

2. 环境准备

版本要求
  • Android Studio Giraffe 及以上(新版内置 Compose 模板)
  • AGP ≥ 8.0,Kotlin ≥ 1.9,JDK 17
  • 最低兼容 API 21(Android 5.0),完整特性建议 minSdk 24+
新建 Compose 项目

New Project → 选择 Empty Activity (Jetpack Compose) 自动生成依赖(build.gradle Module 层):

gradle 复制代码
android {
    namespace "com.example.composelearn"
    compileSdk 35

    defaultConfig {
        applicationId "com.example.composelearn"
        minSdk 24
        targetSdk 35
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary true
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    kotlinOptions {
        jvmTarget = '17'
    }
    buildFeatures {
        compose true // 开启Compose编译
    }
    composeOptions {
        kotlinCompilerExtensionVersion "1.9.0" // 和Kotlin版本对应
    }
    packaging {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
}

dependencies {
    // Compose BOM 统一版本管理(推荐)
    implementation platform('androidx.compose:compose-bom:2026.02.00')
    implementation 'androidx.compose.ui:ui'
    implementation 'androidx.compose.ui:ui-graphics'
    implementation 'androidx.compose.ui:ui-tooling-preview'
    implementation 'androidx.compose.material3:material3' // Material3 新版组件库
    implementation 'androidx.activity:activity-compose:1.9.0' // Activity 挂载Compose入口

    // 调试工具
    debugImplementation 'androidx.compose.ui:ui-tooling'
    debugImplementation 'androidx.compose.ui:ui-test-manifest'
}

3. 第一个 Compose 程序

3.1 @Composable 可组合函数核心规则

定义规则

  1. 函数必须添加注解:@Composable
  2. 无返回值 (返回 Unit
  3. 约定规范:函数名首字母大写(区分普通函数)
  4. 只能在 @Composable 函数内部调用另一个 @Composable 函数
  5. 不能放在循环、if 判断分支以外随意调用(遵循重组规则)

正确写法 vs 错误写法

kotlin 复制代码
// ✅ 正确
@Composable
fun HelloText() {
    Text("Hello Compose")
}

// ❌ 错误:小写、缺少注解
fun wrongFunc() {
    Text("test")
}

Activity 挂载入口

setContent 是唯一入口,所有 Compose 组件都写在里面:

kotlin 复制代码
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            // 全局主题包裹(自动生成的MyAppTheme)
            MyAppTheme {
                HelloText()
            }
        }
    }
}
3.2 @Preview 可视化预览(不用跑模拟器)
3.2.1 使用规则
  1. 注解:@Preview
  2. 修饰 @Composable 函数
  3. 预览函数不能带参数,要调用真正的 UI 组件传参
  4. 点击侧边 Split 分栏,实时看效果
3.2.2 完整预览模板
kotlin 复制代码
// 可预览的包装函数(无参数)
@Preview(showBackground = true, widthDp = 360, heightDp = 600)
@Composable
fun BasicAllPreview() {
    MyAppTheme {
        Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
            HelloText()
            ColumnSample()
            RowSample()
            BoxSample()
            TextSample()
            ButtonSample()
            TextFieldSample()
        }
    }
}
3.2.3 @Preview 常用参数
  • showBackground = true:显示灰色背景,看得更清楚
  • widthDp / heightDp:固定预览窗口大小
  • showSystemUi = true:显示状态栏、导航栏模拟真机
3.2.4 操作方式
  1. 写完 @Preview 后,函数左侧会出现 小眼睛图标
  2. 点击 → Render Preview 自动渲染 UI
  3. 修改代码,预览实时刷新,极大提升调试效率
3.3 入口规则
  1. @Composable 注解的 Kotlin 函数 = UI 组件
  2. 函数无返回值、首字母大写(规范)
  3. setContent 是 Activity 挂载 Compose 根节点
kotlin 复制代码
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 根Compose容器
        setContent {
            MyAppTheme { // 全局主题包裹
                Greeting("Hello Jetpack Compose")
            }
        }
    }
}

// 可组合函数 @Composable
@Composable
fun Greeting(text: String) {
    // Text 基础文本组件
    Text(
        text = text,
        fontSize = 24.sp,
        color = Color.Blue
    )
}

// 预览注解,Split窗口直接看UI效果
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyAppTheme {
        Greeting("预览文本")
    }
}

快捷键:点击 @Preview 旁小图标打开可视化预览。

二、核心基础组件(布局 + 基础控件)

1. 三大基础布局Row / Column / Box

对应传统 XML:

  • Column ≈ LinearLayout 垂直
  • Row ≈ LinearLayout 水平
  • Box ≈ FrameLayout 层叠堆叠
Row 水平布局(横向排列)
kotlin 复制代码
@Composable
fun RowDemo() {
    Row(
        horizontalArrangement = Arrangement.SpaceEvenly, // 水平分布
        verticalAlignment = Alignment.CenterVertically     // 垂直居中
    ) {
        Text("A")
        Text("B")
        Text("C")
    }
}
Column 垂直布局(纵向排列)
kotlin 复制代码
@Composable
fun ColumnDemo() {
    Column(
        modifier = Modifier.padding(20.dp),
        verticalArrangement = Arrangement.Top,
        horizontalAlignment = Alignment.Start
    ) {
        Text("第一行")
        Text("第二行")
    }
}

常用 verticalArrangement

Top / Center / Bottom / SpaceBetween / SpaceAround / SpaceEvenly

Box 层叠布局(FrameLayout)
kotlin 复制代码
@Composable
fun BoxDemo() {
    Box(
        modifier = Modifier.size(200.dp)
    ) {
        Box(Modifier.fillMaxSize().background(Color.Gray))
        Text("悬浮文字", Modifier.align(Alignment.Center))
    }
}

对齐方式:align(Alignment.TopStart/Center/BottomEnd)

2. Modifier 修饰器(Compose 灵魂)

所有组件通过 Modifier 设置样式、尺寸、背景、内边距、点击、滚动等,链式调用:

常用方法:

kotlin 复制代码
Text(
    text = "Modifier完整示例",
    modifier = Modifier
        .padding(16.dp)                  // 四周内边距
        .padding(horizontal = 20.dp)      // 左右边距
        .fillMaxWidth()                   // 占满父宽度
        .height(50.dp)                    // 固定高度
        .background(
            color = Color.Cyan,
            shape = RoundedCornerShape(12.dp) // 圆角矩形
        )
        .clip(RoundedCornerShape(12.dp))  // 裁剪圆角
        .shadow(6.dp, RoundedCornerShape(12.dp)) // 阴影
        .clickable {                      // 点击事件
            println("点击了文本")
        }
)

重点:

  • 顺序影响效果:先 backgroundshadow 和反过来不一样
  • dp 是尺寸单位,sp 只用于文字字号

3. 常用基础控件 Text / Button / TextField/Image

3.1 Text 文本:字体、颜色、行高、字符串资源
kotlin 复制代码
@Composable
fun TextSample() {
    Text(
        text = "Jetpack Compose 文本",
        fontSize = 22.sp,
        color = Color(0xFF2196F3),
        maxLines = 2,
        overflow = TextOverflow.Ellipsis,
        fontWeight = FontWeight.Bold
    )
}
3.2 Image 图片加载
kotlin 复制代码
Image(
    painter = painterResource(id = R.drawable.ic_launcher),
    contentDescription = "图标",
    modifier = Modifier.size(80.dp)
)
3.3 Button / OutlinedButton / TextButton 按钮
kotlin 复制代码
Button(onClick = { /* 点击逻辑 */ }) {
    Text("普通按钮")
}
//三种常用样式:
@Composable
fun ButtonSample() {
    Column(Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
        // 填充按钮
        Button(onClick = { /* 点击逻辑 */ }) {
            Text("主要按钮")
        }

        // 边框按钮
        OutlinedButton(onClick = {}) {
            Text("边框按钮")
        }

        // 文字按钮
        TextButton(onClick = {}) {
            Text("文字按钮")
        }
    }
}

//`spacedBy(10.dp)`:子组件之间统一间距,替代重复写 padding。
3.4 TextField 输入框(文本输入: 受控组件)
kotlin 复制代码
@Composable
fun TextFieldSample() {
    // remember 保存状态,mutableStateOf 可观察变量, 
    // `by` 委托语法简化 `.value` 写法
    var inputContent by remember { mutableStateOf("") }

    TextField(
        value = inputContent,
        onValueChange = { newText ->
            inputContent = newText
        },
        label = { Text("请输入用户名") },
        placeholder = { Text("提示文字") },
        modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp)
    )
}

必须配合状态使用

三、核心原理:状态管理(重中之重)

Compose UI 完全依赖State 状态驱动,状态改变自动重组(recomposition)刷新界面。

1. 基础 remember + mutableStateOf

remember:在组件重组时保存变量,不会被重置 mutableStateOf:创建可观察状态,修改触发 UI 刷新

kotlin 复制代码
@Composable
fun CounterDemo() {
    // 计数器状态
    var count by remember { mutableStateOf(0) }

    Column(Modifier.padding(20.dp)) {
        Text("计数:$count")
        Button(onClick = { count++ }) {
            Text("+1")
        }
    }
}

关键字 by 委托写法,直接赋值;不加 by 需要 .valuecount.value++

2. 状态提升(单向数据流)

最佳实践:UI 组件只负责展示,状态由上层传入,解耦复用:

kotlin 复制代码
// 纯展示组件,无内部状态
@Composable
fun CountView(count: Int, onAdd: () -> Unit) {
    Column {
        Text("计数 $count")
        Button(onClick = onAdd) { Text("加") }
    }
}

// 父组件持有状态
@Composable
fun ParentPage() {
    var count by remember { mutableStateOf(0) }
    CountView(count = count, onAdd = { count++ })
}

3. 复杂状态:data class + mutableStateOf

kotlin 复制代码
data class User(var name: String, var age: Int)

@Composable
fun UserStateDemo() {
    var user by remember { mutableStateOf(User("张三", 20)) }
    Column {
        Text("姓名:${user.name} 年龄:${user.age}")
        Button(onClick = { user = user.copy(age = user.age + 1) }) {
            Text("长大一岁")
        }
    }
}

⚠️ 必须用 copy 创建新对象,Compose 靠对象引用变化感知更新。

4. 状态存储方案层级(由简单到项目级)

  1. remember:临时页面内状态,页面销毁丢失
  2. rememberSaveable:横竖屏旋转、系统进程重启保存状态
  3. ViewModel:跨生命周期、跨组件共享状态(企业项目标配)
  4. 持久化:DataStore / Room 本地磁盘存储
ViewModel 在 Compose 中使用
  1. 依赖添加
gradle 复制代码
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0"
  1. ViewModel 类
kotlin 复制代码
class CountViewModel : ViewModel() {
    private val _count = MutableStateFlow(0)
    val count = _count

    fun add() {
        _count.value += 1
    }
}
  1. Compose 中调用
kotlin 复制代码
@Composable
fun ViewModelDemo() {
    val vm: CountViewModel = viewModel()
    val count by vm.count.collectAsStateWithLifecycle()

    Column {
        Text("ViewModel计数:$count")
        Button(onClick = { vm.add() }) {
            Text("增加")
        }
    }
}

collectAsStateWithLifecycle 绑定生命周期,避免后台无效订阅。

四、进阶布局与滚动、列表

1. 滚动容器

  • VerticalScroll 纵向滚动 Column
  • HorizontalScroll 横向滚动 Row
kotlin 复制代码
Column(
    Modifier.verticalScroll(rememberScrollState())
) {
    // 超长内容自动滚动
}

2. Lazy 高性能列表(替代 RecyclerView)

Compose 懒加载列表,只渲染屏幕可见 Item,性能等同 RecyclerView

LazyColumn 垂直列表
kotlin 复制代码
@Composable
fun LazyListDemo() {
    val list = List(100) { "条目 $it" }
    LazyColumn(Modifier.fillMaxSize()) {
        items(list) { item ->
            Text(
                text = item,
                Modifier.padding(16.dp).fillMaxWidth()
            )
        }
    }
}

其他懒加载组件:

  • LazyRow 横向列表
  • LazyVerticalGrid 网格布局(GridView)
  • LazyHorizontalGrid 横向网格

五、导航、路由与页面跳转(Navigation Compose)

1. 依赖

gradle 复制代码
implementation "androidx.navigation:navigation-compose:2.8.0"

2. 基础多页面跳转完整示例

kotlin 复制代码
// 定义路由常量
object Route {
    const val HOME = "home"
    const val DETAIL = "detail/{id}"
}

@Composable
fun AppNavHost() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = Route.HOME
    ) {
        // 首页页面
        composable(Route.HOME) {
            HomePage { id ->
                navController.navigate("detail/$id")
            }
        }
        // 详情页,接收参数
        composable(
            Route.DETAIL,
            arguments = listOf(navArgument("id") { type = NavType.IntType })
        ) { backStackEntry ->
            val id = backStackEntry.arguments?.getInt("id") ?: 0
            DetailPage(id) {
                navController.popBackStack() // 返回上一页
            }
        }
    }
}

// 首页
@Composable
fun HomePage(onGoDetail: (Int) -> Unit) {
    Button(onClick = { onGoDetail(1001) }) {
        Text("跳转到详情页")
    }
}

// 详情页
@Composable
fun DetailPage(id: Int, onBack: () -> Unit) {
    Column(Modifier.padding(20.dp)) {
        Text("收到参数ID:$id")
        Button(onClick = onBack) {
            Text("返回")
        }
    }
}

在 Activity 根节点调用 AppNavHost() 即可实现单 Activity 多页面架构。

六、高级特性篇

1. 主题系统 Material3

项目自动生成 Theme.kt,统一管理:

  • 主色、辅色、背景色
  • 字体样式 Typography
  • 暗黑模式自动切换
kotlin 复制代码
MaterialTheme(
    colorScheme = if (isDark) DarkColorScheme else LightColorScheme,
    typography = Typography,
    shapes = Shapes
) {
    // 页面内容
}

2. Compose 动画

简单数值动画 animateDpAsState
kotlin 复制代码
@Composable
fun AnimateSizeDemo() {
    var expand by remember { mutableStateOf(false) }
    val size by animateDpAsState(targetValue = if (expand) 200.dp else 80.dp)

    Box(
        Modifier
            .size(size)
            .background(Color.Red)
            .clickable { expand = !expand }
    )
}

复杂动画:AnimatedVisibility 显示隐藏、animateContentSize 内容大小动画、Transition 多状态切换。

3. 手势与拖拽

Modifier.draggableModifier.pointerInput 自定义触摸、滑动、双指缩放。

4. Compose 与传统 View 混合使用

4.1 Compose 嵌套 XML View
kotlin 复制代码
AndroidView(
    factory = { context ->
        LayoutInflater.from(context).inflate(R.layout.old_view, null)
    }
)
4.2 XML 布局嵌套 Compose
xml 复制代码
<androidx.compose.ui.platform.ComposeView
    android:id="@+id/compose_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
kotlin 复制代码
findViewById<ComposeView>(R.id.compose_view).setContent {
    Text("嵌入在XML中的Compose")
}

5. 副作用函数(生命周期)

处理网络请求、资源释放、订阅监听,避免重组重复执行:

  1. LaunchedEffect:协程副作用,页面启动执行、key 变化重启
  2. DisposableEffect:页面销毁时释放资源(解绑广播、关闭流)
  3. SideEffect:每次成功重组后执行
  4. rememberCoroutineScope:组件作用域协程

示例:进入页面请求网络

kotlin 复制代码
@Composable
fun NetRequestDemo() {
    var data by remember { mutableStateOf("加载中...") }
    LaunchedEffect(Unit) { // Unit只执行一次
        // 模拟网络请求
        delay(1000)
        data = "请求成功的数据"
    }
    Text(data)
}

七、工程化最佳实践(项目落地规范)

1. 代码分层架构

textile 复制代码
com.xxx.compose
├── ui/          页面层Compose组件
│   ├── home/
│   ├── mine/
│   └── common/ 通用封装组件(TopBar、EmptyView、Button封装)
├── viewmodel/   ViewModel层
├── repository/ 数据仓库
├── data/        数据源(Api、Room、DataStore)
└── navigation/  统一路由管理

2. 通用组件封装原则

  • 原子组件:只接收参数,无内部硬编码状态
  • 样式统一抽取:封装 Modifier 扩展函数、尺寸常量、颜色常量
kotlin 复制代码
// 扩展函数示例
fun Modifier.cardStyle() = this
    .fillMaxWidth()
    .padding(8.dp)
    .shadow(2.dp, RoundedCornerShape(12.dp))
    .clip(RoundedCornerShape(12.dp))
    .background(Color.White)

3. 性能优化关键点

  1. 减少不必要重组:稳定参数(添加 @Stable 注解)
  2. 大列表一律用 LazyColumn/LazyRow,禁止滚动 Column 加载上千条数据
  3. 图片使用 Coil 加载(Compose 专用图片库)
gradle 复制代码
implementation "io.coil-kt:coil-compose:2.6.0"
kotlin 复制代码
AsyncImage(
    model = "https://xxx.jpg",
    contentDescription = null,
    modifier = Modifier.size(120.dp)
)
  1. 避免在 Composable 函数内部创建对象、执行耗时计算,移入 ViewModel 或 remember 缓存

完整 Demo

kotlin 复制代码
package com.example.composebasic

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.spacedBy
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyAppTheme {
                MainBasicPage()
            }
        }
    }
}

@Composable
fun MainBasicPage() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(20.dp),
        verticalArrangement = Arrangement.spacedBy(24.dp)
    ) {
        HelloText()
        ColumnSample()
        RowSample()
        BoxSample()
        TextSample()
        ButtonSample()
        TextFieldSample()
    }
}

@Composable
fun HelloText() {
    Text("1. 第一个Compose组件", fontSize = 20.sp, fontWeight = FontWeight.Bold)
}

@Composable
fun ColumnSample() {
    Column(Modifier.background(Color(0xFFF5F5F5)).padding(12.dp)) {
        Text("Column 垂直布局1")
        Text("Column 垂直布局2")
        Text("Column 垂直布局3")
    }
}

@Composable
fun RowSample() {
    Row(
        Modifier
            .fillMaxWidth()
            .background(Color(0xFFE3F2FD))
            .padding(12.dp),
        horizontalArrangement = Arrangement.SpaceAround
    ) {
        Text("A")
        Text("B")
        Text("C")
    }
}

@Composable
fun BoxSample() {
    Box(
        Modifier
            .size(180.dp)
            .background(Color.LightGray)
    ) {
        Box(Modifier.fillMaxSize().background(Color.Blue.copy(alpha = 0.2f)))
        Text("Box层叠居中", Modifier.align(Alignment.Center), fontSize = 16.sp)
        Text("右下角", Modifier.align(Alignment.BottomEnd).padding(8.dp), fontSize = 12.sp)
    }
}

@Composable
fun TextSample() {
    Text(
        text = "Text 文本控件,带颜色、加粗、单行省略效果测试超长文字超长文字超长文字",
        fontSize = 18.sp,
        color = Color(0xFFD81B60),
        fontWeight = FontWeight.Medium,
        maxLines = 1,
        overflow = TextOverflow.Ellipsis
    )
}

@Composable
fun ButtonSample() {
    Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
        Button(onClick = {}) { Text("主按钮") }
        OutlinedButton(onClick = {}) { Text("边框按钮") }
        TextButton(onClick = {}) { Text("文字按钮") }
    }
}

@Composable
fun TextFieldSample() {
    var text by remember { mutableStateOf("") }
    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("输入框演示") },
        modifier = Modifier.fillMaxWidth()
    )
}

@Preview(showBackground = true, widthDp = 380, heightDp = 900)
@Composable
fun PreviewAll() {
    MyAppTheme {
        MainBasicPage()
    }
}

@Composable
fun MyAppTheme(content: @Composable () -> Unit) {
    MaterialTheme {
        content()
    }
}

附赠:高频拓展方向

  1. Compose MVI 架构完整模板(需要我直接给一套可复制脚手架)
  2. 封装通用弹窗、加载框、顶部导航栏、下拉刷新
  3. 权限请求、文件读写、相机相册调用 Compose 封装
  4. Compose Multiplatform 一套代码跑 Android、iOS、桌面端
相关推荐
toooooop81 小时前
踩坑:PHP7.2导出Excel正常,升级7.3文件损坏需修复
android·excel
学习星球2 小时前
Astro 全栈实战:拆解 RealWorld 项目
前端·javascript·架构·系统架构·前端框架·c5全栈
mmsx2 小时前
我明明调用了 zoomToBounds,地图却总是停在别处?延迟加到 5 秒也没用,真相只有一个
android·人工智能·bug·地图
软件开发JR2 小时前
基于Web的足球青训俱乐部管理后台系统的设计与开发
java·前端·spring boot·毕业设计
那年窗外下的雪.2 小时前
VXLAN EVPN 分层排障:从 VTEP 可达、ARP/MAC 到 MAC Mobility
服务器·前端·网络·数据库·spine
禁止摆烂_才浅3 小时前
JavaScript 类型判断:instanceof 与 constructor 原理深度解析
前端·javascript·面试
蜡台3 小时前
Jetpack Compose 核心:状态管理 + Lazy 列表
android·kotlin·state·jetpack compose
gezg3 小时前
DeepSeek Harness 插件:Excel 拖进输入框,AI 自己去读文件
前端·ai编程
Asize3 小时前
HTTP 明明无状态,登录态怎么就保住了——React + Zustand + JWT 鉴权全流程拆解
前端·javascript