共计 7716 个字符,预计需要花费 20 分钟才能阅读完成。
理解如何应用 LeanCloud 创立数据库并应用 Next.js 创立带有服务端的应用程序。
前言
通过本教程您将理解到:
- 应用 LeanCloud 作为收费数据库
- 应用 Next.js 开发一个蕴含前后端的利用
- 将利用公布到 Vercel
- 应用 Tailwind 轻松设置款式
咱们将创立一个用于影视剧打分利用,我将它部署在 rec.zehao.me,残缺源码我放在 2eha0/records
创立 Next.js 利用
应用 Next.js 官网模板创立我的项目
& npx create-next-app --example with-tailwindcss my-app
该指标曾经为您配置好以下内容:
- Next.js 最新版本
- TypeScript
- Tailwind CSS & 主动去除未应用的类名
- Next.js API 路由示例
创立前端组件
当初咱们能够开始创立组件了,pages/index.tsx
是利用的入口文件,咱们先来批改整体布局
// pages/index.tsx
import type {NextPage} from 'next'
import Head from 'next/head'
const Home: NextPage = () => {
return (<div className='mx-[3.5rem] min-w-[15rem] max-w-full sm:mx-auto sm:w-[30rem] font-sans'>
<Head>
<title> 我看过的 </title>
<meta name="viewport" content="width=device-width" />
<link rel="icon" href="/favicon.ico" />
</Head>
<h1 className='text-slate-300 flex justify-between items-center text-xl sm:text-5xl my-8 sm:my-20'>
<span> 我看过的 </span>
<span className='text-xs sm:text-xl'> 电影 / 动漫 / 剧 / 书 </span>
</h1>
</div>
)
}
export default Home
接下来,咱们须要为利用增加一个卡片组件,用于显示影视作品的信息,新建 components/card.tsx
文件
// components/card.tsx
import Image from 'next/image'
export const Card: React.FC<Props> = (props) => {
return (<section className='relative before:content-[""] before:border-l-2 before:absolute before:inset-y-0 before:-left-9 before:translate-x-[0.44em] pb-10 first:before:top-1 last:before:bottom-10'>
<p className='text-slate-400 text-xs mb-2 sm:text-base sm:mb-3 relative'>
2022/04/02
<i className='absolute w-4 h-4 rounded-full bg-slate-200 -left-9 top-1/2 translate-y-[-50%]' />
</p>
<div className="flex items-start">
<div className="flex-1 mr-2">
<p className='text-md mb-2 sm:text-2xl sm:mb-3 leading-6 text-slate-900'>
鬼灭之刃
<span className='text-slate-400'>(2019)</span>
</p>
<p className='text-xs sm:text-base text-slate-700'>
<span className='text-slate-400'> 评分:</span>
<big className='font-bold text-blue-500'>🤔 还行 </big>
</p>
<p className='text-xs sm:text-base text-slate-700'>
<span className='text-slate-400'> 分类:</span>
动漫
</p>
<div className="bg-white text-xs text-slate-500 leading-2 mt-4 sm:text-base">
老套的降级打怪式剧情,但动画制作的品质还不错,适宜下饭
</div>
</div>
<div className='flex-none w-1/6 rounded-md sm:w-[5rem] sm:rounded-xl overflow-hidden bg-slate-100 relative aspect-[85/113]'>
<Image
src='https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2551222097.webp'
layout='fill'
objectFit="cover"
alt='鬼灭之刃'
className="hover:opacity-75 duration-300 ease-in-out"
/>
</div>
</div>
</section>
)
}
图片咱们应用了 next/image
组件,咱们须要批改一下 next.config.js
文件,增加图片域名配置
// next.config.js
module.exports = {
reactStrictMode: true,
images: {
domains: [
'img1.doubanio.com',
'img2.doubanio.com',
'img3.doubanio.com',
'img9.doubanio.com',
],
},
}
而后咱们能够增加 <Card />
组件到 pages/index.tsx
中,看一下成果
// pages/index.tsx
import type {NextPage} from 'next'
import Head from 'next/head'
import {Card} from '../components/card'
const Home: NextPage = () => {
return (<div className='mx-[3.5rem] min-w-[15rem] max-w-full sm:mx-auto sm:w-[30rem] font-sans'>
<Head>
<title> 我看过的 </title>
<meta name="viewport" content="width=device-width" />
<link rel="icon" href="/favicon.ico" />
</Head>
<h1 className='text-slate-300 flex justify-between items-center text-xl sm:text-5xl my-8 sm:my-20'>
<span> 我看过的 </span>
<span className='text-xs sm:text-xl'> 电影 / 动漫 / 剧 / 书 </span>
</h1>
<div>
<Card />
<Card />
<Card />
</div>
</div>
)
}
export default Home
至此利用的外观曾经初见雏形了,接下来咱们为 Card
增加一些 props
,首先咱们来定义 props
的类型,咱们在根目录下新建一个 types.ts
文件
// types.ts
export type Record = {
date: string
title: string
score: 1 | 2 | 3 | 4 | 5
comment?: string
year: number
img: string
type: 'movie' | 'tv' | 'anime' | 'book'
}
之所以放在根目录,是因为等一下创立 API 时也会用到这个类型
接下来咱们批改一下 Card
组件,将数据局部替换成 props
// components/card.tsx
import Image from 'next/image'
import {Record} from '../types'
type Props = Record
const Score: React.FC<Pick<Props, 'score'>> = ({score}) => {switch (score) {
case 1:
return <big className='font-bold text-black-500'>😡 不看也罢 </big>
case 2:
return <big className='font-bold text-green-500'>🥱 无聊 </big>
case 3:
return <big className='font-bold text-blue-500'>🤔 还行 </big>
case 4:
return <big className='font-bold text-violet-500'>🤩 值得一看 </big>
case 5:
return <big className='font-bold text-orange-500'>💯 神作!</big>
}
}
const renderType = (type: Props['type']) => {
const typeMap = {
movie: '电影',
tv: '剧',
book: '书',
anime: '动漫',
}
return typeMap[type] ?? '未知'
}
export const Card: React.FC<Props> = (props) => {
return (<section className='relative before:content-[""] before:border-l-2 before:absolute before:inset-y-0 before:-left-9 before:translate-x-[0.44em] pb-10 first:before:top-1 last:before:bottom-10'>
<p className='text-slate-400 text-xs mb-2 sm:text-base sm:mb-3 relative'>
{new Date(props.date).toLocaleDateString()}
<i className='absolute w-4 h-4 rounded-full bg-slate-200 -left-9 top-1/2 translate-y-[-50%]' />
</p>
<div className="flex items-start">
<div className="flex-1 mr-2">
<p className='text-md mb-2 sm:text-2xl sm:mb-3 leading-6 text-slate-900'>
{props.title}
<span className='text-slate-400'>({props.year})</span>
</p>
<p className='text-xs sm:text-base text-slate-700'>
<span className='text-slate-400'> 评分:</span>
<Score score={props.score} />
</p>
<p className='text-xs sm:text-base text-slate-700'>
<span className='text-slate-400'> 分类:</span>
{renderType(props.type) }
</p>
<div className="bg-white text-xs text-slate-500 leading-2 mt-4 sm:text-base">
{props.comment}
</div>
</div>
<div className='flex-none w-1/6 rounded-md sm:w-[5rem] sm:rounded-xl overflow-hidden bg-slate-100 relative aspect-[85/113]'>
<Image
src={props.img}
layout='fill'
objectFit="cover"
alt={props.title}
className="hover:opacity-75 duration-300 ease-in-out"
/>
</div>
</div>
</section>
)
}
设置 LeanCloud Storage
LeanCloud 是一个 BaaS(Backend as a Service)^Backend as a Service: [后端即服务] 平台,倡议注册国际版 LeanCloud,可免实名认证
首先,咱们须要在 Data Storage 中创立一个 Class
- 将 Class 命名为
Records
- 增加
img
、title
、type
、comment
和type
字段,它们的类型都是String
- 增加
year
、score
字段,将他们的类型设置为Number
创立读取数据 API
当初咱们来创立一个 API 用于读取 LeanCloud 中的数据
首先咱们须要装置 LeanCloud JS SDK
$ npm install leancloud-storage --save
而后咱们须要将 LeanCloud 的配置信息增加到 .env.local
中,配置信息能够在 “Settings” -> “App keys” 中找到
LEANCLOUD_APP_ID="{replace-your-app-id}"
LEANCLOUD_APP_KEY="{replace-to-your-app-key}"
LEANCLOUD_SERVER_URL="{replace-to-your-server-url}"
新建 pages/api/records.ts
// pages/api/records.ts
import AV from 'leancloud-storage'
import {Record} from '../../types'
import type {NextApiRequest, NextApiResponse} from 'next'
export default async function handler(
_req: NextApiRequest,
res: NextApiResponse<Record[]>) {
try {
const {
LEANCLOUD_APP_ID: appId,
LEANCLOUD_APP_KEY: appKey,
LEANCLOUD_SERVER_URL: serverURL,
} = process.env
if (!appId || !appKey || !serverURL) {res.status(500).json({error: 'Missing Leancloud config'} as any)
return
}
AV.init({appId, appKey, serverURL})
const query = new AV.Query('Record')
const data = await query.find()
const records: Record[] = data.reverse().map(x => {const json = x.toJSON()
return {
date: json.createdAt,
title: json.title,
score: json.score,
comment: json.comment,
year: json.year,
img: json.img,
type: json.type,
}
})
res.status(200).json(records)
} catch (e: any) {res.status(500).json(e)
}
}
接着咱们批改一下 pages/index.tsx
,从 /api/records
接口获取数据
// pages/index.tsx
import type {NextPage} from 'next'
import Head from 'next/head'
import {useEffect, useState} from 'react'
import {Card} from '../components/card'
import {Record} from '../types'
const Home: NextPage = () => {const [ records, setRecords] = useState<Record[] | null>(null)
useEffect(() => {fetch('/api/records')
.then(res => res.json())
.then(setRecords)
}, [])
const renderCards = () => {if (!records) {return null}
return records.map(x => <Card key={ `${x.date}${x.title}${x.year}` } {...x} />)
}
return (<div className='mx-[3.5rem] min-w-[15rem] max-w-full sm:mx-auto sm:w-[30rem] font-sans'>
<Head>
<title> 我看过的 </title>
<meta name="viewport" content="width=device-width" />
<link rel="icon" href="/favicon.ico" />
</Head>
<h1 className='text-slate-300 flex justify-between items-center text-xl sm:text-5xl my-8 sm:my-20'>
<span> 我看过的 </span>
<span className='text-xs sm:text-xl'> 电影 / 动漫 / 剧 / 书 </span>
</h1>
<div>
{renderCards() }
</div>
</div>
)
}
export default Home
部署到 Vercel
咱们的利用曾经能够在本地运行了,下一步让咱们把它部署到 Vercel 上。
- 将咱们的代码提交到 git 仓库(如 Github、GitLab、BitBucket)
- 将 Next.js 我的项目导入 Vercel
- 在导入期间设置环境变量
- 点击“Deploy”
Vercel 将自动检测您正在应用 Next.js 并为您的部署启用正确的设置。最初,您的应用程序部署在相似 xxx.vercel.app 的 URL 上。
增加数据
当初咱们的利用曾经运行在公网上了,咱们能够在 LeanCloud 上尝试增加几条数据,而后刷新页面看看是否可能失常显示。
总结
在本教程中,咱们可能创立一个 Next.js 应用程序,通过 Tailwind CSS 丑化界面,显示从 LeanCloud 动静获取的数据列表。
- 查看源码
- 查看演示
本文转载自我的博客 https://www.zehao.me/full-sta…