A2UI实时渲染展示

1、在minimax平台上根据自然语言生成前端代码

https://agent.minimaxi.com/chat?id=3758586920273252

用户问题:现在有个收支数据,请给我生成对应的a2ui卡片,data={"time": "1月", "in": 1230, "out": 20},其中in为收入,out为支出,单位是元,请用a2ui协议生成代码,并提供文件下载

生成文件如下:

复制代码
{
  "type": "view",
  "props": {
    "className": "finance-card"
  },
  "style": {
    "backgroundColor": "#FFFFFF",
    "borderRadius": 12,
    "padding": 16,
    "flexDirection": "row",
    "justifyContent": "space-between",
    "alignItems": "center",
    "boxShadow": "0 2px 8px rgba(0,0,0,0.05)",
    "marginBottom": 12
  },
  "children": [
    {
      "type": "text",
      "props": {
        "text": "1月"
      },
      "style": {
        "fontSize": 24,
        "fontWeight": "bold",
        "color": "#1F2937",
        "flex": 1
      }
    },
    {
      "type": "view",
      "style": {
        "flexDirection": "column",
        "alignItems": "flex-end"
      },
      "children": [
        {
          "type": "view",
          "style": {
            "flexDirection": "row",
            "alignItems": "center",
            "marginBottom": 4
          },
          "children": [
            {
              "type": "text",
              "props": {
                "text": "收入"
              },
              "style": {
                "fontSize": 12,
                "color": "#9CA3AF",
                "marginRight": 8
              }
            },
            {
              "type": "text",
              "props": {
                "text": "+¥1,230"
              },
              "style": {
                "fontSize": 16,
                "fontWeight": "600",
                "color": "#EF4444"
              }
            }
          ]
        },
        {
          "type": "view",
          "style": {
            "flexDirection": "row",
            "alignItems": "center"
          },
          "children": [
            {
              "type": "text",
              "props": {
                "text": "支出"
              },
              "style": {
                "fontSize": 12,
                "color": "#9CA3AF",
                "marginRight": 8
              }
            },
            {
              "type": "text",
              "props": {
                "text": "-¥20"
              },
              "style": {
                "fontSize": 16,
                "fontWeight": "600",
                "color": "#10B981"
              }
            }
          ]
        }
      ]
    }
  ]
}

