推荐一个神器 --Same.dev 的 AI 工具,可以生成react/vue 代码

1,636 阅读5分钟

以下是针对神器 Same.dev 的详细介绍,结合其通过输入 Bilibili 网址生成 React 网站代码的功能,从开发流程、技术实现到运行效果的完整解析,


一、Same.dev 是什么?

Same.dev 是一个专为前端开发者设计的 UI 组件搜索平台,支持多个前端框架(如 Vue、React、Svelte、Solid 等)。
它可以帮助前端开发者快速查找和复用各种 UI 组件,这对团队的 CRUD 项目来说,能提升组件复用率,减少 UI 设计上的重复劳动。它还可以帮助开发者快速查找、预览和复用开源的 UI 组件,从而提高开发效率,减少重复造轮子。

  • 代码智能生成:解析目标网站的 HTML/CSS/JS 结构,转换为 React 组件化代码。
  • 运行效果预览:提供实时预览功能,展示生成的 React 页面效果。
  • 可扩展性:生成的代码支持自定义修改,适配复杂业务需求。

二、使用 Same.dev开发 Bilibili 风格网站的步骤

1. 输入目标 URL

same.dev网站点这里:

在 Same.dev 的输入框中粘贴 Bilibili 页面 URL(如 https://www.bilibili.com),工具会自动爬取页面结构和样式,并分析其关键组件(导航栏、视频列表、播放器等)。

截屏2025-03-23 21.15.37.png

2. 生成 React 代码

Same.dev 会根据目标网站的布局生成以下内容:

  • 组件化结构:将页面拆分为可复用的 React 组件(如 Header.jsFooter.js)。
  • CSS-in-JS 样式:使用 styled-components 或内联样式实现 Bilibili 的视觉风格。
  • 路由配置:若目标网站是多页面应用,自动生成 react-router 配置。

示例生成的代码片段(基于 Bilibili 首页):

import { Header } from "@/components/Header";
import { HeroCarousel } from "@/components/HeroCarousel";
import { PopularVideos } from "@/components/PopularVideos";
import { ChannelRecommendations } from "@/components/ChannelRecommendations";
import { Footer } from "@/components/Footer";

export default function Home() {
  return (
    <main className="min-h-screen">
      <Header />
      <div className="bili-container">
        <HeroCarousel />
        <PopularVideos />
        <ChannelRecommendations />
      </div>
      <Footer />
    </main>
  );
}

Header.js

"use client";

import { useState } from "react";
import Link from "next/link";
import Image from "next/image";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { MagnifyingGlassIcon } from "@radix-ui/react-icons";

export function Header() {
  const [searchValue, setSearchValue] = useState("");

  // Main navigation items
  const mainNavItems = [
    { name: "首页", href: "/" },
    { name: "动画", href: "/anime" },
    { name: "番剧", href: "/bangumi" },
    { name: "国创", href: "/guochuang" },
    { name: "电影", href: "/movie" },
    { name: "电视剧", href: "/tv" },
    { name: "综艺", href: "/variety" },
    { name: "纪录片", href: "/documentary" },
    { name: "动态", href: "/dynamic" },
    { name: "直播", href: "/live" },
  ];

  // Secondary navigation (the shorter links below main nav)
  const secondaryNavItems = [
    { name: "游戏", href: "/game" },
    { name: "音乐", href: "/music" },
    { name: "舞蹈", href: "/dance" },
    { name: "知识", href: "/knowledge" },
    { name: "科技", href: "/tech" },
    { name: "运动", href: "/sports" },
    { name: "汽车", href: "/car" },
    { name: "生活", href: "/life" },
    { name: "美食", href: "/food" },
    { name: "动物", href: "/animal" },
    { name: "VLOG", href: "/vlog" },
    { name: "鬼畜", href: "/kichiku" },
    { name: "时尚", href: "/fashion" },
    { name: "资讯", href: "/information" },
    { name: "娱乐", href: "/ent" },
    { name: "影视", href: "/cinephile" },
    { name: "更多", href: "/more" },
  ];

  return (
    <header className="fixed top-0 z-50 w-full border-b bg-white shadow-sm">
      <div className="bili-container">
        {/* Top Nav */}
        <div className="flex h-16 items-center justify-between">
          {/* Logo */}
          <div className="flex items-center">
            <Link href="/" className="mr-8">
              <div className="relative h-10 w-28">
                <Image
                  src="https://ext.same-assets.com/2591192343/3166205871.png"
                  alt="Bilibili Logo"
                  fill
                  className="object-contain"
                  priority
                  crossOrigin="anonymous"
                />
              </div>
            </Link>

            {/* Main Navigation */}
            <nav className="hidden md:block">
              <ul className="flex space-x-1">
                {mainNavItems.map((item) => (
                  <li key={item.name}>
                    <Link href={item.href} className="nav-link">
                      {item.name}
                    </Link>
                  </li>
                ))}
              </ul>
            </nav>
          </div>

          {/* Search and User */}
          <div className="flex items-center space-x-4">
            {/* Search */}
            <div className="relative hidden sm:block">
              <div className="relative">
                <Input
                  value={searchValue}
                  onChange={(e) => setSearchValue(e.target.value)}
                  placeholder="搜索"
                  className="h-9 w-56 rounded-full bg-gray-100 pl-10 pr-4 outline-none focus:ring-2 focus:ring-bilipink/50"
                />
                <MagnifyingGlassIcon className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400" />
              </div>
            </div>

            {/* User area */}
            <div className="flex items-center space-x-2">
              <Button variant="ghost" size="sm" className="hidden sm:inline-flex">
                投稿
              </Button>
              <Button variant="ghost" size="sm" className="hidden sm:inline-flex">
                大会员
              </Button>
              <Button variant="ghost" size="sm" className="hidden sm:inline-flex">
                消息
              </Button>
              <Button variant="ghost" size="icon" className="hidden sm:inline-flex">
                <span className="sr-only">Notifications</span>
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  className="h-5 w-5"
                >
                  <path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" />
                  <path d="M10.3 21a1.94 1.94 0 0 0 3.4 0" />
                </svg>
              </Button>
              <Link href="/login">
                <Button size="sm" className="bg-bilipink hover:bg-bilipink/90">
                  登录
                </Button>
              </Link>
            </div>
          </div>
        </div>

        {/* Secondary Navigation */}
        <div className="hidden pb-2 md:block">
          <nav>
            <ul className="flex flex-wrap">
              {secondaryNavItems.map((item) => (
                <li key={item.name}>
                  <Link href={item.href} className="nav-link text-xs">
                    {item.name}
                  </Link>
                </li>
              ))}
            </ul>
          </nav>
        </div>
      </div>
    </header>
  );
}

HeroCarousel.tsx

"use client";

import { useState, useEffect, useRef } from "react";
import Image from "next/image";
import Link from "next/link";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/ui/carousel";
import { type CarouselApi } from "@/components/ui/carousel";

// Carousel data
const carouselItems = [
  {
    id: 1,
    title: "热门动画",
    image: "https://ext.same-assets.com/3697608304/2529357920.webp",
    link: "/anime",
  },
  {
    id: 2,
    title: "番剧推荐",
    image: "https://ext.same-assets.com/2561937933/1726487991.webp",
    link: "/bangumi",
  },
  {
    id: 3,
    title: "游戏区精选",
    image: "https://ext.same-assets.com/3049323316/2786914680.avif",
    link: "/game",
  },
  {
    id: 4,
    title: "综艺专区",
    image: "https://ext.same-assets.com/1451989687/2722035463.avif",
    link: "/variety",
  },
  {
    id: 5,
    title: "知识区推荐",
    image: "https://ext.same-assets.com/4218359082/376622656.avif",
    link: "/knowledge",
  },
];

export function HeroCarousel() {
  const [api, setApi] = useState<CarouselApi>();
  const [current, setCurrent] = useState(0);

  useEffect(() => {
    if (!api) {
      return;
    }

    const onSelect = () => {
      setCurrent(api.selectedScrollSnap());
    };

    api.on("select", onSelect);
    return () => {
      api.off("select", onSelect);
    };
  }, [api]);

  // Auto-rotate carousel
  useEffect(() => {
    if (!api) return;

    const interval = setInterval(() => {
      api.scrollNext();
    }, 5000);

    return () => clearInterval(interval);
  }, [api]);

  return (
    <div className="relative mt-24 rounded-lg shadow-sm">
      <Carousel className="w-full" setApi={setApi}>
        <CarouselContent>
          {carouselItems.map((item) => (
            <CarouselItem key={item.id}>
              <Link href={item.link}>
                <div className="relative aspect-[16/6] w-full overflow-hidden rounded-lg">
                  <Image
                    src={item.image}
                    alt={item.title}
                    fill
                    className="object-cover transition-transform duration-500 hover:scale-105"
                    priority
                    crossOrigin="anonymous"
                  />
                  <div className="absolute bottom-0 w-full bg-gradient-to-t from-black/70 to-transparent p-4 text-white">
                    <h3 className="text-lg font-semibold">{item.title}</h3>
                  </div>
                </div>
              </Link>
            </CarouselItem>
          ))}
        </CarouselContent>
        <CarouselPrevious className="absolute left-2 top-1/2 -translate-y-1/2" />
        <CarouselNext className="absolute right-2 top-1/2 -translate-y-1/2" />
      </Carousel>

      {/* Carousel indicators */}
      <div className="absolute bottom-2 left-1/2 flex -translate-x-1/2 space-x-2">
        {carouselItems.map((_, index) => (
          <button
            key={index}
            className={`h-2 w-2 rounded-full ${
              index === current ? "bg-white" : "bg-white/50"
            }`}
            onClick={() => api?.scrollTo(index)}
          />
        ))}
      </div>
    </div>
  );
}

3. 本地运行与调试

生成的项目代码支持一键下载并运行:

npm install
npm start

工具会启动本地服务器(默认 http://localhost:3000),实时展示与 Bilibili 高度相似的页面效果。

截屏2025-03-23 21.05.05.png

三、技术实现原理

1. 页面解析与组件映射

  • DOM 结构分析:使用类似 cheerio 的库解析目标网站的 HTML,识别重复结构和关键节点(如 .video-list)。
  • 样式提取:通过 CSS 选择器提取样式规则,转换为 React 支持的 CSS Modules 或 styled-components

2. 跨平台适配

  • 响应式布局:自动生成媒体查询代码,适配移动端和 PC 端。
  • 第三方库集成:集成 axios 处理 API 请求、react-player 实现视频播放功能。

3. 代码优化

  • 虚拟 DOM 优化:生成的代码遵循 React 最佳实践,减少不必要的渲染。
  • 状态管理:若页面涉及复杂交互(如用户登录),自动引入 ReduxContext API

四、Same.dev 的独特优势

  1. 开发效率提升
    • 节省 70% 的 UI 开发时间,尤其适合快速原型设计和竞品复刻。
  2. 学习价值
    • 生成的代码包含注释和规范,帮助新手学习 React 和现代前端工程化实践。
  3. 可扩展性强
    • 支持接入自定义 API、添加动画效果(如 framer-motion),或集成 UI 库(如 Ant Design)。

五、运行效果对比

功能模块Bilibili 原版Same.dev 生成版
首页导航栏✔️✔️ (支持路由跳转)
视频播放器✔️✔️ (基于 react-player)
弹幕功能✔️⚠️ 需手动集成
用户登录✔️✖️ 需自行开发

六、适用场景与局限性

适用场景

  • 快速原型设计:1 小时内复刻竞品核心页面。
  • 教学演示:展示 React 组件化开发流程。

局限性

  • 动态功能依赖手动开发:如用户系统、支付功能需自行实现。
  • 复杂动画支持有限:需结合 GSAPThree.js 增强效果。

七、总结

Same.dev 通过智能解析和代码生成技术,大幅降低了 React 开发门槛,尤其适合需要快速实现 UI 复刻的场景。开发者可基于生成的代码进一步优化功能,或结合 Create React AppWebpack 构建完整应用。

扩展阅读

通过 Same.dev,即使新手也能快速入门 React 开发,体验“输入即生成”的高效工作流! 🚀


:本文代码示例和功能描述基于 Same.dev 公开文档及测试结果,实际效果可能因版本更新有所差异。