如何在React中构建动态下拉组件 - 解释React复合组件模式

下拉菜单长期以来一直是网站和应用程序中的重要组成部分。它们是用户交互的默默英雄,通过简单的点击或轻触默默地促进着无数的操作和决策。

今天你可能已经遇到了其中之一,无论是在你最喜爱的在线商店上选择类别,还是在注册表单上选择你的出生日期。

但如果我告诉你,有一个秘密配方可以将你的下拉菜单从平凡提升到华丽呢?

加入我,我将解剖复合组件模式的奥秘,并利用其能力构建一个动态下拉组件。

(本文视频讲解:java567.com)

先决条件

  • HTML、CSS和Tailwind CSS的基础知识
  • React和React Hooks的基础知识。

我们将涵盖的内容:

  1. 理解下拉菜单组件
  2. 理解复合组件
  3. 如何构建下拉菜单组件
    • 常规函数式 React 方法
    • 复合组件模式方法
  4. 常规方法和复合组件方法的比较
  5. 结论

理解下拉菜单组件

下拉菜单组件在用户界面设计中起着至关重要的作用,作为交互式菜单,它们赋予用户从一系列选项中进行选择的能力。通常,它们由一个可点击的区域组成,在激活时展示用户可以进行选择的一系列选项。

下拉菜单组件的操作很简单:当用户与之交互时——通常通过点击或轻触——下拉菜单会展开,显示可用的选项。

随后,用户可以从这些选择中选择一个,然后该选择要么显示在下拉菜单本身中,要么用于更新界面中相关字段或元素。

下拉菜单组件提供了一种清晰高效的方法,向用户呈现各种选择,使其非常适用于需要同时保持整洁界面的情况下访问多个选项的场景。

下拉菜单还具有以下作用:

  • 导航辅助:作为导航辅助工具,下拉菜单通过提供跳转到不同部分或页面的菜单来帮助用户浏览网站。
  • 表单输入:简化数据输入,下拉菜单为用户提供了预定义选项供选择,例如在账户注册期间选择国家、出生日期或首选语言。
  • 过滤器:在电子商务平台上,下拉菜单使购物者能够通过选择选项,如产品类别、价格范围或品牌,来细化其搜索结果。
  • 菜单选择器:在餐厅网站上常见的,下拉菜单显示菜单或允许用户选择菜系类型,便于轻松探索和选择餐饮选项。
  • 数据展示:下拉菜单可以有效地组织和展示数据,允许用户通过日期范围、地理区域或产品类别等条件在仪表板或分析工具中过滤信息。

下拉菜单组件的示例可在此处看到:

01-展示下拉菜单演示展示下拉菜单演示

或在Semantic UI页面上。

理解复合组件

复合组件模式就像使用乐高积木一样:你组装小的部件来创建更大更复杂的东西。在React中,这是一种巧妙的设计组件的方式,由几个小部件组成,它们能够无缝地协同工作。

想象一下你正在构建一个下拉菜单。与其创建一个处理所有事情的单一组件,不如将其拆分成较小、可重用的部件。你可能有一个用于下拉按钮的组件,另一个用于选项列表,还有一个用于处理状态和交互逻辑的组件。

01-复合组件示意图复合组件示意图

这里有一个有趣的地方:这些小组件通过共享上下文进行通信。上下文就像是一个信使,可以在不需要通过组件树的每个级别传递信息的情况下,将信息从一个组件传递到另一个组件。

这是一个强大的工具,可以简化组件之间共享数据的过程,特别是当它们被深度嵌套时。

那么,为什么这种模式如此有益呢?

  • 首先,它提高了可读性。通过将复杂的组件分解为更小、更专注的部件,代码变得更易于理解和维护。每个组件都有明确的责任,这使得调试和更新变得更加容易。
  • 其次,复合组件增强了可维护性。由于组件的每个部分都处理特定的任务,因此进行更改或添加新功能变得更加简单。你可以修改组件的一个部分而不影响其他部分,减少引入错误的风险。
  • 最后,复合组件提供了极大的灵活性。你可以组合不同的部件来创建组件的特殊版本,而无需重写任何代码。这使得调整组件以适应不同目的和设计需求变得更加容易。

因此,虽然使用上下文来构建UI组件的想法起初可能看起来不同寻常,但这是一种巧妙的方式,可以创建动态和可重用的组件,从而赋予开发人员构建出色用户体验的能力。

