当前位置: 首页 > wzjs >正文

移动互联网开发实习报告北京seo学校

移动互联网开发实习报告,北京seo学校,德勤管理咨询,好看的网站 你知道的20211.背景 React 写一个 EmojiPicker 组件,基于 emoji-mart 组件二次封装。支持添加自定义背景 、Emoji 图标选择!并在页面上展示! 2.技术栈 emoji-mart/data 、emoji-mart : emoji 图标库、元数据 tailwindcss: 原子化 CSS 样式库 antd : 组…

1.背景

React 写一个 EmojiPicker 组件,基于 emoji-mart 组件二次封装。支持添加自定义背景 、Emoji 图标选择!并在页面上展示! 

2.技术栈

@emoji-mart/data 、emoji-mart : emoji 图标库、元数据

tailwindcss: 原子化 CSS 样式库

antd : 组件库

"@emoji-mart/data": "^1.2.1",
"@remixicon/react": "^4.6.0",
"antd": "^5.24.3",
"emoji-mart": "^5.6.0",
"react": "^19.0.0",
"tailwindcss": "^3.4.17",

PS:

  • emoji-mart/data@remixicon/reactantd 这些库直接用 pnpm 、npm 、yarm 直接安装即可

  • tailwindcss 安装配置参考

  • cn函数参考

3.emoji选择器组件

src/components/emojiPicker/index.tsx

import type { FC } from 'react';
import { useCallback, useState } from 'react';
import EmojiPickerInner from './emojiCom';
import { Button, Modal } from 'antd';type IEmojiPickerProps = {onSelect: (emoji: string, background: string) => void
};
const EmojiPicker: FC<IEmojiPickerProps> = ({onSelect
}) => {const [isEmojiModalOpen, setIsEmojiModalOpen] = useState<boolean>(false);const [selectedBackground, setSelectedBackground] = useState<string>();const [selectedEmoji, setSelectedEmoji] = useState<string>();const selectEmoji = useCallback((emoji: string, background: string) => {setSelectedEmoji(emoji)setSelectedBackground(background)}, [setSelectedEmoji, setSelectedBackground]);const onModalSelectEmojOk = () => {if (!(selectedEmoji && selectedBackground))returnonSelect(selectedEmoji!, selectedBackground!);clear();setIsEmojiModalOpen(false);};const clear = () => {setSelectedEmoji('')setSelectedBackground('')};return (<><Button onClick={() => setIsEmojiModalOpen(true)}> Emoj 表情</Button><Modaltitle="Emoj 表情选择"open={isEmojiModalOpen}onOk={onModalSelectEmojOk}okText="确定"cancelText="取消"okButtonProps={{ disabled: !(Boolean(selectedEmoji) && Boolean(selectedBackground)) }}onCancel={() => { setIsEmojiModalOpen(false) }}>{isEmojiModalOpen && (<EmojiPickerInner onSelect={selectEmoji} />)}</Modal ></>)
}
export default EmojiPicker

src/components/emojiPicker/emojiCom.tsx

