有意義的同義詞庫
記住使用同義詞庫時找到的所有單字。
SynonymSearch 透過在您尋找所有搜尋查詢時按其共用定義對所有搜尋查詢的清單進行排序,幫助您回顧剛剛學到的內容(否則可能會忘記)。
SynonymSearch 可讓您透過將同義詞注入句子中來測試同義詞的相似性,該句子的含義取決於它們共享的定義。該應用程式可幫助您主動理解定義,然後根據同義詞儲存庫進行檢查。
該專案是作為 Code Institute 的 MS2 互動式前端模組的一部分開發的。它是為與 Merriam-Webster 的 Collegiate® Thesaurus 的 JSON 回應格式配合使用而編寫的,並透過 Next.js 使用 React 進行開發,使用create-next-app
進行引導並使用 Vercel 進行部署。
請造訪此處的項目:synonyms.vercel.app
供參考:早期方案命名為“synonym-chaser”
原理圖模型於 2021 年 1 月初開始,以建立不同組件之間的關係並分配適當的職責。
這種方法有助於分解專案範圍,最重要的是,為開發和故障排除提供參考基準。
請參閱 React 中的思考(文件)
{Results} => {Root} => {Sense} => {Option}
(請參閱結果目錄){Saves} => {Selection}
(請參閱儲存目錄){ReplaceSubStringNode}
} 從{Results} =>{Root} => {Sense}
傳遞的經過操作的字串(請參閱 string.helper.js)。現在細分為{Saves} => {Selection}
(參見顯示) {Sense} => {Option}
之間處理(請參閱結果目錄)一致的頂部和底部邊框應用於具有動態內容的所有節點。這些離散的邊框旨在將記事本的材料尺寸傳達為使用者熟悉的接觸點。這些wordBoxes
僅在間距上有所不同,並負責在視覺上傳達清單清單中的層次結構。
ThemeProvider
包裝應用程序,以便將樣式傳遞到元件樹中。請參閱 Material-UI 主題。 字體系列設定為系統字體數組,以便適應裝置/平台/使用者配置並避免依賴顯式字體。 theme.context.js
中的commonSettings
物件包含這些覆蓋的列表,該列表與 Material-UI 的主題提供者合併。請參閱 Material-UI Global-css
export const commonSettings = {
typography : {
fontFamily : [
'-apple-system' ,
'BlinkMacSystemFont' ,
'"Segoe UI"' ,
'Roboto' ,
'"Helvetica Neue"' ,
'Arial' ,
'sans-serif' ,
'"Apple Color Emoji"' ,
'"Segoe UI Emoji"' ,
'"Segoe UI Symbol"' ,
] . join ( ',' ) ,
} ,
}
該應用程式具有兩組主要和次要顏色,分別用於透過 Material UI 的調色板配置配置的淺色主題和深色主題。顏色的行為和狀態依賴 Material-UI 的預設主題物件中定義的屬性。次要顏色設定為中性色調,而原色則渲染為單一的“特徵顏色”。顏色設定的最低限度方法是增強記事本
const lightTheme = createMuiTheme ( {
palette : {
type : 'light' ,
primary : {
main : '#ff3200' ,
} ,
secondary : {
main : grey [ 900 ] ,
} ,
} ,
... commonSettings ,
} ) ;
const darkTheme = createMuiTheme ( {
palette : {
type : 'dark' ,
primary : {
main : lightblue [ 500 ] ,
} ,
secondary : {
main : '#fafafa' ,
} ,
background : {
default : '#151515' ,
} ,
} ,
... commonSettings ,
} ) ;
該網站被建模為漸進式 Web 應用程序,無需重新加載整頁即可呈現單頁應用程式的功能,並經過最佳化以像本機應用程式一樣執行。其框架確保了跨瀏覽器的靈活性。
該網站利用大型浮動操作按鈕 (FAB) 在三個遠端視圖之間快速導航:「搜尋」、「資訊」和「儲存」。視覺隱喻被用來離散且有效地表示這些視圖模式。
浮動的「快速撥號」按鈕在視圖中持續存在,以快速存取應用程式的核心操作:查詢術語、清除已儲存的歷史記錄以及切換淺色或深色模式。
該應用程式在初始頁面加載時具有自訂啟動螢幕,以簡潔地描述其用途:「互動式同義詞庫應用程式」。
jsx
、 jss
js
之間。 (使用 Nestjs 引導)next
是開發, next build
,準備生產, next start
服務。commit
到 Git 並push
送到 GitHub。push
時儲存專案的程式碼和目錄。樣式是用 jss 語法編寫的,並遵循 Material-UI 規範,以便與 Nextjs 伺服器端渲染很好地配合,其中包括自訂pages/_document
的邏輯,以便在使用之前將伺服器端渲染樣式註入到標記中。請注意,這是非官方建議,如果/當 MUI 發布類似於 MUI/Gatsby 的 Nextjs 官方插件時,應進行重構。
所有樣式物件都是使用 MUI 的makeStyles
掛鉤建立的,並遵循 MUI 樣式文件中的主題主題指南。這包括 CSS 覆蓋和媒體查詢。主要元件的樣式物件在樣式目錄中以範圍分隔,並根據需要匯入模組中。但是,某些元件(即Launcher
)在元件檔案本身中聲明了所有樣式屬性。請注意,為了保持一致性,所有樣式最終都應從一個目錄中導出。
results
樹在每個 API 呼叫上呈現jsx
元件,而無需初始化常數。道具和條件表達式控制來自 MW-Thesaurus API 的回應模式的迭代。請注意,值和 Prop-Type 驗證是專門編寫的,以便從此模式中獲得正確的資料:
每個已儲存的單字實例都保留其「獲取」的結果系列的屬性(例如單字的特定定義、標籤、詞根),以增加重複項的值並按意義定義將單字分組,同時確保每個實例(無論相同)在名稱值上,如果定義和含義不同,則不同
React 鉤子useReducer
、 useContext
、 createContext
在context/words.context
中組裝在一起(請參閱 HistoryProvider),為元件提供上下文包裝器以共用和使用相同的資料。請注意,此邏輯直接根據 next.js/examples/with-context-api 中設定的範例建模。
遵循HistoryProvider
導出的上下文包裝鉤子useHistory
和useDispatchHstory
所實現的目標——它們在helpers/*
中的高階組件、共享組件和輔助函數中使用,以從根本上操作DOM——相同的邏輯被重新用於騎乘多個元件將自訂包裝器與 MUI 的 ThemeProvider 掛鉤(請參閱 ThemeProvider)。在這種情況下,設定視圖值允許任何元件從任何地方變更頁面,僅舉幾例。請注意,此 Context 佈局提供者的包羅萬象的性質。
export const ThemeContextProvider = ( { children } ) => {
// Sets the theme for MUI ThemeProvider to use
const [ darkMode , setDarkMode ] = useState ( false ) ;
// Sets the current view
const [ value , setValue ] = useState ( 'launch' ) ;
// Hooks to set warning colors for searchText input
const [ meta , setMeta ] = useState ( true ) ;
const [ root , setRoot ] = useState ( '' ) ;
// Rides an MUI hook to set a memoized theme
const prefersDarkMode = useMediaQuery ( '(prefers-color-scheme: dark)' ) ;
useMemo (
( ) => ( prefersDarkMode
? setDarkMode ( true )
: setDarkMode ( false ) ) ,
[ prefersDarkMode ] ,
) ;
// Provides all values and the hooks that control them
return (
< ThemeDispatchContext . Provider
value = { {
darkMode ,
setDarkMode ,
value ,
setValue ,
meta ,
setMeta ,
root ,
setRoot ,
} }
>
< ThemeProvider
theme = {
darkMode
? darkTheme
: lightTheme
}
>
{ children }
< / ThemeProvider >
< / ThemeDispatchContext . Provider >
) ;
} ;
// All state/hooks are accessible by importing
// a catch-all export below
// Example:
// // anyFile.js
// import { useDispatchTheme } from './../theme.context'
//
// const dispatch = useDispatchTheme()
//
// Change any/all states from any component
// dispatch.setDarkMode(false)
// dispatch.setValue('search')
//
export const useDispatchTheme = ( ) => useContext ( ThemeDispatchContext ) ;
對於非商業和/或教育目的,使用 MW-Thesaurus 是免費的。資訊標籤中的特色品牌標誌遵循但不限於韋氏開發中心要求的品牌指南。
連結到該專案的已註冊 Thesaurus API 金鑰目前是公開的。經過這次討論,保護客戶端 API 呼叫的努力是沒有目的的,因為私鑰總是會被揭露。應考慮遵循 Nextjs API 路由進一步配置在/pages/api
中擁有內部端點。請注意,出於上述原因以及出於專案的教育目的,密鑰已從.env.local
公開。
const axiosConfig = { baseURL : 'https://dictionaryapi.com/api/v3/references/' , } ;
function searchThesaurus ( searchText , selection ) {
const query = selection || searchText ;
// Key is processed from ignored env.local
// use this method if API endpoint is set up in /pages/api/*
const key = process . env . MW_THESAURUS_KEY ;
// @note Key is explicitly declared otherwise
// for Production/submission
return axiosGetCancellable (
`/thesaurus/json/ ${ query } ?key= ${ key } ` ,
axiosConfig ,
) ;
}
注意:所有非典型方法的描述都可以在遵循 jsDoc 標準的註解區塊中找到。
用戶希望在到達網站後幾秒鐘內看到描述
Launcher
:useEffect
允許Launcher
在初始頁面載入時執行一次useContext
允許Launcher
在逾時後將目前頁面視圖value
設定為「 search
」。Synonym Search An Interactive Thesaurus App
」兩秒半。 import React , { useEffect , useState } from 'react' ;
import { useDispatchTheme } from '../../context/theme.context' ;
const Launcher = ( ) => {
const classes = useStyles ( ) ;
const viewDispatch = useDispatchTheme ( ) ;
const [ open , setOpen ] = useState ( true ) ;
const [ showOpen , setShowOpen ] = useState ( true ) ;
useEffect ( ( ) => {
setTimeout ( ( ) => {
setShowOpen ( false ) ;
setTimeout ( ( ) => {
setOpen ( false ) ;
viewDispatch . setValue ( 'search' ) ;
} , 350 ) ;
} , 2500 ) ;
} , [ ] ) ;
return (
< >
< Backdrop
className = { classes . backdrop }
open = { open }
/ >
< Grow
in = { showOpen }
unmountOnExit
>
< Box className = { classes . launch } >
{ ... excerpt . . . }
Synonym
/Search
An Interactive Thesaurus App
{ ... excerpt . . . }
< / Box >
< / Grow >
< / >
) ;
} ;
使用者希望在視圖之間方便地導航
Speed (Dial)
:onClick
。FixedBottom
(從FixedBottom分叉)允許底部Speed Dial
在滾動時響應地移動到移動設備的底部欄上方。useScrollTrigger
允許Speed Dial
與ScrollTop
交換可見性,ScrollTop 是一個浮動操作按鈕,當按一下該按鈕時,可透過id="back-to-top"
錨點將視窗捲動回頁面頂部。Search
的屬性將傳遞到Speed Dial
以啟動onSearchTextChange
,該函數將查詢傳送到 Thesaurus API。useState
允許useEffect
在透過useDispatch
更改頁面value
時始終關閉SpeedDial
,除非Search
處於active
。ToggleTheme
、 Search
、 Clear
Saves
視圖中SpeedDial
SpeedDial
已打開ToggleTheme
操作not
這個<mode>
SpeedDial
已關閉Saves
視圖中SpeedDial
SpeedDial
已打開Search
操作SpeedDial
仍然打開Search
視圖中SpeedDial
消失ScrollTop
按鈕ScrollTop
SpeedDial
SpeedDial
操作來快速在x
和y
維度中導航(在視圖中向上/向下,在視圖之間向左/向右)。此外,可以在頁面標題中存取每個視圖的按鈕導航。另外兩個視圖是Saves
和Info
,它們與SpeedDial
中的操作屬於同一浮動操作按鈕系列。主題、顏色和使用者介面的一致性和獨特性會影響使用者的衝動和對所傳達的持久接觸點的熟悉程度。 import React , { useEffect , useState } from 'react' ;
import { useDispatchTheme } from '../../context/theme.context' ;
const Speed = ( {
children ,
value ,
index ,
searchText ,
loading ,
onSearchTextChange ,
... other
} ) => {
const trigger = useScrollTrigger ( ) ;
const classes = useStyles ( ) ;
const [ open , setOpen ] = useState ( false ) ;
const [ direction , setDirection ] = useState ( 'up' ) ;
const matches = useMediaQuery ( '(min-width:600px)' ) ;
const viewDispatch = useDispatchTheme ( ) ;
const view = viewDispatch . value ? viewDispatch . value : null ;
const handleClick = ( event ) => setOpen ( ! open ) ;
open && trigger ? setOpen ( false ) : null ;
useEffect ( ( ) => {
setTimeout ( ( ) => {
if ( viewDispatch . value !== 'search' ) {
setOpen ( false ) ;
}
} , 10 ) ;
} , [ view ] ) ;
return (
< Slide appear direction = "up" in = { ! trigger } >
< FixedBottom offset = { matches ? 16 : 48 } >
< SpeedDial
ariaLabel = "actions"
className = { classes . speedDialGroup }
FabProps = { {
className : clsx ( classes . speedDial , classes . bottom ) ,
size : matches ? 'medium' : 'small' ,
style : { padding : matches ? '12px' : '8px' } ,
} }
onClick = { handleClick }
open = { open }
direction = { direction }
>
{ ... Search action }
{ ... Toggle theme action }
{ ... Clear cache action }
/ >
< / SpeedDial >
< / FixedBottom >
< / Slide >
) ;
} ;
export default Speed ;
用戶希望看到可靠的來源
Brands
(Material-UI AvatarGroup
):useEffect
允許useState
在頁面值設置為當前view
=> Info
時翻轉邊距,使頭像動畫展開,彷彿歡迎用戶來到信息台,同時有一個簡短的段落來描述背後的“ SynonymStory
” “ SynonymSearch
”Logo
實例,每個實例一個: React
、 NextJS
、 MaterialUI
、 CodeInstitute
和Merriam-Webster
。Search
視圖中Info
Info
視圖中Brands
頭像出現Merriam-Webster
Merriam-Webster Developer Center website
Info
中 import React , { useEffect , useState } from 'react' ;
import { useDispatchTheme } from '../../context/theme.context' ;
const Brands = ( { children } ) => {
const classes = useStyles ( ) ;
const viewDispatch = useDispatchTheme ( ) ;
const [ active , setActive ] = useState ( false ) ;
const { value } = viewDispatch ;
useEffect ( ( ) => {
if ( value === 'info' ) {
setTimeout ( ( ) => {
setActive ( true ) ;
} , 750 ) ;
}
} , [ ] ) ;
return (
< AvatarGroup
className = {
clsx (
classes . avatarGroup , active
? classes . active
: classes . inactive ,
)
}
>
< Logo
name = "React"
url = "https://react.org/"
path = "/images/reactLogo.png"
/ >
< Logo
name = "Next JS"
url = "https://nextjs.org/"
path = "/images/nextJSLogo.svg"
/ >
< Logo
name = "Material UI"
url = "https://material-ui.com/"
path = "/images/materialUILogoLight.png"
darkImage = "/images/materialUILogoDark.png"
/ >
< Logo
name = "Code Institute"
url = "https://codeinstitute.net/"
path = "/images/codeInstituteLogo.png"
/ >
< Logo
name = "Merriam-Webster"
url = "https://dictionaryapi.com/"
path = "/images/merriamWebsterLogoLight.png"
/ >
< / AvatarGroup >
) ;
} ;
用戶想要搜尋同義詞
Search
:loading
:結果是否正在加載,meta
:使用者的輸入是否產生有效的結果,root
:結果陣列中的第一項是否與使用者輸入的內容相符。useState
允許這些條件動態改變。useRef
附加到輸入元件,並允許按鍵和滑鼠事件根據上述條件有條件地focus
輸入提示。Field
, Input
。Search
視圖中Search
操作immediately successful word
>immediately successful word
的同義詞Search
操作incomplete word
>real word
>real word
的同義詞更新Search
操作a word with no matches
>good word
>new word
的同義詞更新 const Field = ( {
label ,
onChange ,
placeHolder ,
helperText ,
loading ,
} ) => {
const theme = useTheme ( ) ;
const trigger = useScrollTrigger ( ) ;
const [ active , setActive ] = useState ( false ) ;
const textInput = useRef ( null ) ;
const metaDispatch = useDispatchTheme ( ) ;
const { meta , root } = metaDispatch ;
const handleSearchButton = ( ) => {
setActive ( true ) ;
setTimeout ( ( ) => {
textInput . current && textInput . current . focus ( ) ;
} , 100 ) ;
} ;
const handleClickAway = ( ) => setActive ( false ) ;
const handleBackDrop = ( ) => setActive ( false ) ;
const onKeyPress = ( ) => setActive ( false ) ;
const match
= textInput . current
? textInput . current . value === root
: false ;
active && trigger ? setActive ( false ) : null ;
useEffect ( ( ) => {
if ( active && match ) {
setTimeout ( ( ) => {
setActive ( false ) ;
} , 2000 ) ;
}
} , [ ] ) ;
return (
< ClickAwayListener
onClickAway = { handleClickAway }
>
< >
< Backdrop
open = { active }
onClick = { handleBackDrop }
/ >
< Fab
size = "small"
color = "primary"
aria-label = "search"
onClick = { handleSearchButton }
variant = { active ? 'extended' : 'round' }
style = { active ? {
backgroundColor :
loading
? theme . palette . warning . main
: ! meta
? theme . palette . error . main
: meta && match
? theme . palette . success . main
: theme . palette . primary . main ,
} : null }
>
< Input
label = { label }
placeHolder = { placeHolder }
helperText = { helperText }
active = { active }
match = { match }
meta = { meta }
loading = { loading }
textInput = { textInput }
onKeyPress = { onKeyPress }
onChange = { onChange }
/ >
< / Fab >
< / >
< / ClickAwayListener >
) ;
} ;
用戶想要查看搜尋記錄
useHistory
是一個 Context 掛鉤,用來存取HistoryProvider
中儲存的值。useReducer
允許HistoryProver
根據查詢的單字共享的定義對它們進行分組。Selection
使用者想要查看句子中使用的單字
Display
:Sense
使用它來傳遞sampleString
和optionWord
屬性,這會啟動Intersection Observer
和滑鼠事件來動態更改optionWord
屬性。{it} {/it}
和{lquo} {rquo}
節點。由於它們是開啟和關閉標記,因此當定義碰巧擁有範例字串時,正規表示式替換函數可以可靠地一致地清理範例字串。 (請參閱 Theaurus API 的回應範例)使用者希望在重複結果旁邊看到標籤(也稱為已儲存的單字)
HistoryProvider
中的useReducer
:HistoryProvider
中儲存的 Word 物件與屬性一起儲存,這些屬性允許透過將這些屬性與新單字進行比較來進行驗證:Counters
中的字類型檢查:History
中保存的單字Saves
視圖中使用了相同的功能,因此使用者可以透過他們共享的屬性定義來查看“重複”,也就是使用者儲存的單字。 const [ savedWords , dispatch ] = useReducer ( ( state , action ) => {
switch ( action . type ) {
case 'add' :
const wordIndex = state . findIndex ( ( word ) => word . uuid === action . uuid
|| word . name === action . name
&& word . sense === action . sense ) ;
if ( wordIndex !== - 1 ) {
return state . map ( ( word , i ) => ( {
... word ,
value : word . value + ( wordIndex === i ? 1 : 0 ) ,
} ) ) ;
}
return [
... state ,
{
id : state . length ,
name : action . name ,
value : 1 ,
root : action . root ,
label : action . label ,
uuid : action . uuid ,
sense : action . sense ,
} ,
] ;
case 'remove' :
return state . filter ( ( word ) => word . id !== action . id ) ;
case 'clear' :
return [ ] ;
default :
return state ;
}
} , [ ] ) ;
用戶想要刪除已儲存的搜尋記錄
Clear
:DeleteForever
圖示的按鈕,它是HistoryProvider
中useReducer
的dispatch
函數,可刪除 Context 中的所有內容。Chip
元件表示的Delete
圖示刪除單字。 // clear.button.js
// excerpt
const wordsDispatch = useDispatchHistory ( ) ;
const handleClick = ( event ) => {
wordsDispatch ( {
type : 'clear' ,
} ) ;
} ;
// words.context.js
// excerpt from reducer
// the above handler calls case 'remove'
case 'remove' :
return state . filter ( ( word ) => word . id !== action . id ) ;
查看最新結果
Vercel 的 Lighthouse 用於測試效能,它在每次git push
上都會產生獨特的結果。 lighthouse-badges 用於透過安裝npm i -g lighthouse-badges
並將新的雜湊 url 推送到 url 陣列來為每個部署產生新徽章:
lighthouse-badges
-o docs/badges -r
-u https://synonyms.vercel.app/ [... all other urls]
# Output to docs/badges
# Badges will contain the respective
average score(s) of all the urls
supplied, combined
Lighthouse 的指標(即「可訪問性」和「效能」)會在每次審核時產生特定標誌。每次推送都會進行調整,專門解決任何問題。
role
清晰而更改細化 HTML5 語意元素。 回到頂部
create-next-app
引導並使用 Vercel 進行部署,我透過以下步驟實現了這一點:commit
程式碼並將其從我的本機 IDE push
送到 Github。select
輸入存取「匯入 Git 儲存庫」。“您的專案已成功部署。”
回到頂部
git clone https://github.com/israelias/synonym-chaser
cd
到此儲存庫的名稱: cd synonym-chaser
npm install
npm run dev
# or
yarn dev
開啟瀏覽器存取 localhost:3000
info
中簡短描述以外的所有內容均來自韋氏大學同義詞庫。回到頂部