您的位置:首页 > 财经 > 产业 > android项目开发_微信开发者工具简介_企业培训考试平台官网_关键词优化的最佳方法

android项目开发_微信开发者工具简介_企业培训考试平台官网_关键词优化的最佳方法

2024/11/18 7:27:40 来源:https://blog.csdn.net/qq_53123067/article/details/140903455  浏览:    关键词:android项目开发_微信开发者工具简介_企业培训考试平台官网_关键词优化的最佳方法
android项目开发_微信开发者工具简介_企业培训考试平台官网_关键词优化的最佳方法

Electron是一个开源的桌面应用程序开发框架,它允许开发者使用Web技术(如 HTML、CSS 和 JavaScript)构建跨平台的桌面应用程序,它的出现极大地简化了桌面应用程序的开发流程,让更多的开发者能够利用已有的 Web 开发技能来构建功能强大且跨平台的应用程序,这对于提升开发效率和应用程序的快速交付具有重要意义。

初始化项目

安装框架:今天博主这里用到electron-vite构建器开发桌面端应用,对项目进行一个初始化,这里我们用到该构建器中的react框架开始今天项目的书写,如果想了解vue框架搭建的项目,参考我之前的文章:地址 ,废话不多说直接开始我们今天的项目讲解:

终端执行如下命令安装electron项目:

npm create @quick-start/electron@latest

这里输入完项目的名称之后,选择今天要讲解的react模板即可:

根据需求选择是否使用TS,博主写项目一般都选择TS,这里也就选择TS吧:

是否添加electron更新的插件,当然必须选上: 

是否下载electron的镜像代理,这里也选上吧:

配置完成之后,切换到对应项目目录,终端执行 npm i 安装好依赖,终端执行 npm run dev,可以看到我们的项目已经跑起来了,初识页面看着也是非常的简约大气,项目也是给我们默认配置好了相关的插件便于代码的书写:

配置UI框架:因为这里我们使用了react框架搭建项目,所以这里的UI组件库的话还是采用常用的antd进行样式的搭建吧,终端执行如下命令进行安装:

npm install antd --save

然后随便引入一个按钮,可以看到我们的组件库已经引入成功了:

配置styled-components:因为这里我们使用了react框架来编写electron项目,所以这里我们使用了styled-components样式库来编写内容样式,详情请参考我之前的文章:地址  。

安装图标库:这里我们使用一个大家场景的图标库Font Awesome,该图标库内容还是比较丰富全面的,并且支持vue和react框架其地址为:地址 ,因为本项目采用react框架,所以这里就以react安装为例吧,终端执行如下命令进行安装:

# 以下三个库都需要进行安装
npm i --save @fortawesome/fontawesome-svg-core # 图标库核心文件
npm i --save @fortawesome/react-fontawesome@latest # react风格图标
npm i --save @fortawesome/free-solid-svg-icons # solid类型的字体库

安装完图标库之后,直接在相应的文件中引入对应的图标即可,示例代码如下:

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTimes, faSearch } from '@fortawesome/free-solid-svg-icons'// 引入对应图标
<FontAwesomeIcon icon={faSearch} /> // 搜索图标
<FontAwesomeIcon icon={faTimes} /> // 关闭图标

左侧菜单栏

在项目初始化完毕 之后,接下来我们开始我们开始对页面开始编写相应的内容了,为了固定我们的界面大小,这里我们先在主进程中把界面的大小固定住,禁止用户缩放,如下:

然后我们在根组件App.tsx中编写相应的内容模块,这里我们分两部分,左侧是菜单栏,右侧是展示的内容区域,这里我们借助样式组件styled-components开始相应的样式,当然这里我们也写了一下全局样式,清除一下框架默认的样式,代码如下(条理清晰,一目了然):

import styled, { createGlobalStyle } from "styled-components";
// 导入公共组件
import SearchFile from "./components/SearchFile";const App = () => {return (<><GlobalStyle /><Container><LeftDiv><SearchFile title={'我的文档'} onSearch={(value: string)=> {console.log(value)}}></SearchFile></LeftDiv><RightDiv>右侧</RightDiv></Container></>);
}export default App;
// 设置全局样式
const GlobalStyle = createGlobalStyle`body {margin: 0;padding: 0;font-family: sans-serif;}
`
// 样式组件
const Container = styled.div` // 初始容器width: 100%;height: 100vh;display: flex;
`;
const LeftDiv = styled.div` // 左边容器width: 30%;height: 100%;background-color: #008c8c;
`
const RightDiv = styled.div` // 右边容器width: 70%;height: 100%;background-color: #fff;
`