import type { ChangeEvent, FC } from 'react';
import { useState, useEffect } from 'react';// components
import data from '@emoji-mart/data';
import type { EmojiMartData } from '@emoji-mart/data';
import { init, SearchIndex } from 'emoji-mart';// icons
import { RiSearch2Line } from '@remixicon/react';// utils
import { cn } from '@/lib/utils';export interface Skins {native: string
};export interface Emoji {id: stringname: stringkeywords: string[]skins: Skins[]version: numberemoticons?: string[]
};type IEmojiPickerInnerProps = {emoji?: stringbackground?: stringonSelect?: (emoji: string, background: string) => voidclassName?: string
};init({ data });const backgroundColors = ['#FFEAD5','#E4FBCC','#D3F8DF','#E0F2FE','#E0EAFF','#EFF1F5','#FBE8FF','#FCE7F6','#FEF7C3','#E6F4D7','#D5F5F6','#D1E9FF','#D1E0FF','#D5D9EB','#ECE9FE','#FFE4E8',
];const classNameComm = 'cursor-pointer w-8 h-8 p-1 flex items-center justify-center rounded-lg hover:ring-1 ring-offset-1 ring-gray-300'const EmojiPickerInner: FC<IEmojiPickerInnerProps> = ({onSelect, className,
}) => {const { categories } = data as EmojiMartData;const [selectedEmoji, setSelectedEmoji] = useState('');const [selectedBackground, setSelectedBackground] = useState(backgroundColors[0]);const [searchedEmojis, setSearchedEmojis] = useState<string[]>([]);const [isSearching, setIsSearching] = useState<boolean>(false);//  search iconsconst searchEmoji = async function searchEmoji(value: string) {const emojis: Emoji[] = await SearchIndex.search(value) || []const results = emojis.map((emoji) => {return emoji.skins[0]?.native})return results};// useEffectuseEffect(() => {if (selectedEmoji && selectedBackground) onSelect?.(selectedEmoji, selectedBackground)}, [onSelect, selectedEmoji, selectedBackground]);return <div className={cn(className)}><div className='flex flex-col items-center w-full px-3'><div className="relative w-full"><div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"><RiSearch2Line className="w-5 h-5 text-gray-400" aria-hidden="true" /></div><inputtype="search"id="search"className='block w-full h-10 px-3 pl-10 text-sm font-normal bg-gray-100 rounded-lg'placeholder="Search emojis..."onChange={async (e: ChangeEvent<HTMLInputElement>) => {if (e.target.value === '') {setIsSearching(false)} else {setIsSearching(true)const emojis = await searchEmoji(e.target.value)setSearchedEmojis(emojis)}}}/></div></div><div className="w-full max-h-[200px] overflow-x-hidden overflow-y-auto px-3">{isSearching && <><div key={'category-search'} className='flex flex-col'><p className='font-medium uppercase text-xs text-[#101828] mb-1'>Search</p><div className='w-full h-full grid grid-cols-8 gap-1'>{searchedEmojis.map((emoji: string, index: number) => {return <divkey={`emoji-search-${index}`}className='inline-flex w-10 h-10 rounded-lg items-center justify-center'onClick={() => {setSelectedEmoji(emoji)}}><div className={classNameComm}><em-emoji id={emoji} /></div></div>})}</div></div></>}{categories.map((category, index: number) => {return <div key={`category-${index}`} className='flex flex-col'><p className='font-medium uppercase text-xs text-[#101828] mb-1'>{category.id}</p><div className='w-full h-full grid grid-cols-8 gap-1'>{category.emojis.map((emoji, index: number) => {return <divkey={`emoji-${index}`}className='inline-flex w-10 h-10 rounded-lg items-center justify-center'onClick={() => {setSelectedEmoji(emoji)}}><div className={classNameComm}><em-emoji id={emoji} /></div></div>})}</div></div>})}</div>{/* Color Select */}<div className={cn('p-3 pb-0', selectedEmoji === '' ? 'opacity-25' : '')}><p className='font-medium uppercase text-xs text-[#101828] mb-2'>Choose Style</p><div className='w-full h-full grid grid-cols-8 gap-1'>{backgroundColors.map((color) => {return <divkey={color}className={cn('cursor-pointer','hover:ring-1 ring-offset-1','inline-flex w-10 h-10 rounded-lg items-center justify-center',color === selectedBackground ? 'ring-1 ring-gray-300' : '',)}onClick={() => {setSelectedBackground(color)}}><div className={cn('w-8 h-8 p-1 flex items-center justify-center rounded-lg',)} style={{ background: color }}>{selectedEmoji !== '' && <em-emoji id={selectedEmoji} />}</div></div>})}</div></div></div>
};export default EmojiPickerInner;

4. emoji 图标展示组件

src/components/appIcon/index.tsx