给出的js渲染文件如下:

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>A2UI 收支卡片演示</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }

        .container {
            width: 100%;
            max-width: 400px;
        }

        .card-wrapper {
            background: #ffffff;
            border-radius: 20px;
            padding: 24px;
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
        }

        .card-title {
            text-align: center;
            color: #333;
            font-size: 18px;
            font-weight: 600;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 1px solid #eee;
        }

        /* A2UI Renderer Base Styles */
        .a2ui-view {
            display: flex;
            flex-direction: column;
        }

        .a2ui-text {
            display: block;
        }

        .a2ui-image {
            max-width: 100%;
            height: auto;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="card-wrapper">
            <div class="card-title">A2UI 收支卡片</div>
            <div id="app"></div>
        </div>
    </div>

    <script>
        // A2UI 轻量级渲染器
        const A2UIRenderer = {
            render: function(node, parent) {
                if (!node) return;

                let el;
                const type = node.type || 'view';

                // 根据类型创建元素
                switch(type) {
                    case 'text':
                        el = document.createElement('span');
                        el.innerText = node.props?.text || '';
                        break;
                    case 'button':
                        el = document.createElement('button');
                        if (node.props?.text) el.innerText = node.props.text;
                        el.style.cssText = 'border: none; cursor: pointer; outline: none;';
                        break;
                    case 'image':
                        el = document.createElement('img');
                        el.src = node.props?.src || '';
                        el.alt = node.props?.alt || 'image';
                        break;
                    case 'view':
                    default:
                        el = document.createElement('div');
                        break;
                }

                // 应用样式
                if (node.style) {
                    Object.entries(node.style).forEach(([key, value]) => {
                        // 需要添加px单位的属性
                        const pxProps = [
                            'width', 'height', 'fontSize', 'borderRadius',
                            'padding', 'margin', 'paddingTop', 'paddingBottom',
                            'paddingLeft', 'paddingRight', 'marginTop', 'marginBottom',
                            'marginRight', 'marginLeft', 'gap', 'lineHeight'
                        ];

                        if (pxProps.includes(key) && typeof value === 'number') {
                            el.style[key] = value + 'px';
                        } else {
                            el.style[key] = value;
                        }
                    });
                }

                // 递归渲染子元素
                if (node.children && Array.isArray(node.children)) {
                    node.children.forEach(child => {
                        this.render(child, el);
                    });
                }

                // 挂载到父元素
                if (parent) {
                    parent.appendChild(el);
                }

                return el;
            }
        };

        // 收支卡片数据
        const financeCardData = {
            "type": "view",
            "style": {
                "backgroundColor": "#FFFFFF",
                "borderRadius": 12,
                "padding": 16,
                "flexDirection": "row",
                "justifyContent": "space-between",
                "alignItems": "center",
                "boxShadow": "0 2px 8px rgba(0,0,0,0.05)"
            },
            "children": [
                {
                    "type": "text",
                    "props": {
                        "text": "1月"
                    },
                    "style": {
                        "fontSize": 28,
                        "fontWeight": "bold",
                        "color": "#1F2937",
                        "flex": 1
                    }
                },
                {
                    "type": "view",
                    "style": {
                        "flexDirection": "column",
                        "alignItems": "flex-end"
                    },
                    "children": [
                        {
                            "type": "view",
                            "style": {
                                "flexDirection": "row",
                                "alignItems": "center",
                                "marginBottom": 8
                            },
                            "children": [
                                {
                                    "type": "text",
                                    "props": {
                                        "text": "收入"
                                    },
                                    "style": {
                                        "fontSize": 13,
                                        "color": "#9CA3AF",
                                        "marginRight": 12
                                    }
                                },
                                {
                                    "type": "text",
                                    "props": {
                                        "text": "+¥1,230"
                                    },
                                    "style": {
                                        "fontSize": 18,
                                        "fontWeight": "600",
                                        "color": "#EF4444"
                                    }
                                }
                            ]
                        },
                        {
                            "type": "view",
                            "style": {
                                "flexDirection": "row",
                                "alignItems": "center"
                            },
                            "children": [
                                {
                                    "type": "text",
                                    "props": {
                                        "text": "支出"
                                    },
                                    "style": {
                                        "fontSize": 13,
                                        "color": "#9CA3AF",
                                        "marginRight": 12
                                    }
                                },
                                {
                                    "type": "text",
                                    "props": {
                                        "text": "-¥20"
                                    },
                                    "style": {
                                        "fontSize": 18,
                                        "fontWeight": "600",
                                        "color": "#10B981"
                                    }
                                }
                            ]
                        }
                    ]
                }
            ]
        };

        // 页面加载完成后渲染卡片
        window.addEventListener('DOMContentLoaded', function() {
            const app = document.getElementById('app');
            A2UIRenderer.render(financeCardData, app);
        });
    </script>

<style>

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

.inland-security-footer {
  position: fixed;
  z-index: 10;
  bottom: 0;
  right: 0;
  width: fit-content;
  display: flex;
  justify-content: flex-end;
}

.tooltip-container {
  position: relative;
}

.trigger-content {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  padding: 8px;
  background-color: transparent;
  border-radius: 8px;
  cursor: pointer;
}

.minimax-link {
  display: flex;
  align-items: center;
  cursor: pointer;
  font-weight: 300;
  color: #adadad;
  text-decoration: none;
}

.minimax-link:visited {
  color: #adadad;
}

.minimax-link:hover {
  color: #666666;
}

.tooltip-content {
  position: absolute;
  bottom: 100%;
  right: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 8px;
  padding-bottom: 16px; /* 8px 内容间距 + 8px 用于鼠标移动的透明区域 */
  font-size: 12px;
  line-height: 17px;
  background-color: #fafafa;
  border-radius: 12px;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  color: #171717;
}

/* 创建透明的连接区域,让鼠标可以平滑移动到 tooltip */
.tooltip-content::after {
  content: '';
  position: absolute;
  bottom: -8px;
  left: 0;
  right: 0;
  height: 16px;
}

.tooltip-container:hover .tooltip-content {
  display: flex;
}

.info-section {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}

.beian-link {
  display: flex;
  align-items: center;
  text-decoration: none;
  color: #171717;
}

.beian-icon {
  width: 14px;
  height: 14px;
  margin-right: 2px;
}

.underline-text {
  color: #171717;
  text-decoration: underline;
}

.underline-text:hover {
  color: #000000;
}

/* 深色模式支持 */
@media (prefers-color-scheme: dark) {
  .trigger-content {
    background-color: transparent;
  }

  .minimax-link,
  .minimax-link:visited {
    color: #666666;
  }

  .minimax-link:hover {
    color: #adadad;
  }

  .tooltip-content {
    background-color: #262626;
    color: #ededed;
  }

  .beian-link,
  .underline-text {
    color: #ededed;
  }

  .underline-text:hover {
    color: #ffffff;
  }
}

</style>
<div class="inland-security-footer">
  <div class="tooltip-container">
    <div class="trigger-content">
      <a href="https://www.minimaxi.com/" target="_blank" rel="noreferrer" class="minimax-link">
        <span>© 2026 MiniMax</span>
      </a>
    </div>
    <div class="tooltip-content">
      <section class="info-section">
        <span>上海稀宇科技有限公司</span>
      </section>

      <section class="info-section">
        <a class="beian-link" href="https://www.beian.gov.cn/portal/registerSystemInfo?recordcode=31010402010179" target="_blank" rel="noreferrer">
          <img alt="hailuo-beian-icon" src="https://cdn.hailuoai.com/hailuo-video-web/public_assets/223037d3-79fd-4db0-a456-749f38a6a14b.png" class="beian-icon">
          <span class="underline-text">沪公网安备31010402010179号</span>
        </a>
        <a href="https://beian.miit.gov.cn/" target="_blank" rel="noreferrer" class="underline-text">
          沪ICP备2023003282号-38
        </a>
      </section>

      <section class="info-section">
        <span>模型名称:MiniMax</span>
        <span>备案号:Shanghai-MiniMax-202505230046</span>
      </section>

      <section class="info-section">
        <a href="https://agent.minimaxi.com/doc/zh/terms-of-service.html" target="_blank" rel="noreferrer" class="underline-text">
          用户协议
        </a>
        <a href="https://agent.minimaxi.com/doc/zh/privacy-policy.html" target="_blank" rel="noreferrer" class="underline-text">
          隐私政策
        </a>
      </section>
    </div>
  </div>
</div>

</body>
</html>

通用方案如下:

前端集成A2UI主要有以下几种方式,根据你的技术栈和需求选择:

一、使用CopilotKit(推荐方案)

CopilotKit是目前最成熟的前端A2UI集成方案,提供了完整的React组件和渲染器。

1. 安装依赖

复制代码
# 使用npm
npm install @copilotkit/react-core @copilotkit/react-ui @a2ui/react

# 使用yarn
yarn add @copilotkit/react-core @copilotkit/react-ui @a2ui/react

# 使用pnpm
pnpm add @copilotkit/react-core @copilotkit/react-ui @a2ui/react

2. 基础集成代码

复制代码
// app.jsx 或 main.jsx
import { CopilotKit } from '@copilotkit/react-core';
import { CopilotSidebar } from '@copilotkit/react-ui';
import { createA2UIMessageRenderer } from '@a2ui/react';

// 创建A2UI渲染器
const a2uiRenderer = createA2UIMessageRenderer({
  theme: {
    primaryColor: '#0070f3',
    // 其他主题配置
  }
});

function App() {
  return (
    <CopilotKit
      runtimeUrl="/api/copilotkit" // 后端API路由
      renderActivityMessages={[a2uiRenderer]} // 注册A2UI渲染器
    >
      <CopilotSidebar
        instructions="你是一个餐厅助手,可以帮助用户查找和预订餐厅。"
        defaultOpen={true}
      />
      {/* 你的应用内容 */}
    </CopilotKit>
  );
}

3. 配置API路由(Next.js示例)

复制代码
// app/api/copilotkit/route.js
import { CopilotBackend } from '@copilotkit/backend';
import { A2AClient } from '@a2ui/a2a-client';

export async function POST(request) {
  const backend = new CopilotBackend({
    actions: [
      // 你的自定义操作
    ],
  });

  // 连接到A2A后端
  const a2aClient = new A2AClient({
    endpoint: 'http://localhost:10002', // A2A Agent地址
  });

  return backend.stream(request, {
    onMessage: async (message) => {
      // 将消息转发到A2A Agent
      const response = await a2aClient.sendMessage(message);
      return response;
    },
  });
}

二、使用官方渲染器

A2UI官方提供了多种前端框架的渲染器:

1. Lit渲染器(Web Components)

复制代码
npm install @a2ui/lit

// 使用Lit渲染器
import { A2UIRenderer } from '@a2ui/lit';

class MyElement extends HTMLElement {
  constructor() {
    super();
    this.renderer = new A2UIRenderer();
  }

  connectedCallback() {
    // 连接到A2A流
    const eventSource = new EventSource('/a2a-stream');
    eventSource.onmessage = (event) => {
      const a2uiMessage = JSON.parse(event.data);
      this.renderer.render(a2uiMessage, this);
    };
  }
}

customElements.define('my-a2ui-element', MyElement);

2. Angular渲染器

复制代码
npm install @a2ui/angular

// app.module.ts
import { A2UIModule } from '@a2ui/angular';

@NgModule({
  imports: [
    A2UIModule,
    // 其他模块
  ]
})
export class AppModule { }

// 组件中使用
@Component({
  selector: 'app-a2ui',
  template: `
    <a2ui-surface
      [surfaceId]="'main'"
      (action)="onAction($event)">
    </a2ui-surface>
  `
})
export class A2UIComponent {
  onAction(event: any) {
    console.log('A2UI Action:', event);
    // 处理用户交互
  }
}

3. Flutter渲染器(移动/桌面)

复制代码
# pubspec.yaml
dependencies:
  a2ui_flutter: ^0.1.0

import 'package:a2ui_flutter/a2ui_flutter.dart';

class A2UIPage extends StatefulWidget {
  @override
  _A2UIPageState createState() => _A2UIPageState();
}

class _A2UIPageState extends State<A2UIPage> {
  final A2UIController _controller = A2UIController();

  @override
  void initState() {
    super.initState();
    _connectToAgent();
  }

  Future<void> _connectToAgent() async {
    final stream = await connectToA2AAgent('ws://localhost:8080');
    stream.listen((message) {
      _controller.handleMessage(message);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: A2UIWidget(
        controller: _controller,
        onAction: (action) {
          // 处理用户交互
          print('Action: $action');
        },
      ),
    );
  }
}

三、自定义集成方案

如果你需要更灵活的集成,可以手动处理A2UI协议:

1. 基本消息处理

复制代码
// A2UI消息处理器
class A2UIHandler {
  constructor() {
    this.components = new Map();
    this.dataModel = new Map();
  }

  // 处理A2UI消息流
  async handleStream(stream) {
    const reader = stream.getReader();
    const decoder = new TextDecoder();

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      const text = decoder.decode(value);
      const lines = text.split('\n');

      for (const line of lines) {
        if (line.trim()) {
          try {
            const message = JSON.parse(line);
            this.processMessage(message);
          } catch (error) {
            console.error('解析A2UI消息失败:', error);
          }
        }
      }
    }
  }

  // 处理不同类型的A2UI消息
  processMessage(message) {
    if (message.beginRendering) {
      this.beginRendering(message.beginRendering);
    } else if (message.surfaceUpdate) {
      this.surfaceUpdate(message.surfaceUpdate);
    } else if (message.dataModelUpdate) {
      this.dataModelUpdate(message.dataModelUpdate);
    }
  }

  beginRendering(config) {
    const { surfaceId, root, styles } = config;
    // 初始化渲染表面
    console.log(`开始渲染表面: ${surfaceId}, 根组件: ${root}`);
    this.applyStyles(styles);
  }

  surfaceUpdate(update) {
    const { surfaceId, components } = update;
    
    components.forEach(component => {
      const { id, component: componentDef } = component;
      
      // 根据组件类型渲染
      if (componentDef.Button) {
        this.renderButton(id, componentDef.Button);
      } else if (componentDef.Card) {
        this.renderCard(id, componentDef.Card);
      } else if (componentDef.List) {
        this.renderList(id, componentDef.List);
      }
      // 处理其他组件类型...
    });
  }

  dataModelUpdate(update) {
    const { surfaceId, contents } = update;
    
    contents.forEach(item => {
      this.dataModel.set(item.key, item.value);
    });
    
    // 更新绑定数据的组件
    this.updateDataBindings();
  }

  renderButton(id, config) {
    const button = document.createElement('button');
    button.id = id;
    button.textContent = config.label || '按钮';
    button.className = `btn btn-${config.variant || 'primary'}`;
    
    if (config.onClick) {
      button.addEventListener('click', () => {
        this.handleAction(config.onClick);
      });
    }
    
    document.getElementById('a2ui-container').appendChild(button);
    this.components.set(id, button);
  }

  handleAction(action) {
    // 发送用户交互回Agent
    fetch('/api/a2ui-action', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(action)
    });
  }
}

