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的朋友;
📝 正在開發的功能
- 👉自定義上傳背景圖片
- 👉自定義背景動畫效果
- 👉自定義工具欄
- 👉導入解析瀏覽器書籤,支持修改、刪除並存入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)
})
})
}
📖📖📖其他的好像都挺簡單的,哈哈哈 ,目前也還在學習Vue3.0,經常看到很多大佬的文章,比如 若川,楊俊寧,chokcoco 等大佬,繼續向他們學習,加油,做一個終身學習者。
需要什麼新的需求或者設計,可以給我提issue,感謝,喜歡的也可以點個贊。
💯 致謝
第一次做一個開源的東西,只想把這個小項目做好,感謝 【空白i】 的打賞 【66.6】,太激動啦;繼續加油,希望可以做出更多更精緻開源的作品處理。繼續加油。😀 😀 😀