起因
前天日常刷酷安的时候看到了一个酷安UWP版的一条动态,作为一个菜鸡前端第一时间想到的是我能不能这样做一个PC版本的应用,第一时间想到了了的是用electron来做,在一番搜索过后,发现了electron的原理是内置了Chromium内核,所以裸打包的话就有62.5mb的体积,如何我就想到了Tauri这个框架,前端是通过系统的 WebView2,后端使用 Rust,裸打包很小(4.32MB)。但是本人对Rust一窍不通emm,但是认真想了之后我发现并不需要使用到Tauri中Rust对后端的操作。因此最终选择是Tauri(嘿嘿)!!
🌟Github项目仓库:github.com/ayuan-gy/Co… 求🌟
效果图gif(比较大)
Tauri 是什么?
Tauri 使用 Web 前端构建更小、更快、更安全的桌面应用程序。
酷安是什么
酷安是深圳酷安网络科技有限公司旗下的一个泛科技数码社区,口号是「发现科技新生活」,前身为知名第三方安卓应用市场「酷市场」,拥有海量数码爱好者用户,在国内数码科技圈具备一定影响力。 公司旗下包含手机客户端「酷安」、B 站数码评测账号「酷安数码」、微信公众号「酷安数码」、微信小程序「酷安App」、微博官方账号「酷安网」。
真正的介绍-> 酷基交友社区,
Blued
的竞争对手人称小绿
目录结构
├───node_modules
├───public
├───src //前端相关代码
│ ├───apis
│ ├───assets
│ ├───data
│ ├───pages
│ │ ├───components
│ │ │ ├───article-card
│ │ │ ├───icon-bars
│ │ │ ├───icon-list
│ │ │ └───SwitchRoute
│ │ ├───detail
│ │ │ ├───article-detail
│ │ │ │ └───Comt
│ │ │ │ ├───reply-detail
│ │ │ │ └───time-action
│ │ │ └───person-detail
│ │ └───main
│ │ └───pages
│ │ ├───beautify-page
│ │ ├───fast-news
│ │ ├───head-lines
│ │ ├───hot-list
│ │ ├───tutorial-page
│ │ └───vertical-topic
│ │ └───Comt
│ │ └───topic-list
│ └───utils
└───src-tauri //后端相关代码
代码书写中的一些问题与抉择
技术选型
React + TypeScript(any大法好) + Less
- 选React是因为他的灵活性以及(其实就是想熟练一下)
- TypeScript一开始是想好好写interface的,但是终究还是被我用成了anyscript
- Less嵌套写法(更好做样式隔离)以及配合组件库做自定义主题
- 在深思熟虑(想了一小会)后没有选择全局状态管理
是否使用组件库
一开始的想法是需要纯手写界面,但是在对整个App做了一个总体的统揽之后,感觉内容复杂度并不低,所以最终选择了ArcoDesign,这也大大在后面提高了我的开发效率(偷大懒哈哈哈)。
左侧主页Tab的内容组件动态渲染
本来的想法是定义一个想下面这样的结构来做到一个map
函数可以一次性便捷的渲染首页内容:
通过path
字段和懒加载React.lazy
来匹配对应的组件,然后就有了下面的这一段代码:
const modules = import.meta.glob('./**')
const Component = (props: any) => {
console.log(modules)
const Com = React.lazy(modules[`./pages/${props.path}/index.tsx`] as any)
console.log(Com)
return <Com />
}
通过查阅资料,之前使用的webppack
可以通过require
来动态引入组件,而vite
中提供的是import.meta.glob
函数,参数为/**
代表的是匹配的是目录下及子目录下的所有文件,最终写的能够通过ts
的类型检查,但是在最后发现,并不会渲染对应的目录组件,还会导致Component
组件无限渲染的。在搜索无果后最终选择了最笨的方法,麻了,又是一次无奈的妥协:
Tab
栏下的对应组件我选择了将其分为多个组件进行封装,目录如下:
首页卡片组件的封装
在观察中发现,首页中有多个部分是重叠且相似度极高的页面组件,例如下图:
因此有了组件article-card
和icon-list
,详细实现移步上面GitHub仓库:
图片懒加载
酷安作为一个数码社区平台,出现最多的当然是动态中无处不在的图片,因此图片懒加载是项目中不可缺少的一部分。在掘金、思否等搜索过后,大致的实现思路有几种。
- 首先都要为
img
设置自定义属性,例如data-src
- 然后通过各种方案监听图片是否出现在页面可视区域
viewport
el.offsetTop <= clientHeight + scrollTop + 100
getBoundingClientRect()
IntersectionObserver API
- 最后就是我采用的方案
- 给
img
加上attr
loading="lazy"
浏览器就会自动帮我们实现图片懒加载
页面路由的思考
在我的想法中,我想要的的是在左边页面中,点击动态或者其他模块后,对应的界面都是显示在右边区域中,很容易想象得到的是,右边的模块应该是左边模块的子路由,但是在另外一种情况中,在左边点击后,还会切换左边区域的界面。因此,我想要的的是左边区域与右边区域是两个互不干扰的页面,而非父子路由的嵌套关系,我的做法的使用一个path:"/*"
的路由路径,匹配到我的一个自定义组件中,完全由我来工具path
的变化来决定左右组件的渲染。也就有了我下面的代码:
const MyApp = () => {
return useRoutes([
{
path: '/',
element: <App />,
children: [
{
path: '/*',
element: <SwitchRoute></SwitchRoute>,
},
],
},
])
}
export default MyApp
在SwitchRoute
组件中,使用useEffect
来监听location.pathname
来监听路由的变化并更新左右视图,通过getCom
函数匹配pathname
对应的组件,通过类似下面的代码就能够有区分的渲染左右路由:
const nav = useNavigate()
useEffect(() => {
nav('main-page/person-detail')
}, [])
具体SwitchRoute
组件实现代码如下:
const getCom = (name: string) => {
switch (name) {
case 'article-detail':
return <ArticleDetail></ArticleDetail>
case 'person-detail':
return <PersonDetail></PersonDetail>
case 'main-page':
return <MainPage></MainPage>
}
}
const SwitchRoute = (props: any) => {
const location = useLocation()
const [comName, setComName] = useState<any[]>([])
useEffect(() => {
setComName((names) => {
const name = location.pathname
.split('/')
.filter((_) => _ !== '/')
.filter((_) => _ !== '')
return name
})
}, [location.pathname])
return (
<div className="switch-box">
{getCom(comName[0])}
<div className="switch-right">{getCom(comName[1])}</div>
</div>
)
}
未完待续
如果文章中有什么出现问题的地方,希望能够得到你的指出并加以改进
后面我还会继续更新项目中的一些想法与思考
🌟Github项目仓库:github.com/ayuan-gy/Co… 求🌟