2. 连接到A2A Agent

复制代码
// 连接到A2A Agent
async function connectToA2AAgent(endpoint) {
  // 使用Server-Sent Events (SSE)
  const eventSource = new EventSource(`${endpoint}/stream`);
  
  const handler = new A2UIHandler();
  
  eventSource.onmessage = (event) => {
    try {
      const message = JSON.parse(event.data);
      handler.processMessage(message);
    } catch (error) {
      console.error('处理消息失败:', error);
    }
  };
  
  eventSource.onerror = (error) => {
    console.error('SSE连接错误:', error);
    // 重连逻辑
  };
  
  return {
    close: () => eventSource.close(),
    send: (action) => {
      // 发送用户操作
      return fetch(`${endpoint}/action`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(action)
      });
    }
  };
}

// 使用WebSocket
function connectWithWebSocket(endpoint) {
  const ws = new WebSocket(endpoint);
  const handler = new A2UIHandler();
  
  ws.onmessage = (event) => {
    const message = JSON.parse(event.data);
    handler.processMessage(message);
  };
  
  ws.onopen = () => {
    console.log('A2UI WebSocket连接已建立');
  };
  
  return ws;
}

四、组件库配置

1. 自定义组件Catalog

复制代码
// catalog.json - 定义可用的组件类型
{
  "components": {
    "Button": {
      "properties": {
        "label": { "type": "string" },
        "variant": { 
          "type": "string", 
          "enum": ["primary", "secondary", "outline"] 
        },
        "onClick": { "type": "object" }
      }
    },
    "Card": {
      "properties": {
        "title": { "type": "string" },
        "content": { "type": "string" },
        "imageUrl": { "type": "string" }
      }
    },
    "List": {
      "properties": {
        "direction": { 
          "type": "string", 
          "enum": ["vertical", "horizontal"] 
        },
        "items": { "type": "array" }
      }
    }
  }
}

