0%

[Electron]vanilla js套件系列-listjs

前提情要

筆者與Electron淵源非常深,有一次筆者在上工之前的空檔,有認識的人介紹了一個硬體介接的軟體專案,要在樹梅派上面執行,當時筆者心目中有兩個選擇,一個是Python,一個是Electron,不過Python則需要再找一些UI framework來實作畫面部份,那時候對於Electron也是一份好奇,用html css就能調出畫面,還可以直接套用bootstrap,簡直完美,毅然決然決定使用Electron來開發,但開發過程有很多地方,尤其是硬體介接的部份,卡了很久,眼看上線時間快到,最終放棄作罷,最後使用Python+Tkinter完成該專案,實為可惜。

這次有專案要實作Streaming的小專案,筆者又燃起Electron魂,想到html5的media相關API非常成熟,直接實作了,但第一版有使用jquery刻一些互動效果,要開發進階功能實遇到太多引用問題了,換回最原始使用Vanilla js的方式撰寫,其中學會技巧就是要找到純js的套件時需要下關鍵字Vanilla,才會找到比較符合期待的套件,該篇主題為實作table搜尋pagination時找到的套件介紹。

內容

筆者盡量模擬Electron開發環境,大概就是不要引用jquery相關套件,連bootstrap部份也只引入css部份而已,再則盡量使用script src宣告的方式引入js相關套件,筆者針對此篇的需求,使用的是list.js,跟著筆者實作吧。

Public API

筆者為示範,必須得找到一個公開的API,筆者撰寫的electron專案使用情境是會有一個Sqlite檔案資料庫,使用knex套件存取,筆者會有另一篇介紹knex套件的文章,此篇就以存取公開API的結果來呈現其table的結構。

筆者之前在寫vue系列實就找到過一個public api,繼續沿用下去了,Posts API,另,筆者者邊會使用axios套件實作http request

實際撰寫的程式碼如下

1
2
3
4
5
6
7
8
9
10
11
12
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.24.0/axios.min.js"></script>
<script>
window.addEventListener("DOMContentLoaded", (event) => {
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then((res) => {
// 到時寫處理邏輯在這
console.log(res.data);
})
.catch((err) => console.log("Error: ", err));
});
</script>

可以看到印出的結果,欄位分別為

  • id
  • title
  • body
  • userId

存取API部份就先寫到這邊,接下來介紹Html結構及listjs的宣告方式。

List.js宣告

筆者這邊套用官方文件教學中的NewList這個章節的應用,意思就是html結構中的table是空的,全部資料由外部注入,照著刻應該沒有甚麼問題,上章節已經知道欄位了,就照著欄位在Listjs的初始化options中宣告

1
2
3
4
5
6
7
8
9
var options = {
valueNames: [ 'id', 'title', 'body', 'userId' ],
// listjs塞入資料實的結構,筆者這邊使用table結構,因此宣告成tr>td結構
item: '<tr><td class="id"></td><td class="title"></td><td class="body"></td><td class="userId"></td></tr>',
page: 10,
pagination: true
};
var values = res.data;
var postList = new List('table-list', options, values);

上述程式碼對應的html結構為

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!--listjs對應的tag-->
<div id="table-list">
<div class="col-3 mb-3 mt-3">
<!--只要宣告input並且class設定為search即可擁有listjs的搜尋功能-->
<input class="search form-control" placeholder="Search" />
</div>
<ul class="pagination"></ul>
<table class="table table-bordered table-hover">
<thead>
<tr>
<td>Id</td>
<td>抬頭</td>
<td>內文</td>
<td>使用者</td>
</th>
</thead>
<!--listjs預設抓class名稱為list的區塊當作資料塞入的識別-->
<tbody class="list">

</tbody>
</table>
</div>

Pagination及美化版面

Pagination部份滿簡單的,主要在options中設定

1
2
page: 10,// 一頁幾筆資料設定值
pagination: true // 預設為false

但是預設效果滿醜的,需要修改它,筆者也不是甚麼專業的UI/UX,想要直接套用bootstrap pagination的效果,但是listjs沒有開放設定pagination中的每一個item套用的自定義class,不過它的套用tag是固定的,最外層的class預設是pagination,但可以透過options設定可以更改,但內層的是不能變更

1
2
3
4
5
6
<ul class="pagination">
<!--依照是否該頁碼與當頁頁碼相符而自動套上active-->
<li class="active">
<a class="page"></a>
</li>
</ul>

要直接抄bootstrap pagination是無法靠靜態檔案的,因為bootstrap最新的都是scss版本了,需要執行中的頁面才可以看出完整的css設定,筆者透過bootstrap pagination,參考了一下其結構後宣告為

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<style type="text/css">
.pagination{
display: flex;
padding-left: 0;
list-style: none;
}
li.active .page {
z-index: 3;
color: #fff;
background-color: #0d6efd;
border-color: #0d6efd;
}
li .page {
padding: 0.375rem 0.75rem;
position: relative;
display: block;
color: #0d6efd;
text-decoration: none;
background-color: #fff;
border: 1px solid #dee2e6;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
</style>

完整程式碼

最後看一下組合之後的完整程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
crossorigin="anonymous"
/>
<title>Demo Listjs</title>
<style type="text/css">
.pagination{
display: flex;
padding-left: 0;
list-style: none;
}
li.active .page {
z-index: 3;
color: #fff;
background-color: #0d6efd;
border-color: #0d6efd;
}
li .page {
padding: 0.375rem 0.75rem;
position: relative;
display: block;
color: #0d6efd;
text-decoration: none;
background-color: #fff;
border: 1px solid #dee2e6;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
}
</style>
</head>
<body class="container">
<div id="table-list">
<div class="col-3 mb-3 mt-3">
<input class="search form-control" placeholder="Search" />
</div>
<ul class="pagination"></ul>
<table class="table table-bordered table-hover">
<thead>
<tr>
<td>Id</td>
<td>抬頭</td>
<td>內文</td>
<td>使用者</td>
</th>
</thead>
<tbody class="list">

</tbody>
</table>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.24.0/axios.min.js"></script>
<script>
window.addEventListener("DOMContentLoaded", (event) => {
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then((res) => {
var options = {
valueNames: [ 'id', 'title', 'body', 'userId' ],
item: '<tr><td class="id"></td><td class="title"></td><td class="body"></td><td class="userId"></td></tr>',
page: 10,
pagination: true
};
var values = res.data;
var postList = new List('table-list', options, values);
// console.log(res.data);
})
.catch((err) => console.log("Error: ", err));
});
</script>
</body>
</html>

實際效果

做到這邊,告一段落了,完美的只使用Vanilla js就能做到tablesearch, pagination,太棒了

結論

筆者在Electron專案套用也是順利地套上去了,由於專案內容不能貼出,只能用html靜態檔案的方式做demo,希望有幫助到跟筆者有一樣需求的人。

參考