【Cloudscape云景】Cloudscape云景-React框架的使用-文档细读-云景的组件部分1
写在前面
网址如下: cloudscape.design/components/… Cloudscape共有72个组件, 我们笔记顺序按照组件分类记录.
修改了一下文档中的实例代码, 给文档中实例代码一个使用场景, 这部分可能在Pattern里有. 我没看不知道
安装使用
全局样式包和open sans字体
npm install @cloudscape-design/global-styles
在app里导入
import "@cloudscape-design/global-styles/index.css"
安装组件
npm install @cloudscape-design/components
导入
import ComponentName from "@cloudscape-design/components/{component-name}"
或者这样导入
import { Button } from "@cloudscape-design/components"
全部代码样例如下
import { useState } from "react";
import Header from "@cloudscape-design/components/header";
import Container from "@cloudscape-design/components/container";
import SpaceBetween from "@cloudscape-design/components/space-between";
import Input from "@cloudscape-design/components/input";
import Button from "@cloudscape-design/components/button";
export default function App() {
const [value, setValue] = useState("");
return (
<SpaceBetween size="m">
<Header variant="h1">Hello World!</Header>
<Container>
<SpaceBetween size="s">
<span>Start editing to see some magic happen</span>
<Input
value={value}
onChange={(event) => setValue(event.detail.value)}
/>
<Button variant="primary">Click me</Button>
</SpaceBetween>
</Container>
</SpaceBetween>
);
}
npm start后, 如果出现这样的页面证明成功配置
react的严格模式, 会导致输出两次. 不是错误
布局部分
分类这部分比较难划分, 比如分类在A的组件也可以放在B中.
然后他甚至就在组件A的代码上加了一行就放到组件B里了~
有的没有写实例代码, 我就写一下demo.
应用程序布局 组件
- 基本布局组件: 该组件适用于具有导航、内容区域和工具或帮助面板的应用程序。
- 自定义头部或页脚: 通过
headerSelector
和footerSelector
属性指定。 - 状态管理: 描述了如何控制导航、工具、分割面板等的状态。
所有的状态管理就是事件控制. 云景推荐使用可控状态管理,使用事件传递.
每个组件都分成了, properties 属性, Slots插槽, Event事件,Function函数. 区别如下:
属性: 用来配置组件, 可以用来配置组件外观, 行为, 内容等.navigationOpen
属性用来控制导航抽屉是否打开。
插槽: 将内容插入特定位置用来展示特定内容. 一个名为 navigation
的插槽,可以在其中插入自定义的导航菜单。
事件: 组件触发事件, 当事件触发组件会通过事件来相应. 如果导航抽屉被打开或关闭,组件可能会触发一个名为 onNavigationChange
的事件.
函数: 通常是组件提供的一些方法,用于执行特定的操作或任务。例如,组件可能提供了一个名为 closeNavigationIfNecessary
的函数,你可以在代码中调用这个函数来手动关闭导航抽屉。
函数和事件区别.... 一个是调用一个是特定情况触发, 挺简单的就是简单解释一下.
import React, { useState } from 'react';
import { AppLayout } from 'cloudscape'; // 导入路径可能需要调整
function MyApp() {
const [navigationOpen, setNavigationOpen] = useState(false);
const [toolsOpen, setToolsOpen] = useState(false);
// 定义 ariaLabels
const ariaLabels = {
navigation: "Navigation drawer",
navigationClose: "Close navigation drawer",
navigationToggle: "Open navigation drawer",
notifications: "Notifications",
tools: "Help panel",
toolsClose: "Close help panel",
toolsToggle: "Open help panel"
};
// 处理导航切换事件
const handleNavigationChange = (detail) => {
setNavigationOpen(detail.open);
};
// 处理工具切换事件
const handleToolsChange = (detail) => {
setToolsOpen(detail.open);
};
return (
<AppLayout
ariaLabels={ariaLabels}
navigationOpen={navigationOpen}
toolsOpen={toolsOpen}
onNavigationChange={handleNavigationChange}
onToolsChange={handleToolsChange}
>
{/* 可以在此添加其他插槽内容,如内容、导航、工具等 */}
</AppLayout>
);
}
export default MyApp;
ariaLabels 这个标签是用来辅助ARIA(可访问富互联网):残疾人士等提供无障碍访问动态、可交互的技术.
Box组件
Box组件主要就是提供了一些, 段落文字, H1文字, 代码块, 值得一提的是这里放了按钮的布局
Split panel组件
这个图案意思是, 选中资源后, 会在下侧展示分割组件;
原则: 不要使用分割组件来显示帮助信息, 不要使用分割面板来代替详情页.
它的作用是显示资源详情信息. (详情页会有其他交互, 这里是没有交互,只做反显)
Wizard向导组件
import * as React from "react";
import Wizard from "@cloudscape-design/components/wizard";
import {Container, FormField, Input, SpaceBetween, Header, Link, Box, ColumnLayout, Button} from "@cloudscape-design/components";
export default () => {
const [
activeStepIndex,
setActiveStepIndex
] = React.useState(0);
return (
<Wizard
i18nStrings={{
stepNumberLabel: stepNumber =>
`Step ${stepNumber}`,
collapsedStepsLabel: (stepNumber, stepsCount) =>
`Step ${stepNumber} of ${stepsCount}`,
skipToButtonLabel: (step, stepNumber) =>
`Skip to ${step.title}`,
navigationAriaLabel: "Steps",
cancelButton: "Cancel",
previousButton: "Previous",
nextButton: "Next",
submitButton: "Launch instance",
optional: "optional"
}}
onNavigate={({ detail }) =>
setActiveStepIndex(detail.requestedStepIndex)
}
activeStepIndex={activeStepIndex}
allowSkipTo
isLoadingNextStep
steps={[
{
title: "Choose instance type",
info: <Link variant="info">Info</Link>,
description:
"Each instance type includes one or more instance sizes, allowing you to scale your resources to the requirements of your target workload.",
content: (
<Container
header={
<Header variant="h2">
Form container header
</Header>
}
>
<SpaceBetween direction="vertical" size="l">
<FormField label="First field">
<Input />
</FormField>
<FormField label="Second field">
<Input />
</FormField>
</SpaceBetween>
</Container>
)
},
{
title: "Add storage",
content: (
<Container
header={
<Header variant="h2">
Form container header
</Header>
}
>
<SpaceBetween direction="vertical" size="l">
<FormField label="First field">
<Input />
</FormField>
<FormField label="Second field">
<Input />
</FormField>
</SpaceBetween>
</Container>
),
isOptional: true
},
{
title: "Configure security group",
content: (
<Container
header={
<Header variant="h2">
Form container header
</Header>
}
>
<SpaceBetween direction="vertical" size="l">
<FormField label="First field">
<Input />
</FormField>
<FormField label="Second field">
<Input />
</FormField>
</SpaceBetween>
</Container>
),
isOptional: true
},
{
title: "Review and launch",
content: (
<SpaceBetween size="xs">
<Header
variant="h3"
actions={
<Button
onClick={() => setActiveStepIndex(0)}
>
Edit
</Button>
}
>
Step 1: Instance type
</Header>
<Container
header={
<Header variant="h2">
Container title
</Header>
}
>
<ColumnLayout
columns={2}
variant="text-grid"
>
<div>
<Box variant="awsui-key-label">
First field
</Box>
<div>Value</div>
</div>
<div>
<Box variant="awsui-key-label">
Second Field
</Box>
<div>Value</div>
</div>
</ColumnLayout>
</Container>
</SpaceBetween>
)
}
]}
/>
);
}
这里主要记录一下, isLoadingNextStep.
主要在父组件里进行异步操作,案例代码如下
export default () => {
const [activeStepIndex, setActiveStepIndex] = React.useState(0);
const [isLoadingNextStep, setIsLoadingNextStep] = React.useState(false);
const loadNextStep = async () => {
setIsLoadingNextStep(true);
// 这里可以放置获取下一步数据的异步代码
// 例如,调用API或执行其他异步操作
setIsLoadingNextStep(false);
};
// 当用户导航到下一步时,触发加载
const handleNavigate = ({ detail }) => {
setActiveStepIndex(detail.requestedStepIndex);
loadNextStep();
};
return (
<Wizard
isLoadingNextStep={isLoadingNextStep}
onNavigate={handleNavigate}
// 其他属性和子组件
/>
);
};
action部分
按钮
按钮下拉菜单Button dropdown
Copy to clipboard 复制到剪切板组件
import React from 'react';
import { Box, Button, Popover, StatusIndicator } from '@cloudscape-design/components';
// import './custom.scss';
export default () => (
<span className="custom-wrapping">
<Box margin={{ right: 'xxs' }} display="inline-block">
<Popover
size="small"
position="top"
triggerType="custom"
dismissButton={false}
content={<StatusIndicator type="success">[Name of the content] copied</StatusIndicator>}
>
<Button
variant="inline-icon"
iconName="copy"
ariaLabel="Copy [name of the content]"
onClick={() => {
navigator.clipboard.writeText('text-that-gets-copied');
}}
/>
</Popover>
</Box>
text-that-gets-copied
</span>
);
主要就是修改这部分代码
类似实现如下
const textToCopy = "这是我想复制的文本";
// ...
<Button
variant="inline-icon"
iconName="copy"
ariaLabel="Copy text"
onClick={() => {
navigator.clipboard.writeText(textToCopy);
}}
/>
写的完整一些, 一般在实际中会获取某个dom的值.
import React, {useRef} from 'react';
import { Box, Button, Popover, StatusIndicator } from '@cloudscape-design/components';
export default () => {
const inputRef = useRef(null);
const handleCopyClick = () => {
if (inputRef.current) {
navigator.clipboard.writeText(inputRef.current.value);
}
};
return (
<span className="custom-wrapping">
<Box margin={{right: 'xxs'}} display="inline-block">
<Popover
size="small"
position="top"
triggerType="custom"
dismissButton={false}
content={<StatusIndicator type="success">[Name of the content] copied</StatusIndicator>}
>
<Button
variant="inline-icon"
iconName="copy"
ariaLabel="Copy [name of the content]"
onClick={() => {
navigator.clipboard.writeText(inputRef.current.value);
}}
/>
</Popover>
</Box>
<input ref={inputRef} type="text" placeholder="输入要复制的文本"/>
</span>
);
};
Segmented control分段控制组件
import * as React from "react";
import SegmentedControl from "@cloudscape-design/components/segmented-control";
export default () => {
const [selectedId, setSelectedId] = React.useState(
"seg-1"
);
return (
<SegmentedControl
selectedId={selectedId}
onChange={({ detail }) =>
setSelectedId(detail.selectedId)
}
label="Default segmented control"
options={[
{ text: "Segment 1", id: "seg-1" },
{ text: "Segment 2", id: "seg-2" },
{ text: "Segment 3", id: "seg-3" }
]}
/>
);
}
这里要控制选项卡显示不同内容可以用下面的代码
import * as React from "react";
import SegmentedControl from "@cloudscape-design/components/segmented-control";
export default () => {
const [selectedId, setSelectedId] = React.useState("seg-1");
let content;
switch (selectedId) {
case "seg-1":
content = <div>内容1</div>;
break;
case "seg-2":
content = <div>内容2</div>;
break;
case "seg-3":
content = <div>内容3</div>;
break;
default:
content = <div>默认内容</div>;
}
return (
<div>
<SegmentedControl
selectedId={selectedId}
onChange={({ detail }) => setSelectedId(detail.selectedId)}
label="Default segmented control"
options={[
{ text: "Segment 1", id: "seg-1" },
{ text: "Segment 2", id: "seg-2" },
{ text: "Segment 3", id: "seg-3" }
]}
/>
{content} {/* 这里渲染选中选项卡对应的内容 */}
</div>
);
};
显示结果如下
Input部分
AttributeEditor属性编辑组件
代码如下:
import * as React from "react";
import AttributeEditor from "@cloudscape-design/components/attribute-editor";
import {Input} from "@cloudscape-design/components";
export default () => {
const [items, setItems] = React.useState([
{ key: "some-key-1", value: "some-value-1" },
{ key: "some-key-2", value: "some-value-2" }
]);
return (
<AttributeEditor
onAddButtonClick={() => setItems([...items, {}])}
onRemoveButtonClick={({
detail: { itemIndex }
}) => {
const tmpItems = [...items];
tmpItems.splice(itemIndex, 1);
setItems(tmpItems);
}}
items={items}
addButtonText="Add new item"
definition={[
{
label: "Key",
control: item => (
<Input
value={item.key}
placeholder="Enter key"
/>
)
},
{
label: "Value",
control: item => (
<Input
value={item.value}
placeholder="Enter value"
/>
)
}
]}
removeButtonText="Remove"
empty="No items associated with the resource."
/>
);
}
实现效果如下
这个组件允许用户动态添加、编辑和删除键值对。用户可以点击添加按钮来创建新的键值对,然后在文本框中输入键和值。用户还可以点击移除按钮来删除特定的键值对。
需要注意的是,虽然这个示例允许用户在界面上添加、删除和查看键值对,但它并没有实现修改这些键值对的逻辑。你可能需要添加更多代码来处理用户输入的变化,例如通过在 Input
组件上使用 onChange
属性来监听和保存用户的输入。