有意义的同义词库
记住使用同义词库时找到的所有单词。
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}
(参见显示) 显示现在是一个虚拟组件,因为react-intersection-observer完全在结果树中的{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
中简短描述之外的所有内容均来自韦氏大学同义词库。返回顶部