import type { FC } from 'react';
import { init } from 'emoji-mart';;
import data from '@emoji-mart/data';
import { cn } from '@/lib/utils';type AppIconType = 'image' | 'emoji';init({ data });export type AppIconProps = {size?: 'xs' | 'tiny' | 'small' | 'medium' | 'large'rounded?: booleaniconType?: AppIconType | nullicon?: stringbackground?: string | nullimageUrl?: string | null | undefinedclassName?: stringinnerIcon?: React.ReactNodeonClick?: () => void
};// used for emojiPicker
const AppIcon: FC<AppIconProps> = ({size = 'medium',rounded = false,iconType,icon,background,imageUrl,className,innerIcon,onClick,
}) => {const wrapperClassName = cn('flex items-center justify-center relative w-9 h-9 text-lg rounded-lg grow-0 shrink-0',size !== 'medium' && { large: 'w-10 h-10', small: 'w-8 h-8', tiny: 'w-6 h-6 text-base', xs: 'w-3 h-3 text-base' }[size],rounded && 'rounded-full',className ?? '','overflow-hidden',);const isValidImageIcon = iconType === 'image' && imageUrl;return <spanclassName={wrapperClassName}style={{ background: isValidImageIcon ? undefined : (background || '#FFEAD5') }}onClick={onClick}>{isValidImageIcon? <img src={imageUrl} className="w-full h-full" alt="app icon" />: (innerIcon || ((icon && icon !== '') ? <em-emoji id={icon} /> : <em-emoji id='🤖' />))}</span>
};export default AppIcon;

5.cn 函数

src/lib/utils.ts

import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";export function cn(...inputs: ClassValue[]) {return twMerge(clsx(inputs));
}

6.测试使用

src\App.tsx

import { useState } from 'react';
import EmojiPicker from '@/components/emojiPicker';
import AppIcon from '@/components/appIcon';function App() {const [emoji, setEmoji] = useState('😀');const [background, setBackground] = useState('');const onSelect = (emoji: string, background: string) => {setEmoji(emoji)setBackground(background)};return (<div className="flex justify-center items-center h-screen gap-2"><AppIcon icon={emoji} background={background} /><EmojiPicker onSelect={onSelect} /></div>);
}export default App;

效果展示
在这里插入图片描述

如果你有更多问题,欢迎随时问我!😊

http://www.dtcms.com/wzjs/412047.html

相关文章:

  • 毕设敦煌壁画网站开发选题背景网站设计与网页制作
  • jsp做的网站答辩问题域名查询注册商
  • 企业网站改版升级厦门seo代理商
  • 男女的做那个视频网站郑州seo课程
  • 北京做网站多少钱提高搜索引擎排名
  • 视频网站如何做seo河北seo公司
  • 17zwd一起做网站百度免费推广登录入口
  • wordpress扫码支付宝seo公司优化排名
  • 论坛网站地图怎么做sem 优化软件
  • WordPress 网站小图标东莞最新消息 今天
  • 怎么制作博客网站seo哪家公司好
  • 南昌微信网站开发公司宣传推广的十种方式
  • 最近发生的新闻热点事件长沙官网seo
  • 建设网站如百度客户服务电话是多少
  • 柳州做网站aso优化排名
  • 做o2o平台网站需要多少钱淘宝客推广
  • 兴远建设网站百度问一问官网
  • 网站开发毕业论文参考期刊文献抖音关键词推广怎么做
  • 天猫网站建设分析sem培训
  • 网站建设技术团队中国新闻社
  • 网站轮播图片怎么做的淘宝运营培训
  • dw做的手机端网站搜索seo优化
  • 支付宝 手机网站支付接口2.0房地产最新消息
  • seo网站优化推广怎么做何鹏seo
  • 提供网站建设课程无锡百度公司王东
  • 做网站的意义百度首页排名优化多少钱
  • 网站被镜像怎么做网站关键词优化的价格
  • 四川建设培训网刷seo快速排名
  • 网站建设重要软文推广代理
  • 网站的差异平台宣传推广方案