2022我的年終總結

夕水發表於2022-12-28

本文參與了 SegmentFault 思否年度徵文「一名技術人的 2022」,歡迎正在閱讀的你也加入。

前言

時光如梭,歲月匆匆而過,2022年一轉眼就已經到了末尾,今年的環境異常艱難,可是想想自己這一年來的付出,也還是值得做一個覆盤總結的,正所謂有得必有失,在這一年我失去了太多,不過卻也讓我成長了不少,當然這些都是題外話,我主要還是來複盤一下今年我所學習的成果。

文章總結

今年一共寫了11篇文章,加上本次年終總結,一共12篇,數量也並不多,分別如下:

其中尤其是50天用vue3完成了50個web專案,我學到了什麼?實現《羊了個羊》的小遊戲我最為滿意,畢竟這兩篇文章是我用心總結出每一個知識點,並且讓自己融會貫通學到的知識點,同時也幫助他人學到知識點那就足夠了。

其實今年我主要重心放在了React技術棧上,所以我也用React寫了不少東西,對於vue框架,尤其是vue3,最主要的輸出就是50天用vue3完成了50個web專案,我學到了什麼?,關於這50個專案其實雖然表面上寫的是50天,但實際上我花了不止50天,當然這都不重要了,最重要的是我從這50個專案裡面深入去了解了一下less和sass這兩門css預處理語言的語法。例如混入mixin,函式,迴圈,條件判斷等,兩種預處理語言之間也有很多相同的地方,當然也有不同的地方。比如迴圈,我們在sass當中會有@for關鍵字,而在less當中,我們需要寫選擇器 + when(這種更像是在寫遞迴呼叫自身)。

同時對於vue3的核心語法,我也有了一定的認知,至少在實際做vue3的專案當中,我認為我還是沒有多大的問題的,這些都是透過實際動手做這50個web專案讓我學到的,為了方便我還特意用vue3寫了一個關於這50個web專案的網站,地址在這裡

PS: 如果以上地址訪問不到,可以訪問這裡

這個網站是我自己設計並實現的,雖然佈局看起來有些簡單,但是我認為其中的邏輯功能和樣式程式碼還是有點點難度的,在這裡我可以總結一下有哪些知識點值得學習:

  • 實現一個clickOutside指令
  • 實現一個下拉框元件
  • 實現一個圖片預載入元件
  • 實現classnames工具函式(不是複製的classnames原始碼,是參考實現的)
  • 實現文字超出省略的判斷
  • 實現回到頂部的功能
  • 卡片元件以及圖示元件的實現
  • less核心語法

以上是我今年在文章上所做的總結,除此之外我還在github上新增貢獻並逐步完善了3個倉庫,讓我們一起來看看吧。

3個專案

演算法

關於劍指offer演算法,我基本上已經將劍指offer的官方演算法題刷完了,並且解題思路,我也已經記下來建了一個專案,地址在這裡

雖然在工作當中我似乎並沒有用到太多演算法,可事實上做了一下演算法題確實是開啟了我的眼界,更何況,我也已經將演算法給加到了我所做的專案當中,比如那個用vue3實現連連看的小遊戲裡面就有這樣一個演算法。

const findRepeatItem = function (arr: GlobalModule.MaterialData[]) {
    const unique = new Set();
    for (const item of arr) {
        if (unique.has(item.src)) {
            return true;
        }
        unique.add(item.src);
    }  
    return false;
};

這個函式顧名思義,就是從陣列當中查詢重複項,思路就是利用set資料結構儲存每一個陣列項,然後當資料裡面存在要查詢的項的時候,就代表重複了,直接返回即可,這個函式的思路就來源於演算法當中。也就是這個演算法陣列中重複的數字的思路二--雜湊表解法。

這只是其中一個小小的應用而已,如果在實際專案當中碰到相應的需求,我或許也會再次回頭來翻看這些筆記,已達到鞏固並且舉一反三的目的,這個專案也就是我今年完善的3個專案之一。

js和css程式碼段

css程式碼段

這可能是我今年付出精力最多的一個專案了吧,幾乎每天都要貢獻一段程式碼段,不信看下圖:

每天學習一段javascript或者是css程式碼段,不至於讓自己忘記css和js基礎,而且很多程式碼段都會用到實際業務當中,比如使用css實現自定義的單選框和核取方塊,我們以單選框作為示例講一下實現思路如下。

css實現單選框