接下来我们开始编写引入的公共组件SearchFile中的内容,这里我们编写了一个逻辑,默认是文字内容,然后用户点击我们设置的搜索的图标样式之后,则变成输入框,用户可以通过回车传递输入的数据给父组件,然后点击esc退出输入框的模式,具体代码如下所示:

import { useState, useEffect, useRef } from 'react'
import styled from 'styled-components'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTimes, faSearch } from '@fortawesome/free-solid-svg-icons'const SearchFile = ({ title, onSearch }: { title: string; onSearch: (value: string) => void }) => {const [ searchActive, setSearchActive ] = useState<boolean>(false)const [ value, setValue ] = useState<string>('')// 获取输入框实例const inputRef = useRef<HTMLInputElement>(null)// 关闭搜索框const closeSearch = () => {setSearchActive(false)setValue('')}// 监听键盘事件useEffect(() => {const ListenKeyWord = (e: any) => {const { keyCode } = eif ( keyCode === 13 && searchActive ) {onSearch(value)}if ( keyCode === 27 && searchActive ) {closeSearch()}}document.addEventListener('keyup', ListenKeyWord)// 组件加载时获取焦点return () => { // 组件卸载时移除监听事件document.removeEventListener('keyup', ListenKeyWord)}}, [searchActive, value, onSearch])// 实现输入框聚焦useEffect(() => {if (searchActive && inputRef.current) {inputRef.current.focus()}}, [searchActive])return (<>{/* 默认文字显示 */}{ !searchActive && (<SearchDiv><Span>{ title }</Span><Span onClick={()=> { setSearchActive(true) }}><FontAwesomeIcon icon={faSearch} /></Span></SearchDiv>)}{/* 点击文字则显示搜索框 */}{ searchActive && (<SearchDiv><Input value={value} ref={inputRef} onChange={(e)=> {setValue(e.target.value)}} /><Span onClick={closeSearch}><FontAwesomeIcon icon={faTimes} /></Span></SearchDiv>)}</>)
}export default SearchFile
// 样式组件
const SearchDiv = styled.div`display: flex;align-items: center;justify-content: space-between;border-bottom: 1px solid #fff;
`
const Span = styled.span`color: #fff;padding: 5px 15px;font: normal 16px/40px '微软雅黑';cursor: pointer;user-select: none;
`
const Input = styled.input.attrs({type: 'text',placeholder: '搜索文件'
})`width: 100%;height: 25px;border: none;outline: none;border-radius: 1px;margin-left: 10px;
`

最终呈现的效果如下所示:

接下来开始对左侧的文件菜单栏样式做一个调整,这里我们将其也抽离出一个公共组件,因为文件名称也是要进行输入框来修改,也是要借助监听键盘事件,这里我们将其抽离出一个hooks函数:

// 自定义监听键盘事件hook函数
import { useState, useEffect } from 'react';export const useKeyHandler = (code: number) => {const [ keyPressed, setKeyPressed ] = useState<boolean>(false);const keyDownHandler = (e: any) => { if (e.keyCode == code) setKeyPressed(true) }; // 按下键盘const keyUpHandler = (e: any) => { if (e.keyCode == code) setKeyPressed(false) } // 抬起键盘useEffect(() => {document.addEventListener('keydown', keyDownHandler);document.addEventListener('keyup', keyUpHandler);return () => {document.removeEventListener('keydown', keyDownHandler);document.removeEventListener('keyup', keyUpHandler);}});return keyPressed;
}

然后接下来我们开始创建文件列表菜单名称,这里我们在根组件中把数据通过props传递给文件列表组件,组件拿到数据后,根据情况进行渲染:

组件拿到数据之后开始对页面进行一个渲染,这里就不再一一赘述了,都是正常的vue代码:

最终得到的效果如下所示:

然后如法炮制,在左侧的底部下面再放置两个按钮,新建和导入,如下:

import styled from 'styled-components'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'interface ButtonItemProps {title: string,btnClick?: () => void,icon: any
}const ButtonItem = ({ title, btnClick, icon }: ButtonItemProps) => {return (<BtnDiv><FontAwesomeIcon style={{ marginRight: '10px' }} icon={icon} />{ title }</BtnDiv>)
}export default ButtonItem
// 样式组件
const BtnDiv = styled.div`width: 100%;display: flex;align-items: center;justify-content: center;height: 40px;cursor: pointer;font-size: 18px;user-select: none;&:hover {background-color: #15ad7a;border-radius: 5px 5px 5px 5px;}&:active {background-color: #00fc17;}
`

最终呈现的效果如下所示:

右侧主内容

接下来开始编写右侧内容区域,首先我们先完成顶部tab标签页的静态内容,这里我们在App根组件中设置TabList组件,然后传入相关数据,以及激活标签页,未保存、点击和关闭回调:

然后开始搭建静态页面,如下所示:

import styled from 'styled-components'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTimes, faCircle } from '@fortawesome/free-solid-svg-icons'interface TabListProps {files: any[]activeItem: stringunSaveItems: any[]clickItem: (id: string) => voidcloseItem: (id: string) => void
}const TabList = ({ files, activeItem, unSaveItems, clickItem, closeItem }: TabListProps) => {return (<TabDiv>{ files.map(item => {let isUnSave = unSaveItems.includes(item.id)return (<TabItem $isActive={activeItem === item.id}key={item.id} onClick={(e: any) => { e.preventDefault(); clickItem(item.id) }}><TabItemName>{ item.title }</TabItemName><TabItemIcon onClick={(e: any) => { e.stopPropagation(); closeItem(item.id) }}><FontAwesomeIcon className='close' icon={faTimes} /></TabItemIcon>{ isUnSave && (<FontAwesomeIcon className='circle' icon={faCircle} />) }</TabItem>)}) }</TabDiv>)
}

最终呈现的效果如下所示:

接下来开始编写右侧主内容中下侧的编辑器内容,这里我们借助一个开源的简易的react编辑器插件,其官方网址为:地址 ,如下所示:

终端执行如下命令进行安装:

npm install --save react-simplemde-editor easymde

安装完成之后,通过一段简单的示例代码进行演示:

import SimpleMDE from "react-simplemde-editor";
import "easymde/dist/easymde.min.css";<SimpleMDEvalue={initFiles[1].body}onChange={(value: string) => console.log("编辑", value)}options={{autofocus: true, // 自动获得焦点spellChecker: false, // 拼写检查status: true, // 状态栏minHeight: "470px", // 最小高度}}
/>

最终呈现的效果如下所示,可以看到我们的编辑器已经被成功渲染出来了:

这里我们默认都是把上方的tab标签页都给写死了,这里我们先把写死的内容参数去掉,判断如果用户没有点击文件的话,默认右侧的内容区域是不显示内容的,这里我们给一个提示,根据是否有激活的tabid来判断:

const [files, setFiles] = useState<filesTypes[]>(initFiles); // 文件列表
const [activeId, setActiveId] = useState<string>(""); // 当前激活的tab
const [openIds, setOpenIds] = useState<string[]>([]); // 打开的tab
const [unSaveIds, setUnSaveIds] = useState<string[]>([]); // 未保存的tab// 计算已打开的所有文件信息
const getOpenFiles = openIds.map((id) => {return files.find((file) => file.id === id);
});// 计算正在编辑的文件信息
const activeFile = files.find((file) => file.id === activeId);

这里根据判断参数渲染内容:

{ activeFile ? (<><TabList files={getOpenFiles}   activeItem={activeId} unSaveItems={unSaveIds} clickItem={(id: string)=>{ console.log("点击", id)}}closeItem={(id: string)=>{ console.log("关闭", id)}}/><SimpleMDEvalue={activeFile.body}onChange={(value: string) => console.log("编辑", value)}options={{autofocus: true, // 自动获得焦点spellChecker: false, // 拼写检查status: true, // 状态栏minHeight: "470px", // 最小高度}}/></>
) : (<AdvertisementDiv><AdvertisementImgs src={img} title="csdn博主 '亦世凡华、'" onClick={()=> {window.open("https://blog.csdn.net/qq_53123067?spm=1000.2115.3001.5343")}} /><AdvertisementTitle>当前暂无数据<br/>(PS: 点击上方图片,求一波关注)</AdvertisementTitle></AdvertisementDiv>
) }

最终呈现的效果如下所示:

菜单栏操作

接下来对左侧菜单栏中的按钮进行一个交互操作了,主要分为以下几个方向:

搜索文件:点击搜索图标,在输入框输入相关内容,搜索栏下方的文件列表依据关键字进行呈现,这里我们再呈现设置一下左侧菜单栏的显示内容,如果有搜索出内容就显示搜索的内容,否则默认显示files,代码如下:

const [searchFiles, setSearchFiles] = useState<filesTypes[]>(); // 左侧展示搜索列表于默认列表进行区分
// 计算左侧列表需要展示什么样信息
const fileList = (searchFiles && searchFiles.length > 0) ? searchFiles : files;
// 依据关键字搜索文件
const searchFile = (keyword: string) => {const newFiles = files.filter(item => item.title.includes(keyword));setSearchFiles(newFiles);
}

tab标签页:接下来我们设置当点击左侧菜单栏中的文件,则打开右侧的tab标签页面,然后当点击tab标签页的时候,切换激活状态,以及点击标签页中的关闭图标进行一个关闭操作:

// 依据关键字搜索文件
const searchFile = (keyword: string) => {const newFiles = files.filter(item => item.title.includes(keyword));setSearchFiles(newFiles);
}
// 点击左侧文件显示编辑页面
const openItem = (id: string) => {setActiveId(id); // 激活tab// 判断是否已经打开if (!openIds.includes(id)) {setOpenIds([...openIds, id]);}
};
// 点击某个tab选项时切换当前状态
const changeActive = (id: string) => setActiveId(id)
// 关闭某个tab
const closeFile = (id: string) => {const retOpens = openIds.filter((item) => item !== id); // 过滤掉该tabsetOpenIds(retOpens); // 过滤掉该tabif (retOpens.length > 0) {setActiveId(retOpens[0]); // 激活第一个tab} else {setActiveId(""); // 如果没有tab了,则清空激活状态}
};

文件内容更新:然后这里当我们对文件里面的body内容进行修改的时候,tab标签页是呈现修改的圆点状态,然后把修改的内容重新添加到当前修改的文件的body中:

// 文件内容更新
const changeFile = (id: string, value: string) => {if (!unSaveIds.includes(id)) {setUnSaveIds([...unSaveIds, id]); // 添加未保存的tab}// 某个内容更新后,更新文件列表const newFiles = files.map((file) => {if (id === file.id) {return {...file, body: value}; // 更新文件内容} else {return file;}});setFiles(newFiles); // 更新文件列表
};

删除文件:删除文件很简单,直接拿到当前要删除的文件id进行一个过滤,然后顺便关闭可能正在打开的tab标签内容即可:

// 删除某个文件项
const deleteItem = (id: string) => {const newFiles = files.filter(item => item.id !== id);setFiles(newFiles);// 删除后,关闭可能正在打开的tabcloseFile(id);
}

重命名文件:重命名文件的话,直接把输入框中输入的内容拿过来,然后计算当前要修改的文件把里面的名称title进行一个替换即可:

// 重命名文件名称
const renameFile = (id: string, newTitle: string) => {const newFiles = files.map((file) => {if (id === file.id) {return {...file, title: newTitle}; // 更新文件内容} else {return file;}});setFiles(newFiles); // 更新文件列表
}

新建文件:新建文件的话需要对每个文件生成特定的id,所以这里我们使用uuid进行生成唯一标识,终端执行如下命令进行安装:

npm install uuid
// 新建文件
const createNewFile = () => {const newId = uuidv4();const newFile: any = {id: newId,title: "",body: "## 初始化内容",createTime: new Date().getTime(),isNew: true}// 避免连续点击新建if (!files.find((file) => file?.isNew)) {setFiles([...files, newFile]);}
}

最终呈现的效果如下所示:

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com