TypeScript学习笔记

鉴于学习Web,不得不学习Javascript,但是还是学习TypeScript更有性价比,Typescript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准,并且最近微软也宣布用Go语言重写Typescript,速度提升10倍左右,更要学了。

一、基础知识

1、基础语法

一个Typescript程序有以下模块

  • 模块
  • 函数
  • 变量
  • 语句和表达式
  • 注释

Typescript和Javascript的最大区别就是多了变量的类型声明

(1)变量声明

首先了解几个变量声明函数

语法

let age: number = 25;
const pi: number = 3.14;

(2)函数声明

基本与Javascript一致,只是需要在函数传递变量处也加上类型声明

function greet(name: string): string {
    return "Hello, " + name;
}

Typescript同样也支持使用箭头来声明函数

const greet = (name: string): string => "Hello, " + name;

(3)类声明

同样与Javascript一致,只需加上类型声明

class Person {
    name: string;
    age: number;
    
    constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
    }
    
    greet() {
    return `Hello, my name is ${this.name}`;
    }
}

(4)接口声明

接口在ts代码中起到一个说明书的作用,声明了一个接口之后,当其他部分代码需要创建一个类时,使用implements (实施)来继承这个接口,那么这个类之内必须包含接口中声明的所有变量和方法。这样可以规范代码。如接口

interface Bookshelf {
  width: number; // 书架的宽度
  height: number; // 书架的高度
  color: string; // 书架的颜色
  addBook(book: string): void; // 一个方法,用来添加书
}

那么我们创建一个类来继承这个接口

class MyBookshelf implements Bookshelf {
  width: number;
  height: number;
  color: string;

  constructor(width: number, height: number, color: string) {
    this.width = width;
    this.height = height;
    this.color = color;
  }

  addBook(book: string) {
    console.log(`Adding book: ${book}`);
  }
}

可以看到该类中包含了接口声明的三个变量和一个方法

(5)模块的导出和导入

Typescript支持模块化编程,已经写好的类、函数、值等可以导出后再其他代码文件复用,现在在person.ts中定义一个Person函数,传入参数name并导出

export class Person {
    constructor(public name: string) {}
}

那么我在另一个代码文件中可以

import { Person } from './person';

可以导入多个模块或函数,使用逗号分隔

(5)泛型

泛型变量可以在定义函数,类的参数时暂时不指定变量类型,而是使用占位符替代,例如

function identity<T>(arg: T): T {
    return arg;
}

这里指定了传入参数以及返回值的类型为泛型,编译器会自动判断变量类型,如果编译器无法判别,那么我们也可以显式指定,在<>中填入具体类型,如

let firstItem = firstElement<number>(myTuple); // 显式指定 T 为 number

2、常用函数

Typescript的常用函数以及其语法基本与PHP一致,就不在多说,只需注意类型注解

二、实际操作

为了能够顺利完全使用Typescript来搭建一个页面,顺带学一下Next.js(无奈😢),一个Nextjs项目目录应该为

my-next-app/
├── app/
│   ├── layout.js        // 根布局
│   ├── page.js          // 首页
│   ├── about/
│   │   ├── layout.js    // /about 的布局
│   │   └── page.js      // /about 页面
│   ├── blog/
│   │   ├── layout.js    // /blog 的布局
│   │   ├── page.js      // /blog 列表页
│   │   └── [slug]/
│   │       └── page.js  // /blog/:slug 详情页
│   └── dashboard/
│       ├── layout.js    // /dashboard 的布局
│       └── page.js      // /dashboard 页面
├── public/
│   ├── logo.png         // 静态资源
│   └── favicon.ico      // 网站图标
├── node_modules/        // 项目依赖
├── package.json         // 项目配置文件
├── next.config.js       // Next.js 配置文件
└── .next/               // 构建输出目录

首先创建一个Nextjs项目

npx create-next-app@latest my-next-app

然后

npm run dev