思路就是如下列出的幾點,我們就可以建立一個帶有狀態更改動畫的樣式單選按鈕。

  • 建立一個 .radio-container 並使用 flexbox 為單選按鈕建立適當的佈局。
  • 重置 <input> 上的樣式並使用它來建立單選按鈕的輪廓和背景。
  • 使用 ::before 元素建立單選按鈕的內圈。
  • 使用 transform: scale(1) 和 CSS transition 在狀態變化時建立動畫效果。

程式碼量也不算多,我們來看html和css程式碼分別如下:

<div class="radio-container">
    <input type="radio" class="radio-input" id="male" name="sex"/>
    <label for="male" class="radio">男</label>
    <input type="radio" class="radio-input" id="female" name="sex"/>
    <label for="female" class="radio">女</label>
</div>
.radio-container {
    box-sizing: border-box;
    background-color: #fff;
    color: #545355;
    height: 64px;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-flow: row wrap;
}
.radio-container * {
    box-sizing: border-box;
}
.radio-input {
    appearance: none;
    background-color: #fff;
    width: 16px;
    height: 16px;
    border: 1px solid #cccfdb;
    margin: 0;
    border-radius: 50%;
    display: grid;
    align-items: center;
    justify-content: center;
    transition: all .3s ease-in;
}
.radio-input::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    transform: scale(0);
    transition: .3s transform ease-in-out;
    box-shadow: inset 6px 6px #fff;
}
.radio-input:checked {
    background-color: #2396ef;
    border-color: #2396ef;
}
.radio-input:checked::before {
    transform: scale(1);
}
.radio {
    cursor: pointer;
    padding: 6px 8px;
}
.radio:not(:last-child){
    margin-right: 6px;
}

都是常規的佈局,其中我們主要利用了label的for屬性和input的id屬性繫結在一起,然後透過樣式將input框給隱藏,修改label的樣式去模擬出單選框,從而達到如下的效果:

同理,核取方塊也是這樣的思路去實現的,事實上還有很多小技巧,比如隱藏一個元素,我們通常可能會使用display和visibility又或者是opacity屬性來達到隱藏,可事實上這三個屬性隱藏元素或多或少都會有一定的問題,比如display無法新增過渡效果,而visibility又佔用元素本身的空間,opacity只是單純的設定透明度,元素依然可以被點選等等,而這裡我們可以利用clip和定位來達到隱藏元素的目的,從而解決前面三個屬性所帶來的問題。程式碼如下:

