larrykkk / notes Goto Github PK
View Code? Open in Web Editor NEW個人筆記
個人筆記
ex1. 各自改變
handleSearch(keyword){
this.search.keyword = keyword
this.getList()
}
handlePageChange(page){
this.search.page = page
this.getList()
}
handleSizeChange(size){
this.search.size = size
this.search.page = 1
this.getList()
}
handleFilter(filter){
this.search.filter = filter
this.search.page = 1
this.getList()
}
優點:
直覺、好修改
缺點:
重複性高
ex2. 寫函數組裝
getQueryParams({foo, bar}){
const query = {
page: search.page || 1,
size: search.size || 10,
filter: search.filter || {},
...
}
if(foo){
query.filter = [{
foo: (foo + 1) * 2
}]
}
if(bar){
query.filter.bar = {bar}
}
return query
}
handleSearch(keyword){
const query = getQueryParams({ keyword })
this.getList(query)
}
handleFilter(filter){
const query = getQueryParams({ filter })
this.getList(query)
}
優點:
不像 ex1 那樣的重複性高了,且可以很靈活的自己調整資料
缺點:
隨邏輯愈複雜 getQueryParams 會變成越龐大的怪物,修改成本上升
ex3. es6 spread + pure function
getList(params){
this.search = {...this.search, ...params}
// 如果需要轉換資料額外處理
const data = this.convertSearch(this.search) // 這是一個 pure function
axios.post('api', data)
// 如果不需要轉換資料額外處理
axios.post('api', this.search)
}
handleSearch(keyword){
this.getList({ keyword })
}
handlePageChange(page){
this.getList({ page })
}
handleSizeChange(size){
this.getList({ page: 1, size})
}
handleFilter(filter){
this.getList({page: 1, filter})
}
優點:
利用 es6 spread 展開的特性解決 ex1 重複性的問題,
並把資料轉換的函式獨立成 pure function(即在不影響輸入的值情況下,回傳出一個新的值的函式),
如此既可降低重複性 & 複雜度
缺點:
還未在很複雜的情況下使用過,實用度未知
3.nuxt 換頁
https://stackoverflow.com/questions/54531166/vuetify-ssr-pagination
外部網路開啟
https://stackoverflow.com/questions/55236594/nuxtjs-expose-localhost-to-external-doesnt-work
https://zh.nuxtjs.org/faq/host-port/
api 依賴注入 控制反轉
https://codesandbox.io/s/nuxt-axios-api-rsfuf
Authentication
// trust
https://github.com/nuxt/docs/blob/master/zh/examples/auth-external-jwt.md
cookie 增刪查
https://stackoverflow.com/questions/14573223/set-cookie-and-get-cookie-with-javascript
刪除的成功方式
https://stackoverflow.com/questions/5688491/unable-to-delete-cookie-from-javascript
使用 cookie 當作登入機制的 cors 設定
https://yu-jack.github.io/2019/06/02/ajax-with-session/
設定 head
nuxt/nuxt#1086
https://stackoverflow.com/questions/47864147/how-do-i-configure-dynamic-og-tags-in-nuxt-js-vue-js
10.編譯很慢怎辦?
nuxt/nuxt#5131 (comment)
https://imgur.com/xwetpiE
Nuxt Warning
The command 'nuxt build' finished but did not exit after 5s
nuxt/nuxt#5271
do not use created()
pm2 start
pm2 start -i 4 npm --name "nuxt" -- run dev
npm run build
pm2 start -i 4 npm --name "nuxt" -- run start
使用 vue-quill-editor
editorOption 請參考 官網doc
quilljs/quill#1089 (comment)
「前端早读君002」改造vue-quill-editor: 结合element-ui上传图片到服务器
步驟說明:
這一步就是要設定你的編輯器要用什麼
以及最重要的要改寫 image 點擊後的 handlders
...
var toolbarOptions = [
["bold", "italic", "underline", "strike"], // toggled buttons
["blockquote", "code-block"],
["link", "image", "video"],
["clean"] // remove formatting button
];
export default {
name: "quill",
components: {
quillEditor
},
data() {
return {
content: "<p>a</p><p>b</p><p>c</p><p>b</p><p>e</p><p>f</p>",
editorOption: {
modules: {
toolbar: {
container: toolbarOptions, // Selector for toolbar container
handlers: { image: this.selectLocalImage }
}
}
}
};
},
...
selectLocalImage() {
const input = document.createElement("input");
input.setAttribute("type", "file");
input.click();
// Listen upload local image and save to server
input.onchange = () => {
const file = input.files[0];
// file type is only image.
if (/^image\//.test(file.type)) {
this.saveToServer(file);
} else {
console.warn("You could only upload images.");
}
};
},
saveToServer(file) {
console.log(file);
const fd = new FormData();
fd.append("image", file);
const xhr = new XMLHttpRequest();
xhr.open("POST", "http://127.0.0.1:3000/api/image", true);
xhr.onload = () => {
if (xhr.status === 200) {
// this is callback data: url
// const url = JSON.parse(xhr.responseText).data;
this.insertToEditor();
}
};
xhr.send(fd);
},
insertToEditor(url) {
// push image url to rich editor.
const range = this.editor.getSelection();
this.editor.insertEmbed(
range.index,
"image",
"https://img.purch.com/w/660/aHR0cDovL3d3dy5saXZlc2NpZW5jZS5jb20vaW1hZ2VzL2kvMDAwLzEwNC84MTkvb3JpZ2luYWwvY3V0ZS1raXR0ZW4uanBn"
);
}
在談單元測試的時候常常會談到一個關鍵性的名詞: 覆蓋率(coverage),
雖然很多時候覆蓋率並不是一個好的指標來衡量你的測試品質,但在客觀的情況下就是會問你覆蓋率到多少。
所以今天我讓我們來研究一下這個東西吧!
不過在那之前要先講一下怎麼開啟產生覆蓋率報告
以 Vue + Jest 為例
有找到這裡 說明如何開啟
通常是把以下的設定寫進 jest.config.js 或是 package.json (還需要稍作修改) 裡面就可以了
module.exports = {
moduleFileExtensions: ['js', 'json', 'vue'],
transform: {
'^.+\\.js$': 'babel-jest',
'^.+\\.vue$': 'vue-jest'
},
collectCoverage: true,
collectCoverageFrom: ['src/**/*.{js,vue}', '!src/main.js']
}
再跑一次測試就可以了,以使用 @vue/cli-plugin-unit-jest 來安裝的同學為例,只要再次使用 npm run test:unit
就可以等待報告產生了
跑完以後不管是否全部通過還是有部分通過,都會在根目錄下面 coverage
這個資料夾,我們直接進入 coverage/lcov-report 就可以看到報告的 html 檔 index.html
,點兩下打開以後就可以檢視覆蓋率如何
簡單解釋一下各項的意思
首先是左上角的文字跟數字
如果是 Statements 10/10 那就表示在這支檔案中的 Statements 的覆蓋率是百分之百
計算每一個陳述句的覆蓋率,關於 Statement 是甚麼 ?
這裡面的語法都算是 statement
用我自己的理解來解釋的話那就是:
statement 執行一些邏輯,但不會回傳值(value),像下面這種就不是 statement,因為會回傳值
new objectType([param1, param2, ..., paramN]);
你也可以參考這文章
我自己測試的話,會發現很多地方我覺得不是 statements 的地方其實都算是 statement,像是我發現 data
既是 statement 也是 functions 也是 lines (@@?)
data() {
return {
// ...
}
}
每一個 if ... else 或是 switch case 產生的分支,都會被計算是一次
就是計算 JS function,在 vue 中常見的 methods 也屬於 functions
計算每一行的覆蓋
I: 代表 if 語句沒有成立,判斷式內的語句未執行
E: 代表 else 語句沒有成立,判斷式內的語句未執行
行數左邊的 x 數量: 代表那一行執行次數
黃色:代表沒有覆蓋的 Branches
粉紅色:未涵蓋的 Statements
這篇文章的主要想傳達幾個重點
資料來源:
axios/axios#708
axios.get(...)
.then((response) => {
return axios.get(...); // using response.data
})
.then((response) => {
console.log('Response', response);
});
codepen Demo
請看console
PaginationData.vue
<template>
<div>
...
// 不具名插槽
<slot>warn need data</slot>
//具名插槽
<slot name="插槽名稱">warn need data</slot>
...
</div>
</template>
// when you use PaginationData component
<PaginationData>
// #default 是v-slot的縮寫,等同 v-slot:default
// 不具名插槽
<template #default>
// 具名插槽
<template #插槽名稱>
<ul class="photo-list photo-list--name-after">
...
</ul>
</template>
</PaginationData>
每次在寫git commit message的時候,都覺得這次這個message要怎麼寫啊傷腦筋,況且每次寫出來的東西都沒有一致的格式,導致自己覺得混亂乾脆不去看他,漸漸的就步入了一種惡性循環當中,趁這個機會做個紀錄並糾正自己的格式。
惡性循環
亂寫message >> 不去管理他 >> 繼續亂寫
主要是讓後續維護者(或者是自己)閱讀,單憑 Git commit message 就能瞭解之前做過了那些改動,而不需要去檢查每一個� log� 究竟做了什麼改動,假設code改動超過幾百行,但是目的只為了達到某件事情,那直接寫在 Git commit message 上面不就讓人一目瞭然了嗎?
在Google一番之後發現中文文章大多數是參考這篇文章作為標準,不過我是參考中文版
其實這沒有絕對好或壞,單純是看人、團隊的規定。那你說:我們團隊沒有規範,都是各自開發怎麼辦?那就只好自己規範一套自己的拉~
這邊直接套用文章中的七大原則
Fixed companyProfile Bugs(標題)
when user enter this page,will see name split each char(內文)
標題越簡潔越好,與內容相反。
使標題方便在 git log --oneline 下閱讀
舉例而言:
If applied, this commit will refactor subsystem X for readability
If applied, this commit will update getting started documentation
If applied, this commit will remove deprecated methods
If applied, this commit will release version 1.0.0
If applied, this commit will merge pull request #123 from user/branch
注意到,如果使用非祈使句會讓這個句子不通順:
If applied, this commit will fixed bug with Y
If applied, this commit will changing behavior of X
If applied, this commit will more fixes for broken stuff
If applied, this commit will sweet new API methods
如果只更動內容只使用標題的文字就可以描述的話可以省略內文
可以在gcm的標題最前面加上類別好分辨
大致上可以分類為以下幾種:
[fix] example title message
或者是
fix: example title message
取決於喜好or規範
參考: https://www.academind.com/learn/vue-js/snippets/image-upload/
<el-upload
class="avatar-uploader"
action="url"
:multiple="false"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="">
</el-upload>
handleAvatarSuccess(res, file, fileList) {
let formData = new FormData();
formData.append('uniID', this.uniID);
formData.append('thumbnail', file.raw);
axios.post(`${this.GLOBAL.apiUrl}/public/api/company/upload-picture`, formData)
.then((res)=>{
console.log(res);
})
.catch((err)=>{
console.log(err);
});
console.log(formData);
for (var [key, value] of formData.entries()) {
console.log(key, value);
};
},
在受夠 RN 要跟模擬器打交道以及其他各種奇怪的 bug 之後決定放棄,使用 Expo 這種可以無腦玩的方式。
畢竟現在也只是牛刀小試一下而已~
https://reactnative.dev/ RN 官網
https://expo.io/ expo 官網
https://reactnavigation.org/ 導航 library
https://docs.expo.io/guides/icons/ @expo/icon library
https://stackoverflow.com/a/59517269/9057142
試過以下幾套
react native elements 功能少
RNUI 程式碼範例與文件缺乏
native-base 程式碼範語文件較齊全但已經沒在維護
UI Kitten 推薦
在 React Native 是不能使用 <div>
、<span>
等 HTML tag 的,只能使用 RN 本身提供的 <View>
、<Text>
等等
請參考對照表
在 RN 中使用 style 還蠻容易的,請參考 https://reactnative.dev/docs/style
至於的話,RN 可使用 Flex 的方式來處理,https://reactnative.dev/docs/flexbox 有詳細的說明
在 RN 裡面因為有的手機會有瀏海的關係
所以必須使用 react-native-safe-area-context 等類似的套件來解決。
在 APP 開發的世界中好像沒有 Router 這個用法,都是稱作 navigation 導航。
要使用不同導航的話可以用 navigation.navigate、navigation.push、navigation.goBack、navigation.popToTop 等方法辦到,請參考常用連結的 react-navigation
let csvBase64 = res.data.payload.file;
var dom = document.createElement('a');
dom.href = csvBase64;
dom.download = "列表.csv";
dom.click();
npm install --save @babel/polyfill
之後在main.js裡面
import 'babel-polyfill'
重新編譯後結束
var resizeTimer;
window.addEventListener("resize", function(e) {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
// Run code here, resizing has "stopped"
console.log(123)
}, 250);
});
參考: https://css-tricks.com/snippets/jquery/done-resizing-event/
先給 <el-autotcomplete>
一個 ref="autocomplete"
然後在
@keyup.enter.native.prevent="inputSearch(keyword)"
裡面寫
this.$refs.autocomplete.$refs.suggestions.showPopper = false;
這樣按下 enter 之後就會一起將提示框關閉了
首先要說會想寫回顧文章主要是看了以下兩位前輩才產生的想法
每次看完別人的文章都有一種:
哇,好厲害,居然可以條理分明地列出所有做過的事情,然後每一件事情都可以講出一個所以然,然後放到一篇文章中做紀錄,尤其是對我這種沒什麼在寫文字的人來說。
這樣的想法時常在我腦海中浮現,於是就產生了這篇文章,內容並不會有制式規定,想寫甚麼就寫甚麼~
去年 12 月 10 號開始第二份前端工程師的工作(就是目前這份),直到現在滿一年又多一點,真的深刻感受到公司好壞的差別。
因為我上一份工作經驗超級無敵差,進去沒三個月就直接倒閉這樣,中間曲折離奇的故事就更不用說了。關於這一段故事我想我會寫一篇文章另外講。
而目前的公司有兩個開發部門,我的部門是專門接專案做的,所以產出的專案就會比較多一點,然後品質比較差(?),畢竟在有限時間內不可能事事求最好,不過我捫心自問我都是很認真在寫啦。
來說說我做了那些專案吧
這個系統蠻特殊的,後來也當成公司的產品在做,但因為我是中期才加入專案,架構跟寫法都因為已經有了不好改,加上當時的我對 Vue 真的很不熟悉,所以每隻檔案幾乎都沒在拆 component 的,主要的檔案幾乎都是千行起跳。
這也導致我到後期就開始要加新的程式碼的時候就會很痛苦,因為一隻檔案裏面 template , data , function ,style 全寫在一起,光是要找到我想要找的變數就很不容易,滑鼠要瘋狂的滾,後來雖然有用了 vscode 的 ctrl + f 去搜尋,是有加快了一些,但是並沒有解決根本的問題。
現在回想,這可能也是間接導致我的開發速度慢上不少的原因,但是我當時並不知道。
所以後來在 成為卓越程式設計師的38項必修法則 書中讀到 DRY 原則跟 KISS 原則,就覺得相見恨晚。
某地方政府內部系統
論壇
求大大(TypeScript)手下留情
紀錄 jest 學習遇到的障礙與解決方案
...
<slot :item="item">
<span v-html="markMatchWord(item[valueKey])"></span>
</slot>
...
methods: {
markMatchWord(val) {
if (!this.value) {
return val;
}
let keyword = this.value;
let regexp = new RegExp(this.value, 'g');
let result = val.match(keyword);
let str = '';
console.log(str);
console.log(result);
// return val.slice(1);
val = val.replace(regexp, '<span class="highlight-text">' + this.value + '</span>');
return val;
},
...
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.