启动成功,我们可以直接在app文件夹下直接创建新文件夹,文件夹的名称将对应其路径,若是路径下还有子文件夹,那么子文件夹的路径也可用,我们同样来写一个留言板界面,首先写后端,逻辑是

GET 请求

  • 检查public/messages目录是否存在。
  • 如果存在,读取目录下所有.txt文件,提取文件名和内容。
  • 返回留言列表的 JSON 数据。

POST 请求

  • 解析请求体中的留言内容。
  • 创建public/messages目录(如果不存在)。
  • 生成带时间戳的文件名,将留言内容写入文件。
  • 返回成功或失败的 JSON 响应。
import { NextResponse } from 'next/server';
import fs from 'fs/promises';
import path from 'path';

export async function GET() {
  try {
    const dirPath = path.join(process.cwd(), 'public/messages');
    try {
      await fs.access(dirPath);
    } catch {
      return NextResponse.json({ messages: [] });
    }
    const files = await fs.readdir(dirPath);
    
    const messages = await Promise.all(files
      .filter(file => file.endsWith('.txt'))
      .map(async (file) => {
        const content = await fs.readFile(path.join(dirPath, file), 'utf8');
        return { filename: file, content };
      }));

    return NextResponse.json({ messages });
  } catch (error) {
    console.error('读取留言失败:', error);
    return NextResponse.json(
      { success: false, error: '服务器错误' },
      { status: 500 }
    );
  }
}

export async function POST(request: Request) {
  try {
    const { content } = await request.json();
    
    // 创建messages目录(如果不存在)
    const dirPath = path.join(process.cwd(), 'public/messages');
    await fs.mkdir(dirPath, { recursive: true });
    
    // 生成带时间戳的文件名
    const filename = `message_${Date.now()}.txt`;
    const filePath = path.join(dirPath, filename);
    
    // 写入文件内容
    await fs.writeFile(filePath, content, 'utf8');
    
    return NextResponse.json({ success: true });
  } catch (error) {
    console.error('保存留言失败:', error);
    return NextResponse.json(
      { success: false, error: '服务器错误' },
      { status: 500 }
    );
  }
}

用到好几处异步,不太懂,下面是前端代码,主要逻辑为:

用户输入留言并提交后,通过 POST 请求发送留言内容到服务器;提交成功后,清空输入框并重新加载留言列表;页面加载时自动获取并显示所有留言,每条留言显示内容和时间戳。

'use client';
import { useEffect, useState } from 'react';

export default function Home() {
  const [message, setMessage] = useState('');
  const [messages, setMessages] = useState<{filename: string; content: string}[]>([]);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
      const response = await fetch('/api/messages', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({ content: message })
      });
      
      if (response.ok) {
        setMessage('');
        fetchMessages();
      }
    } catch (error) {
      console.error('提交失败:', error);
    }
  };

  const fetchMessages = async () => {
    try {
      const response = await fetch('/api/messages');
      const data = await response.json();
      setMessages(data.messages);
    } catch (error) {
      console.error('获取留言失败:', error);
    }
  };

  useEffect(() => {
    fetchMessages();
  }, []);

  return (
    <div className="container mx-auto p-4 max-w-2xl">
      <h1 className="text-2xl font-bold mb-4">留言板</h1>
      
      <form onSubmit={handleSubmit} className="mb-8">
        <textarea
          value={message}
          onChange={(e) => setMessage(e.target.value)}
          className="w-full p-2 border rounded mb-2"
          rows={4}
          placeholder="输入您的留言..."
          required
        />
        <button
          type="submit"
          className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
        >
          提交留言
        </button>
      </form>

      <div className="space-y-4">
        {messages.map((msg) => (
          <div key={msg.filename} className="p-4 border rounded bg-gray-50">
            <p className="text-gray-800">{msg.content}</p>
            <time className="text-sm text-gray-500 mt-2 block">
              {new Date(parseInt(msg.filename.split('_')[1])).toLocaleString()}
            </time>
          </div>
        ))}
      </div>
    </div>
  );
}

最终效果

CSS是直接使用TailwindCSS,感觉挺方便的

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