2. 主题配置

复制代码
// theme.js
export const defaultTheme = {
  colors: {
    primary: '#0070f3',
    secondary: '#7928ca',
    background: '#ffffff',
    text: '#000000'
  },
  spacing: {
    small: '8px',
    medium: '16px',
    large: '24px'
  },
  typography: {
    fontFamily: 'system-ui, sans-serif',
    fontSize: {
      small: '12px',
      medium: '14px',
      large: '16px'
    }
  }
};

// 在渲染器中使用
const renderer = createA2UIMessageRenderer({
  theme: defaultTheme,
  components: customComponents
});

五、完整集成示例

React + CopilotKit + A2UI完整示例

复制代码
// App.jsx
import React, { useState } from 'react';
import { CopilotKit, useCopilotChat } from '@copilotkit/react-core';
import { CopilotPopup } from '@copilotkit/react-ui';
import { createA2UIMessageRenderer } from '@a2ui/react';

const a2uiRenderer = createA2UIMessageRenderer({
  theme: {
    colors: {
      primary: '#0070f3',
      background: '#f5f5f5'
    }
  },
  onAction: (action) => {
    console.log('A2UI Action:', action);
    // 处理用户交互
    if (action.type === 'submit_form') {
      // 提交表单逻辑
    }
  }
});

