Part1用Vue3.0 开发一款导入浏览器书签的在线书签
介绍(取名)
【红隼书签】是一款简洁的在线书签导航网站。 名字的由来其实是,本着爱护动物,爱护动物的初心,想到起一个鸟类的名称,其实最开始想了很多名字,小詹书签,麻雀书签等。
然而听起来都不够嘹亮。起初想了一个食肉的,有点厉害的又有点呆萌的鸟类的名字,红隼【英文翻译:kestrel】,点个赞。于是就有了这个名字啦,然而听起来也是不错的。于是开发计划开始啦。
数据起源(印象中文)
他的默认数据为我选的是印象中文的web导航数据;其实我本人哪里珍藏了更多的导航数据,然而很多设计到公司的一些拜访网站。想想还是算了,于是就用了印象中文的数据。它能够批改数据;全局搜寻筛选性能;单页面实现逻辑非常简单,老手小白也能实现二次批改开发;采纳granim插件实现背景动画;可抉择更多动画成果;炫酷光晕背景动画成果。
性能/特色
(炫酷光晕背景动画成果,可导入浏览器数据存入LeanCloud)
- ✅ 1.同步印象中文的web导航数据;书签反对新增、批改和删除
- ✅ 2.全局搜寻筛选性能;本地离线数据长久化,书签增删改查
- ✅ 3.可登录获取保留在leancloud外面的书签数据,再不必放心书签数据失落了
- ✅ 4.采纳granim插件实现背景动画;可抉择更多动画成果;
- ✅ 5.反对导入浏览器书签数据(Google,火狐),并存入LeanCloud;
- ✅ 6.可注册leanCloud并批改appId和appKey;本人部署该书签;
- ✅ 7.采纳Vue3.0 Composition API;也是一个学习Vue3.0 的学习我的项目;心愿帮忙更多正在学习VUe 3.0的敌人;
- ✅ 8.自定义上传背景图片
- ✅ 9.自定义背景动画成果
- ✅ 10.导入解析浏览器书签,反对批改、删除并存入LeanCloud
正在开发的性能
- 自定义工具栏
- 书签反对多种布局款式(卡片,列表,树形书签构造等)
- 反对批改整个书签的图标;目前应用的是红点图标,也挺难看的;
- 自定义配色计划
- 减少中国风和热门游戏配色成果
- 其余性能
自定义导入数据
能够将浏览器的书签导出,而后导入到书签零碎中。也能够将书签零碎的数据导入到浏览器中。
leancloud存储
数据到云端。只需注册登录即可,后续无需放心数据失落问题。
⚡主题
目前提供 清晰/暗黑两种主题。后续还会减少更多的主题成果。
暗黑
清爽亮堂
网址书签
========⚡⚡⚡ 红隼书签 留神:本我的项目会继续新增性能,但继续保护。如应用中发现问题,请留言或者提交 issue 。谢谢!!!
装置步骤
- 1.克隆我的项目 https://gitee.com/zhanhongzhu/kestrel-bookmark.git
- 2.进入我的项目目录
npm install
- 3.启动我的项目
npm run serve
- 4.关上浏览器即可 localhost:8080 就能够看到界面啦;
- 5.打包命令
npm run build
成果
源码地址
齐全开源,大家能够随便钻研,二次开发。当然还是非常欢送大家点个Star⭐⭐⭐\
源码链接(gitee) 源码链接(github)
我的项目构造
├── src ├── Api // 寄存接口 │ └──common.js // leancloud-storage公共接口函数封装 │ └──user.js // leancloud-storage 登录、登出接口 ├── assets // 寄存动态资源 │ └──Json // 静态数据源json数据 │ └──svg // 工具栏图标 ├── components //寄存组件 │ └──Dialog.vue // 新增、批改书签 │ └──Login.vue // 登录弹窗 ├── APP.vue └── main.js
我的项目图标(后续反对批改图标)
红隼书签应用了的是iconfont图标,设计的小姐姐是是半夏鸭,设计的图标太棒了,在此表示感谢。( ´・・` )
很喜爱这个图标的;
小姐姐的图标作品集地址图标作品集地址
次要性能函数--1、解析浏览器书签为JSON数据
export function walkBookmarksTree(root) { const result = [] // 深度优先遍历 const walk = (node, list) => { const els = node.children if (els && els.length > 0) { for (let i = 0; i < els.length; i++) { const item = els[i] // p标签或h3标签间接跳过 if (item.tagName === 'P' || item.tagName === 'H3') { continue } // 文件夹不必创立元素 if (item.tagName === 'DL') { walk(els[i], list) } else { // DT节点 let child = null // 判断是否是文件夹 const children = item.children let isDir = false for (let j = 0; j < children.length; j++) { if (children[j].tagName === 'H3' || children[j].tagName === 'DL') { isDir = true } } // 文件夹 if (isDir) { child = { type: item.tagName === 'DT' ? item.querySelector('h3') ? item.querySelector('h3').innerText : '' : '', folder: true, children: [] } walk(els[i], child.children) } else { // 书签 const _item = item.querySelector('a') if (_item) { child = { title: _item?.innerText, url: _item?.href } } } child && list.push(child) } } } } walk(root, result) //过滤不为 folder的书签,保障书签可能辨认 const myBookmark = result.filter(v => v.folder) return flagBrowerList(myBookmark)}
2、原生Input文件上传-暗藏input标签,实现点击上传
<i class="el-icon-upload2" title="导入浏览器书签" @click="importBookmark"> <input type="file" ref="filElem" id="file"></i>
// 导入书签const importBookmark = () => { const file = document.getElementById('file') file.dispatchEvent(new MouseEvent('click')) const mybookmark = document.getElementById('mybookmark') document.getElementById('file').addEventListener('change', function () { var file = document.getElementById('file').files[0] var reader = new FileReader() reader.readAsText(file, 'utf-8') reader.onload = function () { mybookmark.innerHTML = reader.result const formDatas = JSON.stringify(walkBookmarksTree(mybookmark)) //此处曾经获取了咱们上传的bookmark.html文件的内容了,并且曾经格式化 }) } else { ElMessage.warning('请先登录') }}
3、接入leanCloud 实现serveless数据存储
其实这部分我曾经进行了简略的函数封装,用起来是很不便的,还有很多用法能够参考leancloud文档,具体用法是十分具体的。
其实应用上面几个封装的函数,根本就能够实现一个零碎的增删改查了,还是十分疾速不便的。数据以JSON数据格式进行存储。
4.1 对象存储公共函数(传入表名和存储的数据)
import AV from 'leancloud-storage'// 对象存储公共函数export const saveObject = (className, params) => { return new Promise((resolve, reject) => { const Todo = AV.Object.extend(className) const user = AV.User.current() var todo = new Todo() todo.set('formDatas', params.formDatas) todo.set('user', user) todo.save().then((res) => { resolve(res) }, (error) => { reject(error) }) })}
4.2 获取对象存储的列表数据(传入表名和条件)
// 获取对象列表export const getObject = (className, params) => { return new Promise((resolve, reject) => { const query = new AV.Query(className) // 查问多个条件 const user = AV.User.current() for (const v in params) { if (params[v]) { query.equalTo(v, params[v]) } } query.equalTo('user', user) query.find().then((res) => { resolve(res) }, (error) => { reject(error) }) })}
4.3 删除对象数据(传入表名和数据ID)
// 删除对象export const deleteObject = (className, id) => { return new Promise((resolve, reject) => { const todo = AV.Object.createWithoutData(className, id) todo.destroy().then((res) => { resolve(res) }, (error) => { reject(error) }) })}
4.4 更新对象数据(传入表名和存的数据+ID)
// 更新对象export const updateObject = (className, params) => { return new Promise((resolve, reject) => { const todo = AV.Object.createWithoutData(className, params.id) for (var i in params) { todo.set(i, params[i]) } todo.save().then((res) => { resolve(res) }, (error) => { reject(error) }) })}
issue
须要什么新的需要或者设计,能够给我提issue,感激,喜爱的也能够点个赞。
致谢
感激 【空白i】 的打赏 【66.6】持续加油,心愿能够做出更多更粗劣开源的作品解决。持续加油。
其余链接
- 我的博客(收集各类大神的学习笔记及官网文档,强烈推荐)
- 红隼书签
- 掘金
- 思否
- CSDN
- 简书
- 语雀(超过1800多篇开发文档)