.offscreen {
    border: 0;
    clip: rect(0,0,0,0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
}

然後我們給要隱藏的元素新增一個offscreen類名即可達到隱藏元素,這不失為一種隱藏元素的辦法,當然還有很多的css程式碼段值得學習的,例如border實現等高佈局,css實現載入中效果,開關元件,高度過渡效果等等示例。

js程式碼段

除了css程式碼段,js程式碼段也有許多值得學習的知識點,比如氣泡排序演算法.

氣泡排序演算法

我們來看這個演算法的實現思路如下:

  • 宣告一個變數,swapped,指示在當前迭代期間是否交換了任何值。
  • 使用擴充套件運算子 (...) 克隆原始陣列 arr。
  • 使用 for 迴圈遍歷克隆陣列的元素,在最後一個元素之前終止。
  • 使用巢狀的 for 迴圈遍歷 0 和 i 之間的陣列段,交換任何相鄰的亂序元素並將 swapped 設定為 true。
  • 如果在迭代後 swapped 為 false,則不需要更多更改,因此返回克隆的陣列。

程式碼如下:

const bubbleSort = arr => {
    let swapped = false;
    let a = [...arr];
    for(let i = 0;i < a.length;i++){
        swapped = false;
        for(let j = 0;j < a.length - i;j++){
            if(a[j + 1] < a[j]){
                //陣列解構的方式
                [a[j],a[j + 1]] = [a[j + 1],a[j]];
                swapped = true;
            }
        }
        if(!swapped) { 
            return a;
        }
    }
    return a;
}

再比如陣列分塊,這個也會用到實際業務當中。

陣列分塊

我們來看實現陣列分塊的思路如下:

  • 使用 Array.from() 建立一個新陣列,該陣列適合將要生成的塊數。
  • 使用 Array.prototype.slice() 將新陣列的每個元素對映到長度為 size 的塊。
  • 如果原始陣列不能被平均分割,最終的塊將包含剩餘的元素。

js程式碼如下:

const chunk = (arr,size) => Array.from({ length:Math.ceil(arr.length / size)},(v,i) => arr.slice(i* size,i * size + size));   

當然還有更多的css和js程式碼段,我就不一一舉例了,我只是想說明這樣每天學習一段程式碼段讓自己學到了很多,更多的程式碼段請看網站

如果訪問不了,可訪問這個網站

react程式碼段

今年還新開了一個專案,記錄react的學習程式碼段,包含基礎元件和hook函式兩個部分,除此之外,還有在使用antd design元件庫的元件基礎上額外封裝的元件。比如實現一個彈出框元件,一個倒數計時元件一個手風琴元件等等,像hooks函式就更多了,比如useTimeout函式,useInterval等等,useBodyScrollLock函式等等。我還是舉其中2個示例來說明吧。

受控的input元件

主要是樣式去美化input元件,同時將input元件的value值和onchange事件暴露出去,在這裡我使用的是css in js來美化輸入框的,程式碼如下:

import styled from '@emotion/styled';
import React from 'react';
import type { SyntheticEvent } from 'react';

const StyleInput = styled.input`
  box-sizing: border-box;
  margin: 0;
  font-variant: tabular-nums;
  list-style: none;
  font-feature-settings: 'tnum';
  position: relative;
  display: inline-block;
  width: 100%;
  min-width: 0;
  padding: 4px 11px;
  color: #000000d9;
  font-size: 14px;
  line-height: 1.5715;
  background-color: #fff;
  background-image: none;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
  transition: all 0.3s;
  &:focus {
    border-color: #40a9ff;
    box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
    border-right-width: 1px;
    outline: 0;
  }
`;
type LiteralUnion<T extends U, U> = T & (U & {});
interface ControlledInputProps {
  type: LiteralUnion<
    | 'button'
    | 'checkbox'
    | 'color'
    | 'date'
    | 'datetime-local'
    | 'email'
    | 'file'
    | 'hidden'
    | 'image'
    | 'month'
    | 'number'
    | 'password'
    | 'radio'
    | 'range'
    | 'reset'
    | 'search'
    | 'submit'
    | 'tel'
    | 'text'
    | 'time'
    | 'url'
    | 'week',
    string
  >;
  value: string;
  onChange(v: string): void;
  placeholder: string;
}
const ControlledInput = (props: Partial<ControlledInputProps>) => {
  const { value, onChange, ...rest } = props;
  const onChangeHandler = (e: SyntheticEvent) => {
    if (onChange) {
      onChange((e.target as HTMLInputElement).value);
    }
  };
  return (
    <StyleInput value={value} onChange={onChangeHandler} {...rest}></StyleInput>
  );
};

並且每一個元件都有對應的tsx和jsx版本,也有相應的介面,也方便學習如何去實現封裝元件,元件的實現個人認為封裝的最複雜的是彈出框元件,因為我需要考慮2種方式使用,第一種是透過元件方式使用,第二種則是透過呼叫方法的方式來使用。

然後就是我們的hooks函式了,比如我們來看useBodyScrollLock函式的實現。

useBodyScrollLock函式的實現

在這個函式中,我們透過在useLayoutEffect生命週期鉤子函式中獲取到body元素,然後給body元素設定一個overflow為hidden的樣式,就達到了滾動的鎖定,顧名思義這個函式就是用來禁止頁面的滾動的。我們來看完整程式碼如下:

import { useLayoutEffect } from 'react';

const useBodyScrollLock = () => {
  useLayoutEffect(() => {
    const container = document.body;
    const originOverflowStyle = window.getComputedStyle(container!).overflow;
    container!.style.overflow = 'hidden';
    return () => {
      container!.style.overflow = originOverflowStyle;
    };
  }, []);
};

export default useBodyScrollLock;

當然這只是一個簡單的hook函式,很好理解,也還有更復雜的hook函式,比如useCopyToClipboard函式的實現,這裡也不需要一一敘述了,想要檢視更多實現思路,請看這個網站

如果訪問不了,請看這個網站

以上就是我今年的輸出了,當然除了這之外,我還在堅持寫一部小說,不過這就不需要透露了,哈哈哈,因為我覺得我寫的也不怎麼樣。

最後

總而言之,我今年的學習成果不算好也不算壞,但是去年立下的flag並沒有完成,只能展望於2023年了,感謝閱讀到這裡,本文就到此為止了,與君共勉。

相關文章