function RestaurantFinder() {
  const { messages, input, setInput, submitMessage } = useCopilotChat();
  
  return (
    <div className="app">
      <CopilotPopup
        instructions="你是一个餐厅助手,可以帮助用户查找、比较和预订餐厅。"
        defaultOpen={true}
        renderActivityMessages={[a2uiRenderer]}
      />
      
      <div className="content">
        <h1>餐厅查找助手</h1>
        <div className="chat-container">
          {messages.map((msg, idx) => (
            <div key={idx} className={`message ${msg.role}`}>
              {msg.content}
            </div>
          ))}
        </div>
        
        <div className="input-area">
          <input
            value={input}
            onChange={(e) => setInput(e.target.value)}
            placeholder="输入你的需求,如:找5家北京的中餐厅"
            onKeyPress={(e) => e.key === 'Enter' && submitMessage()}
          />
          <button onClick={submitMessage}>发送</button>
        </div>
      </div>
    </div>
  );
}

function App() {
  return (
    <CopilotKit
      runtimeUrl="/api/copilotkit"
      publicApiKey={process.env.COPILOTKIT_API_KEY}
    >
      <RestaurantFinder />
    </CopilotKit>
  );
}

export default App;

六、最佳实践建议

  1. 渐进式集成:先从简单的组件开始,逐步增加复杂度

  2. 错误处理:确保A2UI消息解析失败时有降级方案

  3. 性能优化:使用虚拟列表处理大量数据,实现增量更新

  4. 样式隔离:使用Shadow DOM或CSS-in-JS避免样式冲突

  5. 状态管理:将A2UI状态与你的应用状态同步

  6. 测试策略:编写A2UI消息的单元测试和集成测试