在接下来的部分中,我们将深入探讨如何使用上下文将复合组件带入实际。

如何构建下拉菜单组件

我已经准备了一个GitHub存储库,其中包含启动文件,以加快进度。只需克隆这个存储库并安装依赖项。

在这一部分,我们将使用常规的函数式React构建一个下拉菜单组件,然后将其与CC模式进行比较,以充分理解它们之间的区别。PS:你一定会喜欢复合组件模式的。😁

02-Oh-fo-sho-memeOh Fo sho Snoop Dogg gif

常规函数式React方法

我们将从创建下拉菜单组件的基本结构开始。这将涉及设置主下拉菜单容器、触发下拉菜单的按钮以及选项列表。

const Dropdown = () => {return (<div><label className="mt-4">为任务分配用户:</label><button className="  px-4 w-full py-2 flex items-center justify-between  rounded border border-[#828FA340] hover:border-primary cursor-pointer relative "><span className="block"><FiChevronDown color="#635FC7" size={24} /></span></button></div>);
};

这将呈现:

02-Dropdown-button-rendered下拉按钮呈现

然后将用户数组传递给下拉菜单,以创建用户列表。

const Dropdown = ({ usersArray }) => {return (<div><label className="mt-4">为任务分配用户:</label><button className="  px-4 w-full py-2 flex items-center justify-between  rounded border border-[#828FA340] hover:border-primary cursor-pointer relative "><span className="block"><FiChevronDown color="#635FC7" size={24} /></span>{<div className="absolute bottom-full translate-x-9  left-full translate-y-full rounded bg-[#20212c] w-max"><ul className="flex flex-col p-2">{usersArray.map((user) => (<likey={user.id}className={`flex items-center gap-2 p-4 hover:bg-[#2b2c37] rounded transition-all duration-200 `}><imgclassName="w-6 h-6 "src={user.imgUrl}alt={`${user.name} image`}/><span>{user.name}</span></li>))}</ul></div>}</button></div>);
};

这将呈现:

03-Dropdown-list-rendered下拉列表呈现

目前,你的下拉列表默认显示。为了添加切换行为,请为其可见性创建一个状态。

 const [isDropdownOpen, setIsDropdownOpen] = useState(false);

然后将它们作为props传递给Dropdown组件。

<DropdownusersArray={usersArray}isDropdownOpen={isDropdownOpen}setIsDropdownOpen={setIsDropdownOpen}/>

在看到结果之前,将一个切换函数附加到下拉按钮,用于将下拉状态更改为true。

const toggleDropdown = () => {setIsDropdownOpen(true);
};

现在你的下拉组件应该是这样的:

const Dropdown = ({ usersArray, setIsDropdownOpen, isDropdownOpen }) => {const toggleDropdown = () => {setIsDropdownOpen(true);};return (<div><label className="mt-4">为任务分配用户:</label><buttonclassName="  px-4 w-full py-2 flex items-center justify-between  rounded border border-[#828FA340] hover:border-primary cursor-pointer relative "// Function to show the dropdown on clickonClick={toggleDropdown}><span className="block"><FiChevronDown color="#635FC7" size={24} /></span>// Conditionally rendering your dropdown list{isDropdownOpen && (<div className="absolute bottom-full translate-x-9  left-full translate-y-full rounded bg-[#20212c] w-max"><ul className="flex flex-col p-2">{usersArray.map((user) => (<likey={user.id}className={`flex items-center gap-2 p-4 hover:bg-[#2b2c37] rounded transition-all duration-200 `}><imgclassName="w-6 h-6 "src={user.imgUrl}alt={`${user.name} image`}/><span>{user.name}</span></li>))}</ul></div>)}</button></div>);
};

你的下拉现在的行为是这样的:

03-Dropdown-with-list-conditionally-rendering有条件地呈现下拉列表的下拉菜单

我知道你已经注意到你的下拉只能打开,而不能关闭。别担心,我们稍后会以更加简洁的方式来修复它。😉

04-Trust-the-process相信过程

接下来,让我们创建一种方法来为任务分配用户。首先,在App组件中创建一个状态以存储已分配的用户。

 const [assignedList, setAssignedList] = useState([]);

然后将其作为props传递给Dropdown组件。

<DropdownusersArray={usersArray}isDropdownOpen={isDropdownOpen}setIsDropdownOpen={setIsDropdownOpen}assignedList={assignedList}setAssignedList={setAssignedList}
/>

要为任务分配用户,创建一个处理函数,首先检查你试图添加的用户是否已经在数组中,如果还没有,将其添加进去,如果已经存在,则将其移除。

  function handleAssign(user) {setAssignedList((prevList) => {// 检查用户是否已存在于列表中if (prevList.includes(user)) {// 如果用户存在,则从列表中移除它const updatedList = prevList.filter((item) => item !== user);return updatedList;} else {// 如果用户不存在,则将其添加到列表中return [...prevList, user];}});}

为了确认这个函数是否有效,使用assignedList数组为每个已分配的用户添加一个检查图标。

<ul className="flex flex-col p-2">{usersArray.map((user) => (<likey={user.id}className={`flex items-center gap-2 p-4 hover:bg-[#2b2c37] rounded transition-all duration-200 `}onClick={() => handleAssign(user)}>{assignedList.includes(user) && <FiCheck />}<imgclassName="w-6 h-6 "src={user.imgUrl}alt={`${user.name} image`}/><span>{user.name}</span></li>))}
</ul>

通过这个改变,下拉应该会在点击每个用户时进行分配和取消分配。

05-Assigning-and-unassigning-users-to-the-task为任务分配和取消分配用户

为了改进UI,让我们创建一个组件来显示所有已分配的用户。

创建一个AssignedList组件,并传递其相应的状态。

 <AssignedListassignedList={assignedList}setAssignedList={setAssignedList}/>

然后使用已分配的数组来创建一些JSX。

function AssignedList({ assignedList, setAssignedList }) {return (<div className="mt-4 p-2 shadow-sm bg-[#828fa318] rounded"><h2 className="px-2 my-3 font-bold">已分配列表:</h2><div className="flex flex-wrap gap-4 ">{assignedList?.map((user, index) => (<divkey={user.id}className="flex items-center gap-1 w-[47.5%] p-2 hover:bg-[#20212c] rounded transition-all duration-200"><span>{index + 1}.</span><imgclassName="w-6 h-6 "src={user.imgUrl}alt={`${user.name} image`}/><span>{user.name}</span><span className="ml-auto cursor-pointer p-1 hover:bg-[#2b2c37] rounded-full"><FaXmark /></span></div>))}</div></div>);
}

现在测试你的组件应该得到:

06-Displaying-assigned-users-using-the-AssignedList-component使用AssignedList组件显示已分配的用户

最后一个改变是一个主观的选择,因为我更喜欢在没有当前有用户分配任务时显示其他内容。

{assignedList.length === 0 ? (<p className="mt-4 p-2 shadow-sm bg-[#828fa318] rounded">尚未为任务分配用户。</p>
) : (<AssignedListassignedList={assignedList}setAssignedList={setAssignedList}/>
)}

这将带来UI:

10-Showing-a-default-text-when-no-users-are-assigned在没有用户被分配时显示默认文本

复合组件模式方法

现在,让我们开始主要内容。首先创建一个包装整个组件的上下文。

const UserAssignContext = createContext();

然后收集我们的下拉菜单及其组件所需的所有必要数据和函数。这包括已分配用户列表、更新该列表的函数以及下拉菜单当前是否打开等内容。

然后,将这些值提供给所有子组件。

const UserAssignDropdown = ({children,assignedList,setAssignedList,users,
}) => {const UserAssignDropdownRef = useRef(null);const [isDropdownOpen, setIsDropdownOpen] = useState(false);return (<UserAssignContext.Providervalue={{assignedList,users,UserAssignDropdownRef,isDropdownOpen,setIsDropdownOpen,setAssignedList,}}><div ref={UserAssignDropdownRef}>{children}</div></UserAssignContext.Provider>);
};

有了上下文设置好了,现在是时候制作组成我们下拉菜单的各个组件了。每个组件将与上下文交互,以访问和操作必要的数据和函数。

首先,从我们刚刚构建的组件中复制每个样式。

头部组件

这个组件保持不变。

const Header = () => {return <label className="mt-4 mb-2 text-sm">为任务分配用户:</label>;
};
关闭组件

该组件从上下文中获取用于切换下拉菜单的函数。

const Close = () => {const { setIsDropdownOpen } = useContext(UserAssignContext);return (<divclassName="absolute top-0 right-0 flex items-center justify-center -translate-y-full gap-2 bg-[#C0392B] px-2 py-1 rounded-t"onClick={(e) => {e.stopPropagation();setIsDropdownOpen(false);}}><span>关闭</span><span><FaXmark size={20} /></span></div>);
};
已分配列表组件

该组件显示已分配的用户列表,并从列表中删除用户。

const AssignedList = () => {const { assignedList, setAssignedList } = useContext(UserAssignContext);function handleRemove(id) {setAssignedList((assignedList) =>assignedList.filter((user) => user.id !== id));}if (assignedList.length === 0)return (<p className="mt-4 p-2 shadow-sm bg-[#828fa318] rounded">尚未为任务分配用户。</p>);return (<div className="mt-4 p-2 shadow-sm bg-[#828fa318] rounded"><h2 className="px-2 my-3 font-bold">已分配列表:</h2><div className="flex flex-wrap gap-4 ">{assignedList?.map((user, index) => (<divkey={user.id}className="flex items-center gap-1 w-[47.5%] p-2 hover:bg-[#20212c] rounded transition-all duration-200"onClick={() => handleRemove(user.id)}><span>{index + 1}.</span><imgclassName="w-6 h-6 "src={user.imgUrl}alt={`${user.name} image`}/><span>{user.name}</span><span className="ml-auto cursor-pointer p-1 hover:bg-[#2b2c37] rounded-full"><FaXmark /></span></div>))}</div></div>);
};
项组件

该组件表示每个用户,并具有添加和从已分配列表中删除用户的功能。

const Item = ({ user }) => {const { assignedList, setAssignedList } = useContext(UserAssignContext);function handleAssign(user) {setAssignedList((prevList) => {// 检查用户是否已存在于列表中if (prevList.includes(user)) {// 如果用户存在,则从列表中移除它const updatedList = prevList.filter((item) => item !== user);return updatedList;} else {// 如果用户不存在,则将其添加到列表中return [...prevList, user];}});}return (<likey={user.id}className={`flex items-center gap-2 p-4 hover:bg-[#2b2c37] rounded transition-all duration-200 `}onClick={() => handleAssign(user)}>{assignedList.includes(user) && <FiCheck />}<img className="w-6 h-6 " src={user.imgUrl} alt={`${user.name} image`} /><span>{user.name}</span></li>);
};
按钮组件

该组件控制显示List组件(浮动下拉列表)。

const Button = () => {const { setIsDropdownOpen } = useContext(UserAssignContext);return (<buttonclassName="  px-4 py-2 flex items-center justify-between w-full rounded border border-[#828FA340] hover:border-primary cursor-pointer relative "onClick={() => setIsDropdownOpen(true)}><span className="block"><FiChevronDown color="#635FC7" size={24} /></span><UserAssignDropdown.List /></button>);
};

要将这些组件组合成一个单一的复合组件,你需要将每个组件分配给父组件,如下所示:

UserAssignDropdown.List = ListContainer;
UserAssignDropdown.Item = Item;
UserAssignDropdown.Header = Header;
UserAssignDropdown.Button = Button;
UserAssignDropdown.AssignedList = AssignedList;
UserAssignDropdown.Close = Close;

接下来,在你的App组件中作为包装组件导入你的复合组件,并传入适当的状态。

export default function App() {const [assignedList, setAssignedList] = useState([]);return (<div className="bg-[#2b2c37] h-[100dvh] text-white flex  p-20 gap-4 items-center flex-col"><div className=" w-[400px] "><h1 className="text-2xl ">复合组件模式</h1><UserAssignDropdownassignedList={assignedList}setAssignedList={setAssignedList}users={usersArray}></UserAssignDropdown></div></div>);
}

然后在包装器中呈现适当的子组件。

export default function App() {const [assignedList, setAssignedList] = useState([]);return (<div className="bg-[#2b2c37] h-[100dvh] text-white flex  p-20 gap-4 items-center flex-col"><div className=" w-[400px] "><h1 className="text-2xl ">复合组件模式</h1><UserAssignDropdownassignedList={assignedList}setAssignedList={setAssignedList}users={usersArray}><UserAssignDropdown.Header /><UserAssignDropdown.Button /><UserAssignDropdown.AssignedList /></UserAssignDropdown></div></div>);
}

最后,使用之前创建的自定义钩子在单击组件外部时关闭下拉菜单。

const UserAssignContext = createContext();
const UserAssignDropdown = ({children,assignedList,setAssignedList,users,
}) => {const UserAssignDropdownRef = useRef(null);const [isDropdownOpen, setIsDropdownOpen] = useState(false);useClickOutside(UserAssignDropdownRef, () => {setIsDropdownOpen(false);});return (<UserAssignContext.Providervalue={{assignedList,users,UserAssignDropdownRef,isDropdownOpen,setIsDropdownOpen,setAssignedList,}}><div ref={UserAssignDropdownRef}>{children}</div></UserAssignContext.Provider>);
};

至此,你的组件就完成了相同的功能!

11-replicating-the-same-funtionality-with-the-compound-component-pattern复制相同功能的复合组件模式

但是为什么要停在这里呢?

使用这种模式,更改组件的外观就像更改它们在父组件中呈现顺序一样简单。例如,如果你想要首先显示按钮,你只需在父组件中更改顺序。

<UserAssignDropdownassignedList={assignedList}setAssignedList={setAssignedList}users={usersArray}
><UserAssignDropdown.Button /><UserAssignDropdown.Header /><UserAssignDropdown.AssignedList />
</UserAssignDropdown>

UI会相应地作出反应。

04-order-of-rendering-in-compound-component-changed复合组件中呈现顺序已更改

此组件还灵活到足以通过 props 更改元素的布局。

只需通过父级传递样式 props:

<UserAssignDropdownassignedList={assignedList}setAssignedList={setAssignedList}users={usersArray}
><UserAssignDropdown.Header /><UserAssignDropdown.ButtonlistStyles={"!-left-5 !-translate-x-full bg-[#605e80] text-white border"}/><UserAssignDropdown.AssignedList />
</UserAssignDropdown>

并在子级接收这些 props:

const Button = ({ listStyles }) => {const { setIsDropdownOpen, UserAssignDropdownRef } =useContext(UserAssignContext);return (<buttonclassName="  px-4 py-2 flex items-center justify-between w-full rounded border border-[#828FA340] hover:border-primary cursor-pointer relative "ref={UserAssignDropdownRef}onClick={() => setIsDropdownOpen(true)}><span className="block"><FiChevronDown color="#635FC7" size={24} /></span><UserAssignDropdown.List listStyles={listStyles} /></button>);
};const ListContainer = ({ listStyles }) => {const { users, isDropdownOpen } = useContext(UserAssignContext);return (isDropdownOpen && (<ulclassName={`absolute bottom-full translate-x-9  left-full translate-y-full rounded bg-[#20212c] w-max ${listStyles}`}><UserAssignDropdown.Close /><div className="flex flex-col p-2">{users?.map((user, index) => (<UserAssignDropdown.Item key={index} user={user} />))}</div></ul>));
};

你可以轻松更改组件的外观。

12-Using-props-to-customize-the-compound-component使用 props 自定义复合组件

常规方法与复合组件方法的比较

好的,让我们退后一步,比较一下我们刚刚探讨过的两种方法。

简单性和组织性

  • 常规方法:想象一下就像在一个大碗里一次性烘焙蛋糕一样。使用常规方法,我们可以创建一个负责下拉菜单中所有内容的单个组件 - 按钮、列表和所有配料。就像有一个大型食谱卡片,所有步骤都混在一起。它能完成任务,但有点凌乱,而且很难跟踪,特别是当你试图调整食谱的某一部分时。
  • 复合组件方法:现在想象一下,我们为每个配料都有不同的碗,一个用于面粉,另一个用于糖,依此类推。这就是复合组件模式。下拉菜单的每个部分都有自己的空间来发光。就像组织你的厨房一样 - 每样东西都有它的位置。这使得理解和修改变得更容易。需要更改面粉?你知道该去哪里找。

灵活性和定制性

  • 常规方法:使用我们的单碗方法,对下拉菜单的特定部分进行更改有点像尝试在那个大蛋糕混合物中交换成分。当然,你可以做到,但并不总是容易。想要不同口味的蛋糕?你可能需要深入整个碗找到添加它的地方。
  • 复合组件方法:使用复合组件模式,就像为每种口味都有单独的容器。需要添加巧克力片?只需拿起巧克力容器,撒上即可。每个组件都有它的工作,使得定制变得更简单。想要更改按钮的颜色?没问题,它就在那里的容器里。

重用和维护

  • 常规方法:当你的食谱都混在一个碗里时,很难将其中的一部分重用于另一道菜。而且,随着厨房变得越来越忙,东西很容易变得凌乱,难以跟踪。每当你想要制作新菜品时,你可能会发现自己需要重写食谱。
  • 复合组件方法:使用复合组件模式,就像在你的厨房里有一套可重用的工具一样。需要制作不同种类的蛋糕?只需拿起你需要的工具,开始烘焙。每个组件就像是一个专业的小工具 - 容易重用和维护。而且当你的厨房井然有序时,制作新菜品就轻而易举了。

附加信息

这里是你可能需要的所有资源链接。

  • 起始文件
  • 常规函数模式
  • 复合组件模式

结论

最后,这两种方法都在你的代码中有其用武之地。常规方法就像你可靠的旧搅拌碗 - 可靠而熟悉,但也许并不适合每种食谱。

复合组件模式就像一个组织良好的厨房,一切井然有序,准备就绪。它可能需要一些设置,但从长远来看,它可以让你的生活变得更轻松。所以,根据你要做的事情,选择适合你口味的方法 - 并愉快地编码吧! 🍰🎨

(本文视频讲解:java567.com)

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

骨传导耳机哪个牌子好?5款年度精品骨传导耳机推荐

在骨传导耳机最开始出现的时候&#xff0c;相信很多人都只关心骨传导耳机的外观颜值和特殊的传声方式&#xff0c;但当你真正用过一段时间后&#xff0c;对骨传导耳机有了更加深入的了解后就会关注到骨传导耳机的使用体验、音质表现、蓝牙性能等具体功能&#xff0c;而随着骨传…

上位机图像处理和嵌入式模块部署(树莓派4b的一种固件部署方法)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 如果软件开发好了之后&#xff0c;下面就是实施和部署。对于树莓派4b来说&#xff0c;部署其实就是烧录卡和拷贝文件。之前我们烧录卡&#xff0c;…

RK3568 学习笔记 : u-boot 千兆网络无法 ping 通PC问题的解决

前言 开发板型号&#xff1a; 【正点原子】 的 RK3568 开发板 使用 虚拟机 ubuntu 20.04 收到单独 编译 RK3568 u-boot 【问题】u-boot 千兆网络无法ping 通&#xff1f;Linux 下千兆网络正常&#xff0c;说明&#xff1a;开发板硬件正常 u-boot 下网络如果通了&#xff0c;…

Unity的旋转实现一些方法总结(案例:通过输入,玩家进行旋转移动)

目录 1. Transform.Rotate 方法 使用 2. Transform.rotation 或 Transform.localRotation 属性与四元数 使用方式&#xff1a; 小案例 &#xff1a;目标旋转角度计算&#xff1a;targetRotation&#xff08;Quaternion类型&#xff09; 玩家发现敌人位置&#xff0c;玩家…

【数据结构】AVL树(万字超详细 附动图)

一、前言 二、AVL树的性质 三、AVL树节点的定义 四、AVL树的插入 五、AVL树的平衡调整 六、AVL树的验证 6.1 验证有序 6.2 验证平衡 七、AVL树的删除 八、AVL树的性能和代码 一、前言 还没有学习过二叉搜索树的同学可以移步 【数据结构】二叉搜索树-CSDN博客https:/…

【C++】:构造函数和析构函数

目录 前言一&#xff0c;构造函数**1.1 什么是构造函数****1.2 构造函数的特性**1.3 总结 二&#xff0c;析构函数**2.1 什么是析构函数****2.2 析构函数的特性****2.3 总结** 前言 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并…

WebGL绘制和变换三角形

1、绘制多个点 构建三维模型的基本单位是三角形。不管三维模型的形状多么复杂&#xff0c;其基本组成部分都是三角形&#xff0c;只不过复杂的模型由更多的三角形构成而已。 gl.vertexAttrib3f()一次只能向顶点着色器传入一个顶点&#xff0c;而绘制三角形、矩形和立方体等&am…

mysql内存优化

临时更改 查看缓冲池大小 show variables like innodb_buffer_pool_size%;通过sql修改&#xff0c;重启后会失效 SET GLOBAL innodb_buffer_pool_size 4294967296;字节转换网站 永久更改 通过my.cnf配置修改&#xff0c;永久生效 进入mysql容器&#xff0c;vi /etc/my.cnf…

良品生活(C端产品设计)

一、产品定义 用户 人群&#xff1a;有某种兴趣的人群&#xff08;喜欢无印良品的商品&#xff09;。 需求&#xff1a;对某种兴趣有内容消费需求&#xff0c;同时也有与别人分享内容的兴趣。 角色&#xff1a;普通用户&#xff0c;内容创作者。 公司 诉求&#xff1a;通…

绿联 安装transmission

绿联 安装transmission及中文UI 1、镜像 linuxserver/transmission:latest 2、安装 2.1、创建容器 按需配置权重。 2.2、基础设置 2.3、网络 桥接即可。 注&#xff1a;如果使用IPV6&#xff0c;请选择"host"模式。 注&#xff1a;如果使用IPV6&#xff0c;请选…

武汉大学博士,华为上班5年多,月薪多少。。。

最近&#xff0c;一位来自武汉大学的博士研究生透露了自己在华为公司工作五年后的薪酬情况。 据他透露&#xff0c;他在2018年加入华为时的月薪为2.4万&#xff0c;随着时间的推移&#xff0c;到了2023年&#xff0c;他的月薪已经增长至4.4万&#xff01;此外&#xff0c;他还透…

某翻译平台翻译接口逆向之加解密参数刨析

上文链接 某翻译平台翻译接口逆向之webpack学习 分析参数 加密参数&#xff1a; ${t} function S(e, t) {return _(client${u}&mysticTime${e}&product${d}&key${t}) } function k(e, t) {const n (new Date).getTime();return {sign: S(n, e),client: u,produc…

vue实现水平排列且水平居中

样式实现 .body{text-align: center; } .body_content{display: inline-block; } .body_content_cardList{display: flex;flex-wrap: wrap;text-align: center; }<div class"body"><div class"body_content"><div class"body_content…

一模块多功能:钡铼IOy系列模块将开关输出输入与模拟量测量相结合

钡铼IOy系列模块是一款具有多功能特性的智能设备&#xff0c;它将开关输出输入与模拟量测量相结合&#xff0c;为工业自动化领域带来了全新的解决方案。这一系列模块的设计理念在于提供更为灵活和全面的监控与控制功能&#xff0c;以满足工业生产中的多样化需求&#xff0c;从而…

SpringBoot 根据不同环境切换不同文件路径

最简单的办法就是使用多个 application.yml 配置文件 。一个叫 application-test.yml 测试用&#xff1b;另一个是正式使用的 application-prod.yml 。win环境下大部分是开发测试时候使用的&#xff0c;服务正式上线需要部署在Linux服务器上又换成了Linux。但开发初期或者项目…

CANN 开发工具介绍

1、ATC工具 ATC&#xff08;Ascend Tensor Compiler&#xff09;是异构计 算架构CANN体系下的模型转换工具&#xff0c; 它可 以将开源框架的网络模型以及Ascend IR定义 的单算子描述文件&#xff08;json格式&#xff09;转换为昇腾 AI处理器支持的.om格式离线模型。 2、精度…

jdbc操作数据库 and 一个商品管理页面

文章目录 1. 介绍1.1 应用知识介绍1.2 项目介绍 2. 文件目录2.1 目录2.2 介绍以下&#xff08;从上到下&#xff09; 3. 相关代码3.1 DBConnection.java3.2 MysqlUtil.java3.3 AddServlet.java3.4 CommodityServlet.java3.5 DelectServlet.java3.6 SelectByIdServlet.java3.7 S…

解线性方程组——(Jacobi)雅克比迭代法 | 北太天元

一、Jacobi迭代法 n 3 n3 n3 , 阶数为 3 时 A ( a 11 a 12 a 13 a 21 a 22 a 23 a 31 a 32 a 33 ) , b ( b 1 b 2 b 3 ) , A\begin{pmatrix} a_{11} & a_{12} &a_{13}\\ a_{21} & a_{22} &a_{23}\\ a_{31} & a_{32} &a_{33}\\ \end{pmatrix} ,\qua…

广东海洋大学成功部署(泰迪智能科技)大数据人工智能实验室建设

广东海洋大学简称广东海大&#xff0c;坐落于广东省湛江市&#xff0c;是国家海洋局与广东省人民政府共建的省属重点建设大学、广东省高水平大学重点学科建设高校、粤港澳高校联盟成员 &#xff0c;入选卓越农林人才教育培养计划&#xff0c;是教育部本科教学水平评估优秀院校。…