七、调试工具

1. A2UI Composer(可视化设计工具)

访问:https://a2ui-editor.copilotkit.ai/

2. 浏览器开发者工具

复制代码
// 在控制台调试
window.a2uiDebug = {
  logMessages: true,
  showWireframe: false,
  validateSchema: true
};

3. 消息监控

复制代码
// 监控A2UI消息流
const originalFetch = window.fetch;
window.fetch = function(...args) {
  if (args[0].includes('/a2ui')) {
    console.log('A2UI请求:', args);
    return originalFetch.apply(this, args).then(response => {
      console.log('A2UI响应:', response);
      return response;
    });
  }
  return originalFetch.apply(this, args);
};

八、常见问题解决

  1. 消息解析失败:检查JSON格式,确保符合A2UI Schema

  2. 组件未渲染:确认组件已在Catalog中注册

  3. 样式不生效:检查主题配置和CSS加载顺序

  4. 事件不触发:验证action配置和事件绑定

  5. 性能问题:使用增量更新,避免全量重新渲染

总结:前端集成A2UI的核心是选择合适的渲染器(推荐CopilotKit),正确处理A2UI消息流,并实现组件渲染和用户交互的闭环。根据你的技术栈选择对应的集成方案,从简单示例开始逐步完善。

相关推荐
NGC_66112 小时前
Java基础面试题2
java·开发语言·python
马猴烧酒.2 小时前
【JAVA算法|hot100】贪心算法类型题目详解笔记
java·开发语言·ide·笔记·算法·spring·贪心算法
语戚2 小时前
深入浅出 AOP:织入时机、JDK 动态代理与 CGLIB 原理及 Spring 选择策略
java·开发语言·spring·jdk·代理模式·aop·动态代理
bubiyoushang8882 小时前
基于MATLAB的可见光通信(VLC)发射端:电-光转换与LED驱动仿真
开发语言·matlab
014-code2 小时前
Vue 生命周期完全指南
前端·javascript·vue.js
冴羽yayujs2 小时前
资深前端都在用的 9 个调试偏方
前端·javascript·调试
Amumu121382 小时前
CSS移动端
前端·css·css3
不光头强2 小时前
Java中的异常
java·开发语言
lichenyang4532 小时前
组件设计模式与通信
前端·javascript·设计模式